diff --git a/Assets/DefaultPrefabObjects.asset b/Assets/DefaultPrefabObjects.asset
new file mode 100644
index 00000000..ec9afc82
--- /dev/null
+++ b/Assets/DefaultPrefabObjects.asset
@@ -0,0 +1,27 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 0}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 3ad70174b079c2f4ebc7931d3dd1af6f, type: 3}
+ m_Name: DefaultPrefabObjects
+ m_EditorClassIdentifier: FishNet.Runtime::FishNet.Managing.Object.DefaultPrefabObjects
+ _prefabs:
+ - {fileID: 4512293259955182956, guid: fe2b65b02f0484b41aa8cfa9fbbb0e1d, type: 3}
+ - {fileID: 4512293259955182956, guid: 35639798ad77fc145871588b25d66259, type: 3}
+ - {fileID: 4512293259955182956, guid: 0d6d0f48b03b17f49a6340103cd9b9d0, type: 3}
+ - {fileID: 8475222101369129519, guid: 8cf33e8e99a9b0c4c8f29ff725650de6, type: 3}
+ - {fileID: 4512293259955182956, guid: dafef736ca1ae384e9a19eb672843563, type: 3}
+ - {fileID: 201277550, guid: 5b712878ecece354ba4ffb026c0a221c, type: 3}
+ - {fileID: 4512293259955182956, guid: b8017cef39731ba439c70fecc09488e3, type: 3}
+ - {fileID: 201277550, guid: 26a567abbe21227428f5c3d309d1d73c, type: 3}
+ - {fileID: 4512293259955182956, guid: 44611030e61220d42ab7c37ba3c0ea92, type: 3}
+ - {fileID: 8192566354860284824, guid: 6331b3542e64a564c81bc39cedf70c8d, type: 3}
+ - {fileID: 4512293259955182956, guid: f32d4c19de900e64cb73cedcb8ba6f70, type: 3}
+ - {fileID: 611616139817875448, guid: bf5f023b4017a5e41a9815ec5745df3d, type: 3}
diff --git a/Assets/DefaultPrefabObjects.asset.meta b/Assets/DefaultPrefabObjects.asset.meta
new file mode 100644
index 00000000..0fc68651
--- /dev/null
+++ b/Assets/DefaultPrefabObjects.asset.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 84148460c5f94a24282a444e7d59caa0
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 11400000
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Depth-Based Pixelator.meta b/Assets/Depth-Based Pixelator.meta
new file mode 100644
index 00000000..1e5b398b
--- /dev/null
+++ b/Assets/Depth-Based Pixelator.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 6bd4ec969add5234a9d986e113201909
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Depth-Based Pixelator/Demo.meta b/Assets/Depth-Based Pixelator/Demo.meta
new file mode 100644
index 00000000..9b1ecdef
--- /dev/null
+++ b/Assets/Depth-Based Pixelator/Demo.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c82f6d991909cec4d89c10cc9843d272
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Depth-Based Pixelator/Demo/Materials.meta b/Assets/Depth-Based Pixelator/Demo/Materials.meta
new file mode 100644
index 00000000..b0df44bc
--- /dev/null
+++ b/Assets/Depth-Based Pixelator/Demo/Materials.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 3285be480b55bcc41af2063e1d870bc1
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Depth-Based Pixelator/Demo/Models.meta b/Assets/Depth-Based Pixelator/Demo/Models.meta
new file mode 100644
index 00000000..3ffa9868
--- /dev/null
+++ b/Assets/Depth-Based Pixelator/Demo/Models.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 36891dc9b6bef9042abe878169ca7447
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Depth-Based Pixelator/Demo/Prefabs.meta b/Assets/Depth-Based Pixelator/Demo/Prefabs.meta
new file mode 100644
index 00000000..388caec3
--- /dev/null
+++ b/Assets/Depth-Based Pixelator/Demo/Prefabs.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 45690ad9e15981946be65f9548d8dd09
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Depth-Based Pixelator/Demo/Scene.meta b/Assets/Depth-Based Pixelator/Demo/Scene.meta
new file mode 100644
index 00000000..f17abf96
--- /dev/null
+++ b/Assets/Depth-Based Pixelator/Demo/Scene.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 603ed2849a33ba0458483c701165b144
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Depth-Based Pixelator/Demo/Scripts.meta b/Assets/Depth-Based Pixelator/Demo/Scripts.meta
new file mode 100644
index 00000000..8ff13592
--- /dev/null
+++ b/Assets/Depth-Based Pixelator/Demo/Scripts.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: ff34b50cc44bc6543b46be01a211d5b7
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Depth-Based Pixelator/Demo/Skyboxes.meta b/Assets/Depth-Based Pixelator/Demo/Skyboxes.meta
new file mode 100644
index 00000000..0863c59d
--- /dev/null
+++ b/Assets/Depth-Based Pixelator/Demo/Skyboxes.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 361df54f72bfa4c45afb507271efc82c
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Depth-Based Pixelator/Editor.meta b/Assets/Depth-Based Pixelator/Editor.meta
new file mode 100644
index 00000000..c36affd0
--- /dev/null
+++ b/Assets/Depth-Based Pixelator/Editor.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: e71e3609ff417784b81b4f5ae74064bd
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Depth-Based Pixelator/Materials.meta b/Assets/Depth-Based Pixelator/Materials.meta
new file mode 100644
index 00000000..e76e8658
--- /dev/null
+++ b/Assets/Depth-Based Pixelator/Materials.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 196c5002b4773e943baf0f897f1ca573
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Depth-Based Pixelator/RenderFeatures.meta b/Assets/Depth-Based Pixelator/RenderFeatures.meta
new file mode 100644
index 00000000..3497336c
--- /dev/null
+++ b/Assets/Depth-Based Pixelator/RenderFeatures.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: aed2145cbbd99134c9f1556356440612
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Depth-Based Pixelator/Shaders.meta b/Assets/Depth-Based Pixelator/Shaders.meta
new file mode 100644
index 00000000..881f29ed
--- /dev/null
+++ b/Assets/Depth-Based Pixelator/Shaders.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 56fd714f9ff70974b953ab8b676bd2ad
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/FishNet.meta b/Assets/FishNet.meta
new file mode 100644
index 00000000..5e5a2280
--- /dev/null
+++ b/Assets/FishNet.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: f1525dbf8ebd59e438b504fa19c4fd6c
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/FishNet/CodeGenerating.meta b/Assets/FishNet/CodeGenerating.meta
new file mode 100644
index 00000000..e7902b43
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: a03c3ea914b8ed649a14606e1430e404
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/FishNet/CodeGenerating/Extension.meta b/Assets/FishNet/CodeGenerating/Extension.meta
new file mode 100644
index 00000000..20b1a5c8
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Extension.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c2e223f21744b544bbb7e93020199efb
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/FishNet/CodeGenerating/Extension/FieldDefinitionExtensions.cs b/Assets/FishNet/CodeGenerating/Extension/FieldDefinitionExtensions.cs
new file mode 100644
index 00000000..0bac669e
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Extension/FieldDefinitionExtensions.cs
@@ -0,0 +1,16 @@
+using MonoFN.Cecil;
+
+namespace FishNet.CodeGenerating.Helping.Extension
+{
+ internal static class FieldDefinitionExtensions
+ {
+ ///
+ /// Makes a FieldDefinition generic if it has generic parameters.
+ ///
+ public static FieldReference TryMakeGenericInstance(this FieldDefinition fd, CodegenSession session)
+ {
+ FieldReference fr = session.ImportReference(fd);
+ return fr.TryMakeGenericInstance();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/FishNet/CodeGenerating/Extension/FieldDefinitionExtensions.cs.meta b/Assets/FishNet/CodeGenerating/Extension/FieldDefinitionExtensions.cs.meta
new file mode 100644
index 00000000..829f7aff
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Extension/FieldDefinitionExtensions.cs.meta
@@ -0,0 +1,18 @@
+fileFormatVersion: 2
+guid: de84fa9739ed55945b58147a773e1740
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 207815
+ packageName: 'FishNet: Networking Evolved'
+ packageVersion: 4.6.22R
+ assetPath: Assets/FishNet/CodeGenerating/Extension/FieldDefinitionExtensions.cs
+ uploadId: 866910
diff --git a/Assets/FishNet/CodeGenerating/Extension/FieldReferenceExtensions.cs b/Assets/FishNet/CodeGenerating/Extension/FieldReferenceExtensions.cs
new file mode 100644
index 00000000..baeea3d3
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Extension/FieldReferenceExtensions.cs
@@ -0,0 +1,35 @@
+using FishNet.CodeGenerating.Extension;
+using MonoFN.Cecil;
+
+namespace FishNet.CodeGenerating.Helping.Extension
+{
+ internal static class FieldReferenceExtensions
+ {
+ ///
+ /// Gets a Resolve favoring cached results first.
+ ///
+ internal static FieldDefinition CachedResolve(this FieldReference fieldRef, CodegenSession session)
+ {
+ return session.GetClass().GetFieldReferenceResolve(fieldRef);
+ }
+
+ ///
+ /// Makes a FieldReference generic if it has generic parameters.
+ ///
+ public static FieldReference TryMakeGenericInstance(this FieldReference fr)
+ {
+ TypeReference declaringTr = fr.DeclaringType;
+
+ if (declaringTr.HasGenericParameters)
+ {
+ GenericInstanceType git = declaringTr.MakeGenericInstanceType();
+ FieldReference result = new(fr.Name, fr.FieldType, git);
+ return result;
+ }
+ else
+ {
+ return fr;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/FishNet/CodeGenerating/Extension/FieldReferenceExtensions.cs.meta b/Assets/FishNet/CodeGenerating/Extension/FieldReferenceExtensions.cs.meta
new file mode 100644
index 00000000..bc6878ad
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Extension/FieldReferenceExtensions.cs.meta
@@ -0,0 +1,18 @@
+fileFormatVersion: 2
+guid: 6d983ebd0c9e1b745902030c2f7a8e99
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 207815
+ packageName: 'FishNet: Networking Evolved'
+ packageVersion: 4.6.22R
+ assetPath: Assets/FishNet/CodeGenerating/Extension/FieldReferenceExtensions.cs
+ uploadId: 866910
diff --git a/Assets/FishNet/CodeGenerating/Extension/ILProcessorExtensions.cs b/Assets/FishNet/CodeGenerating/Extension/ILProcessorExtensions.cs
new file mode 100644
index 00000000..3fbebd1a
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Extension/ILProcessorExtensions.cs
@@ -0,0 +1,25 @@
+using FishNet.CodeGenerating.Helping.Extension;
+using MonoFN.Cecil;
+using MonoFN.Cecil.Cil;
+
+namespace FishNet.CodeGenerating.Extension
+{
+ internal static class ILProcessorExtensions
+ {
+ ///
+ /// Creates a variable type within the body and returns it's VariableDef.
+ ///
+ internal static VariableDefinition CreateVariable(this ILProcessor processor, CodegenSession session, System.Type variableType)
+ {
+ return processor.Body.Method.CreateVariable(session, variableType);
+ }
+
+ ///
+ /// Creates a variable type within the body and returns it's VariableDef.
+ ///
+ internal static VariableDefinition CreateVariable(this ILProcessor processor, CodegenSession session, TypeReference variableTr)
+ {
+ return processor.Body.Method.CreateVariable(variableTr);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/FishNet/CodeGenerating/Extension/ILProcessorExtensions.cs.meta b/Assets/FishNet/CodeGenerating/Extension/ILProcessorExtensions.cs.meta
new file mode 100644
index 00000000..78221a62
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Extension/ILProcessorExtensions.cs.meta
@@ -0,0 +1,18 @@
+fileFormatVersion: 2
+guid: 127d8312da53b3e49ba9e3e4c6348857
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 207815
+ packageName: 'FishNet: Networking Evolved'
+ packageVersion: 4.6.22R
+ assetPath: Assets/FishNet/CodeGenerating/Extension/ILProcessorExtensions.cs
+ uploadId: 866910
diff --git a/Assets/FishNet/CodeGenerating/Extension/MethodDefinitionExtensions.cs b/Assets/FishNet/CodeGenerating/Extension/MethodDefinitionExtensions.cs
new file mode 100644
index 00000000..1015c038
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Extension/MethodDefinitionExtensions.cs
@@ -0,0 +1,234 @@
+using FishNet.CodeGenerating.Helping;
+using FishNet.CodeGenerating.Helping.Extension;
+using MonoFN.Cecil;
+using MonoFN.Cecil.Cil;
+using System.Collections.Generic;
+
+namespace FishNet.CodeGenerating.Extension
+{
+ internal static class MethodDefinitionExtensions
+ {
+ public const MethodAttributes PUBLIC_VIRTUAL_ATTRIBUTES = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig;
+ public const MethodAttributes PROTECTED_VIRTUAL_ATTRIBUTES = MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig;
+
+ ///
+ /// Returns a custom attribute.
+ ///
+ public static CustomAttribute GetCustomAttribute(this MethodDefinition md, string attributeFullName)
+ {
+ if (md == null)
+ return null;
+
+ foreach (CustomAttribute item in md.CustomAttributes)
+ {
+ if (item.AttributeType.FullName == attributeFullName)
+ return item;
+ }
+
+ // Not found.
+ return null;
+ }
+
+ ///
+ /// Clears the method content and returns ret.
+ ///
+ internal static void ClearMethodWithRet(this MethodDefinition md, CodegenSession session, ModuleDefinition importReturnModule = null)
+ {
+ md.Body.Instructions.Clear();
+ ILProcessor processor = md.Body.GetILProcessor();
+ processor.Add(session.GetClass().CreateRetDefault(md, importReturnModule));
+ }
+
+ ///
+ /// Returns the ParameterDefinition index from end of parameters.
+ ///
+ ///
+ ///
+ ///
+ internal static ParameterDefinition GetEndParameter(this MethodDefinition md, int index)
+ {
+ // Not enough parameters.
+ if (md.Parameters.Count < index + 1)
+ return null;
+
+ return md.Parameters[md.Parameters.Count - (index + 1)];
+ }
+
+ ///
+ /// Creates a variable type within the body and returns it's VariableDef.
+ ///
+ internal static VariableDefinition CreateVariable(this MethodDefinition methodDef, TypeReference variableTypeRef)
+ {
+ VariableDefinition variableDef = new(variableTypeRef);
+ methodDef.Body.Variables.Add(variableDef);
+ return variableDef;
+ }
+
+ ///
+ /// Creates a variable type within the body and returns it's VariableDef.
+ ///
+ internal static VariableDefinition CreateVariable(this MethodDefinition methodDef, CodegenSession session, System.Type variableType)
+ {
+ return CreateVariable(methodDef, session.GetClass().GetTypeReference(variableType));
+ }
+
+ ///
+ /// Returns the proper OpCode to use for call methods.
+ ///
+ public static OpCode GetCallOpCode(this MethodDefinition md)
+ {
+ if (md.Attributes.HasFlag(MethodAttributes.Virtual))
+ return OpCodes.Callvirt;
+ else
+ return OpCodes.Call;
+ }
+
+ ///
+ /// Returns the proper OpCode to use for call methods.
+ ///
+ public static OpCode GetCallOpCode(this MethodReference mr, CodegenSession session)
+ {
+ return mr.CachedResolve(session).GetCallOpCode();
+ }
+
+ ///
+ /// Adds a parameter and returns added parameters.
+ ///
+ public static ParameterDefinition CreateParameter(this MethodDefinition thisMd, CodegenSession session, ParameterAttributes attr, System.Type type)
+ {
+ TypeReference parameterTypeRef = session.ImportReference(type);
+ ParameterDefinition pd = new($"p{thisMd.Parameters.Count}", attr, parameterTypeRef);
+ thisMd.Parameters.Add(pd);
+ return pd;
+ }
+
+ ///
+ /// Adds otherMd parameters to thisMd and returns added parameters.
+ ///
+ public static List CreateParameters(this MethodDefinition thisMd, CodegenSession session, MethodDefinition otherMd)
+ {
+ List results = new();
+
+ foreach (ParameterDefinition pd in otherMd.Parameters)
+ {
+ session.ImportReference(pd.ParameterType.CachedResolve(session));
+ int currentCount = thisMd.Parameters.Count;
+ string name = pd.Name + currentCount;
+ ParameterDefinition parameterDef = new(name, pd.Attributes, pd.ParameterType);
+ // Set any default values.
+ parameterDef.Constant = pd.Constant;
+ parameterDef.IsReturnValue = pd.IsReturnValue;
+ parameterDef.IsOut = pd.IsOut;
+ foreach (CustomAttribute item in pd.CustomAttributes)
+ parameterDef.CustomAttributes.Add(item);
+ parameterDef.HasConstant = pd.HasConstant;
+ parameterDef.HasDefault = pd.HasDefault;
+
+ if (parameterDef == null || thisMd.Parameters == null)
+ {
+ session.LogError($"ParameterDefinition or collection is null. Definition null: {parameterDef == null}. Collection null: {thisMd.Parameters == null}.");
+ }
+ else
+ {
+ thisMd.Parameters.Add(parameterDef);
+ results.Add(parameterDef);
+ }
+ }
+
+ return results;
+ }
+
+ ///
+ /// Returns a method reference while considering if declaring type is generic.
+ ///
+ public static MethodReference GetMethodReference(this MethodDefinition md, CodegenSession session)
+ {
+ MethodReference methodRef = session.ImportReference(md);
+
+ // Is generic.
+ if (md.DeclaringType.HasGenericParameters)
+ {
+ GenericInstanceType git = methodRef.DeclaringType.MakeGenericInstanceType();
+ MethodReference result = new(md.Name, md.ReturnType)
+ {
+ HasThis = md.HasThis,
+ ExplicitThis = md.ExplicitThis,
+ DeclaringType = git,
+ CallingConvention = md.CallingConvention
+ };
+ foreach (ParameterDefinition pd in md.Parameters)
+ {
+ session.ImportReference(pd.ParameterType);
+ result.Parameters.Add(pd);
+ }
+ return result;
+ }
+ else
+ {
+ return methodRef;
+ }
+ }
+
+ ///
+ /// Returns a method reference for a generic method.
+ ///
+ public static MethodReference GetMethodReference(this MethodDefinition md, CodegenSession session, TypeReference typeReference)
+ {
+ MethodReference methodRef = session.ImportReference(md);
+ return methodRef.GetMethodReference(session, typeReference);
+ }
+
+ ///
+ /// Removes ret if it exist at the end of the method. Returns if ret was removed.
+ ///
+ internal static bool RemoveEndRet(this MethodDefinition md, CodegenSession session)
+ {
+ int count = md.Body.Instructions.Count;
+ if (count > 0 && md.Body.Instructions[count - 1].OpCode == OpCodes.Ret)
+ {
+ md.Body.Instructions.RemoveAt(count - 1);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// Returns a method reference for a generic method.
+ ///
+ public static MethodReference GetMethodReference(this MethodDefinition md, CodegenSession session, TypeReference[] typeReferences)
+ {
+ MethodReference methodRef = session.ImportReference(md);
+ return methodRef.GetMethodReference(session, typeReferences);
+ }
+
+ public static MethodDefinition CreateCopy(this MethodDefinition copiedMd, CodegenSession session, string nameOverride = null, MethodAttributes? attributesOverride = null)
+ {
+ session.ImportReference(copiedMd.ReturnType);
+
+ MethodAttributes attr = attributesOverride.HasValue ? attributesOverride.Value : copiedMd.Attributes;
+ string name = nameOverride == null ? copiedMd.Name : nameOverride;
+ MethodDefinition result = new(name, attr, copiedMd.ReturnType);
+ foreach (GenericParameter item in copiedMd.GenericParameters)
+ result.GenericParameters.Add(item);
+
+ result.CreateParameters(session, copiedMd);
+ return result;
+ }
+
+ ///
+ /// Makes a method definition public.
+ ///
+ public static void SetPublicAttributes(this MethodDefinition md)
+ {
+ md.Attributes = PUBLIC_VIRTUAL_ATTRIBUTES;
+ }
+
+ public static void SetProtectedAttributes(this MethodDefinition md)
+ {
+ md.Attributes = PROTECTED_VIRTUAL_ATTRIBUTES;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/FishNet/CodeGenerating/Extension/MethodDefinitionExtensions.cs.meta b/Assets/FishNet/CodeGenerating/Extension/MethodDefinitionExtensions.cs.meta
new file mode 100644
index 00000000..cae2422e
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Extension/MethodDefinitionExtensions.cs.meta
@@ -0,0 +1,18 @@
+fileFormatVersion: 2
+guid: 866ed457fe28c3e4b9698d87b9abd709
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 207815
+ packageName: 'FishNet: Networking Evolved'
+ packageVersion: 4.6.22R
+ assetPath: Assets/FishNet/CodeGenerating/Extension/MethodDefinitionExtensions.cs
+ uploadId: 866910
diff --git a/Assets/FishNet/CodeGenerating/Extension/TypeDefinitionExtensions.cs b/Assets/FishNet/CodeGenerating/Extension/TypeDefinitionExtensions.cs
new file mode 100644
index 00000000..cd6d7865
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Extension/TypeDefinitionExtensions.cs
@@ -0,0 +1,301 @@
+using FishNet.CodeGenerating.Helping.Extension;
+using FishNet.Object.Prediction;
+using FishNet.Utility.Performance;
+using MonoFN.Cecil;
+using System.Collections.Generic;
+
+namespace FishNet.CodeGenerating.Extension
+{
+ internal static class TypeDefinitionExtensions
+ {
+ ///
+ /// Returns if a TypeDefinition is nullable.
+ ///
+ public static bool IsNullable(this TypeDefinition td)
+ {
+ return td.Name == typeof(System.Nullable<>).Name;
+ }
+
+ ///
+ /// Finds the first method by a given name.
+ ///
+ ///
+ ///
+ ///
+ internal static MethodDefinition GetMethod(this TypeDefinition typeDef, string methodName)
+ {
+ foreach (MethodDefinition md in typeDef.Methods)
+ {
+ if (md.Name == methodName)
+ return md;
+ }
+
+ return null;
+ }
+
+ public static MethodReference GetMethodReferenceInBase(this TypeDefinition td, CodegenSession session, string methodName)
+ {
+ MethodDefinition baseMd = td.GetMethodDefinitionInBase(session, methodName);
+ if (baseMd == null)
+ return null;
+
+ MethodReference baseMr;
+ TypeReference baseTr = td.BaseType;
+ if (baseTr.CachedResolve(session).HasGenericParameters)
+ {
+ GenericInstanceType git = (GenericInstanceType)baseTr;
+ baseMr = new(baseMd.Name, baseMd.ReturnType, git)
+ {
+ HasThis = baseMd.HasThis,
+ CallingConvention = baseMd.CallingConvention,
+ ExplicitThis = baseMd.ExplicitThis
+ };
+ foreach (ParameterDefinition pd in baseMd.Parameters)
+ {
+ session.ImportReference(pd.ParameterType);
+ baseMr.Parameters.Add(pd);
+ }
+ }
+ else
+ {
+ baseMr = session.ImportReference(baseMd);
+ }
+
+ return baseMr;
+ }
+
+ ///
+ /// Returns a method in the next base class.
+ ///
+ public static MethodDefinition GetMethodDefinitionInBase(this TypeDefinition td, CodegenSession session, string methodName)
+ {
+ if (td.BaseType == null)
+ {
+ session.LogError($"BaseType for {td.FullName} is null.");
+ return null;
+ }
+
+ TypeDefinition baseTd = td.BaseType.CachedResolve(session);
+ return baseTd.GetMethod(methodName);
+ }
+
+ ///
+ /// Returns a method in the next base class.
+ ///
+ public static MethodReference GetMethodReference(this TypeDefinition td, CodegenSession session, string methodName)
+ {
+ MethodDefinition md = td.GetMethod(methodName);
+ // Not found.
+ if (md == null)
+ return null;
+
+ return md.GetMethodReference(session);
+ }
+
+ ///
+ /// Gets a MethodReference or creates one if missing.
+ ///
+ public static MethodReference GetOrCreateMethodReference(this TypeDefinition td, CodegenSession session, string methodName, MethodAttributes attributes, TypeReference returnType, out bool created)
+ {
+ MethodDefinition md = td.GetMethod(methodName);
+ // Not found.
+ if (md == null)
+ {
+ md = new(methodName, attributes, returnType);
+ td.Methods.Add(md);
+ created = true;
+ }
+ else
+ {
+ created = false;
+ }
+
+ return md.GetMethodReference(session);
+ }
+
+ ///
+ /// Gets a MethodDefinition or creates one if missing.
+ ///
+ public static MethodDefinition GetOrCreateMethodDefinition(this TypeDefinition td, CodegenSession session, string methodName, MethodAttributes attributes, TypeReference returnType, out bool created)
+ {
+ MethodDefinition md = td.GetMethod(methodName);
+ //Not found.
+ if (md == null)
+ {
+ md = new(methodName, attributes, returnType);
+ td.Methods.Add(md);
+ created = true;
+ }
+ else
+ {
+ created = false;
+ }
+
+ return md;
+ }
+
+ ///
+ /// Gets a MethodDefinition or creates one if missing.
+ ///
+ public static MethodDefinition GetOrCreateMethodDefinition(this TypeDefinition td, CodegenSession session, string methodName, MethodDefinition methodTemplate, bool copyParameters, out bool created)
+ {
+ MethodDefinition md = td.GetMethod(methodName);
+ //Not found.
+ if (md == null)
+ {
+ TypeReference returnType = session.ImportReference(methodTemplate.ReturnType);
+ md = new(methodName, methodTemplate.Attributes, returnType)
+ {
+ ExplicitThis = methodTemplate.ExplicitThis,
+ AggressiveInlining = methodTemplate.AggressiveInlining,
+ Attributes = methodTemplate.Attributes,
+ CallingConvention = methodTemplate.CallingConvention,
+ HasThis = methodTemplate.HasThis
+ };
+ md.Body.InitLocals = methodTemplate.Body.InitLocals;
+
+ if (copyParameters)
+ {
+ foreach (ParameterDefinition pd in methodTemplate.Parameters)
+ {
+ session.ImportReference(pd.ParameterType.CachedResolve(session));
+ md.Parameters.Add(pd);
+ }
+ }
+
+ foreach (GenericParameter item in methodTemplate.GenericParameters)
+ {
+ session.ImportReference(item);
+ md.GenericParameters.Add(item);
+ }
+
+ td.Methods.Add(md);
+ created = true;
+ }
+ else
+ {
+ created = false;
+ }
+
+ return md;
+ }
+
+ ///
+ /// Returns a method in any inherited classes. The first found method is returned.
+ ///
+ public static MethodDefinition GetMethodDefinitionInAnyBase(this TypeDefinition td, CodegenSession session, string methodName)
+ {
+ while (td != null)
+ {
+ foreach (MethodDefinition md in td.Methods)
+ {
+ if (md.Name == methodName)
+ return md;
+ }
+
+ try
+ {
+ td = td.GetNextBaseTypeDefinition(session);
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ return null;
+ }
+
+ ///
+ /// Returns a TypeDefintiion found in typeDef or up it's hierarchy.
+ ///
+ /// True to check if typeDef equals fullName.
+ ///
+ public static TypeDefinition GetTypeDefinitionInBase(this TypeDefinition typeDef, CodegenSession session, string targetFullName, bool checkTypeDef)
+ {
+ if (typeDef == null)
+ return null;
+ if (!checkTypeDef)
+ typeDef = typeDef.GetNextBaseTypeDefinition(session);
+
+ while (typeDef != null)
+ {
+ if (typeDef.FullName == targetFullName)
+ return typeDef;
+
+ typeDef = typeDef.GetNextBaseTypeDefinition(session);
+ }
+
+ return null;
+ }
+
+ ///
+ /// Returns the next base type.
+ ///
+ public static TypeDefinition GetNextBaseTypeDefinition(this TypeDefinition typeDef, CodegenSession session)
+ {
+ return typeDef.BaseType == null ? null : typeDef.BaseType.CachedResolve(session);
+ }
+
+ ///
+ /// Creates a FieldReference.
+ ///
+ public static FieldReference CreateFieldReference(this FieldDefinition fd, CodegenSession session)
+ {
+ FieldReference fr;
+ TypeDefinition declaringType = fd.DeclaringType;
+ //Is generic.
+ if (declaringType.HasGenericParameters)
+ {
+ GenericInstanceType git = new(declaringType);
+ foreach (GenericParameter item in declaringType.GenericParameters)
+ git.GenericArguments.Add(item);
+ fr = new(fd.Name, fd.FieldType, git);
+ return fr;
+ }
+ //Not generic.
+ else
+ {
+ return session.ImportReference(fd);
+ }
+ }
+
+ ///
+ /// Gets a FieldReference or creates it if missing.
+ ///
+ public static FieldReference GetOrCreateFieldReference(this TypeDefinition td, CodegenSession session, string fieldName, FieldAttributes attributes, TypeReference fieldTypeRef, out bool created)
+ {
+ FieldReference fr = td.GetFieldReference(fieldName, session);
+ if (fr == null)
+ {
+ fr = td.CreateFieldDefinition(session, fieldName, attributes, fieldTypeRef);
+ created = true;
+ }
+ else
+ {
+ created = false;
+ }
+
+ return fr;
+ }
+
+ ///
+ /// Creates a FieldReference.
+ ///
+ public static FieldReference CreateFieldDefinition(this TypeDefinition td, CodegenSession session, string fieldName, FieldAttributes attributes, TypeReference fieldTypeRef)
+ {
+ FieldDefinition fd = new(fieldName, attributes, fieldTypeRef);
+ td.Fields.Add(fd);
+ return fd.CreateFieldReference(session);
+ }
+
+ ///
+ /// Makes a GenericInstanceType.
+ ///
+ public static GenericInstanceType MakeGenericInstanceType(this TypeDefinition self, CodegenSession session)
+ {
+ TypeReference tr = session.ImportReference(self);
+ return tr.MakeGenericInstanceType();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/FishNet/CodeGenerating/Extension/TypeDefinitionExtensions.cs.meta b/Assets/FishNet/CodeGenerating/Extension/TypeDefinitionExtensions.cs.meta
new file mode 100644
index 00000000..5abafbc6
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Extension/TypeDefinitionExtensions.cs.meta
@@ -0,0 +1,18 @@
+fileFormatVersion: 2
+guid: c9f00cf3dc8b90b469c3c9cb8b87fc88
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 207815
+ packageName: 'FishNet: Networking Evolved'
+ packageVersion: 4.6.22R
+ assetPath: Assets/FishNet/CodeGenerating/Extension/TypeDefinitionExtensions.cs
+ uploadId: 866910
diff --git a/Assets/FishNet/CodeGenerating/Extension/TypeReferenceExtensions.cs b/Assets/FishNet/CodeGenerating/Extension/TypeReferenceExtensions.cs
new file mode 100644
index 00000000..a1437bff
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Extension/TypeReferenceExtensions.cs
@@ -0,0 +1,44 @@
+using FishNet.CodeGenerating.Helping;
+using FishNet.CodeGenerating.Helping.Extension;
+using MonoFN.Cecil;
+using UnityEngine;
+
+namespace FishNet.CodeGenerating.Extension
+{
+ internal static class TypeReferenceExtensions
+ {
+ ///
+ /// Returns if a TypeReference is nullable.
+ ///
+ public static bool IsNullable(this TypeReference tr, CodegenSession session)
+ {
+ TypeDefinition td = tr.CachedResolve(session);
+ return td.IsNullable();
+ }
+
+ ///
+ /// Returns the fullname of a TypeReference without <>.
+ ///
+ ///
+ ///
+ public static string GetFullnameWithoutBrackets(this TypeReference tr)
+ {
+ string str = tr.FullName;
+ str = str.Replace("<", "");
+ str = str.Replace(">", "");
+ return str;
+ }
+
+ ///
+ /// Makes a GenericInstanceType.
+ ///
+ public static GenericInstanceType MakeGenericInstanceType(this TypeReference self)
+ {
+ GenericInstanceType instance = new(self);
+ foreach (GenericParameter argument in self.GenericParameters)
+ instance.GenericArguments.Add(argument);
+
+ return instance;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/FishNet/CodeGenerating/Extension/TypeReferenceExtensions.cs.meta b/Assets/FishNet/CodeGenerating/Extension/TypeReferenceExtensions.cs.meta
new file mode 100644
index 00000000..53e5ceac
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Extension/TypeReferenceExtensions.cs.meta
@@ -0,0 +1,18 @@
+fileFormatVersion: 2
+guid: 239b1b10db80c594d93b7ba4ee2c1ec5
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 207815
+ packageName: 'FishNet: Networking Evolved'
+ packageVersion: 4.6.22R
+ assetPath: Assets/FishNet/CodeGenerating/Extension/TypeReferenceExtensions.cs
+ uploadId: 866910
diff --git a/Assets/FishNet/CodeGenerating/FN_README.txt b/Assets/FishNet/CodeGenerating/FN_README.txt
new file mode 100644
index 00000000..3efe3cf7
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/FN_README.txt
@@ -0,0 +1,9 @@
+After updating a custom Cecil to fix conflict with Unity.Burst in 2021 perform the following:
+
+- Open cecil in it's own project; eg: do not place directly in FN.
+- Rename namespace.Mono to namespace.MonoFN.
+- Current project rename strings, "Mono to "MonoFN
+- Replace current project #if INSIDE_ROCKS to #if UNITY_EDITOR
+- Comment out `[assembly: AssemblyTitle ("MonoFN.Cecil.Rocks")]` within rocks\Mono.Cecil.Rocks\AssemblyInfo.cs.
+- Delete obj/bin/tests folders.
+- Copy into FN project.
diff --git a/Assets/FishNet/CodeGenerating/FN_README.txt.meta b/Assets/FishNet/CodeGenerating/FN_README.txt.meta
new file mode 100644
index 00000000..78b0eb79
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/FN_README.txt.meta
@@ -0,0 +1,14 @@
+fileFormatVersion: 2
+guid: 9133eb285bd7f3c4f89f4d7a2a079c6b
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 207815
+ packageName: 'FishNet: Networking Evolved'
+ packageVersion: 4.6.22R
+ assetPath: Assets/FishNet/CodeGenerating/FN_README.txt
+ uploadId: 866910
diff --git a/Assets/FishNet/CodeGenerating/Helpers.meta b/Assets/FishNet/CodeGenerating/Helpers.meta
new file mode 100644
index 00000000..b0764dd0
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Helpers.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: d27bb367daea26d46a8fa5f6ca02865e
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/FishNet/CodeGenerating/Helpers/AttributeHelper.cs b/Assets/FishNet/CodeGenerating/Helpers/AttributeHelper.cs
new file mode 100644
index 00000000..11790eab
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Helpers/AttributeHelper.cs
@@ -0,0 +1,65 @@
+using FishNet.CodeGenerating.Helping.Extension;
+using FishNet.Object;
+using FishNet.Object.Helping;
+using FishNet.Object.Prediction;
+using MonoFN.Cecil;
+
+namespace FishNet.CodeGenerating.Helping
+{
+ internal class AttributeHelper : CodegenBase
+ {
+ #region Reflection references.
+ internal string ReplicateAttribute_FullName;
+ internal string ReconcileAttribute_FullName;
+ private string ServerAttribute_FullName;
+ private string ClientAttribute_FullName;
+ private string ServerRpcAttribute_FullName;
+ private string ObserversRpcAttribute_FullName;
+ private string TargetRpcAttribute_FullName;
+ #endregion
+
+ public override bool ImportReferences()
+ {
+ ServerAttribute_FullName = typeof(ServerAttribute).FullName;
+ ClientAttribute_FullName = typeof(ClientAttribute).FullName;
+ ServerRpcAttribute_FullName = typeof(ServerRpcAttribute).FullName;
+ ObserversRpcAttribute_FullName = typeof(ObserversRpcAttribute).FullName;
+ TargetRpcAttribute_FullName = typeof(TargetRpcAttribute).FullName;
+ ReplicateAttribute_FullName = typeof(ReplicateAttribute).FullName;
+ ReconcileAttribute_FullName = typeof(ReconcileAttribute).FullName;
+ return true;
+ }
+
+ ///
+ /// Returns type of Rpc attributeFullName is for.
+ ///
+ ///
+ ///
+ public RpcType GetRpcAttributeType(CustomAttribute ca)
+ {
+ if (ca.Is(ServerRpcAttribute_FullName))
+ return RpcType.Server;
+ else if (ca.Is(ObserversRpcAttribute_FullName))
+ return RpcType.Observers;
+ else if (ca.Is(TargetRpcAttribute_FullName))
+ return RpcType.Target;
+ else
+ return RpcType.None;
+ }
+
+ ///
+ /// Returns type of Rpc attributeFullName is for.
+ ///
+ ///
+ ///
+ internal QolAttributeType GetQolAttributeType(string attributeFullName)
+ {
+ if (attributeFullName == ServerAttribute_FullName)
+ return QolAttributeType.Server;
+ else if (attributeFullName == ClientAttribute_FullName)
+ return QolAttributeType.Client;
+ else
+ return QolAttributeType.None;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/FishNet/CodeGenerating/Helpers/AttributeHelper.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/AttributeHelper.cs.meta
new file mode 100644
index 00000000..8c6e43c7
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Helpers/AttributeHelper.cs.meta
@@ -0,0 +1,18 @@
+fileFormatVersion: 2
+guid: d32f3dc23b55598429c5cfe6156e6243
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 207815
+ packageName: 'FishNet: Networking Evolved'
+ packageVersion: 4.6.22R
+ assetPath: Assets/FishNet/CodeGenerating/Helpers/AttributeHelper.cs
+ uploadId: 866910
diff --git a/Assets/FishNet/CodeGenerating/Helpers/CodegenSession.cs b/Assets/FishNet/CodeGenerating/Helpers/CodegenSession.cs
new file mode 100644
index 00000000..b9fd5a4f
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Helpers/CodegenSession.cs
@@ -0,0 +1,171 @@
+using FishNet.CodeGenerating.Helping;
+using FishNet.CodeGenerating.ILCore;
+using FishNet.CodeGenerating.Processing;
+using FishNet.CodeGenerating.Processing.Rpc;
+using MonoFN.Cecil;
+using System.Collections.Generic;
+using System.Linq;
+using Unity.CompilationPipeline.Common.Diagnostics;
+#if !UNITY_2020_1_OR_NEWER
+using UnityEngine;
+#endif
+using SR = System.Reflection;
+
+namespace FishNet.CodeGenerating
+{
+ internal class CodegenSession
+ {
+ ///
+ /// Current module for this session.
+ ///
+ internal ModuleDefinition Module;
+ ///
+ /// Outputs errors when codegen fails.
+ ///
+ internal List Diagnostics;
+ ///
+ /// SyncVars that are being accessed from an assembly other than the currently being processed one.
+ ///
+ internal List DifferentAssemblySyncVars = new();
+ ///
+ /// CodegenBase classes for processing a module.
+ ///
+ private List _bases;
+ ///
+ /// Quick lookup of base classes.
+ ///
+ private Dictionary _basesCache = new();
+
+ ///
+ /// Returns class of type if found within CodegenBase classes.
+ ///
+ ///
+ ///
+ internal T GetClass() where T : CodegenBase
+ {
+ string tName = typeof(T).Name;
+ return (T)_basesCache[tName];
+ }
+
+ ///
+ /// Resets all helpers while importing any information needed by them.
+ ///
+ ///
+ ///
+ internal bool Initialize(ModuleDefinition module)
+ {
+ Module = module;
+ Diagnostics = new();
+
+ _bases = new()
+ {
+ new ReaderImports(), new ReaderProcessor(), new WriterImports(), new WriterProcessor(), new PhysicsHelper(), new TimeManagerHelper(), new AttributeHelper(), new GeneralHelper(), new ObjectHelper(), new NetworkBehaviourHelper(), new TransportHelper(), new NetworkConnectionImports(), new PredictedObjectHelper(), new GeneratorHelper(), new CustomSerializerProcessor(), new NetworkBehaviourProcessor(), new QolAttributeProcessor(), new RpcProcessor(), new SyncTypeProcessor(), new PredictionProcessor()
+ };
+
+ // Add all to dictionary first, then import.
+ foreach (CodegenBase item in _bases)
+ {
+ string tName = item.GetType().Name;
+ _basesCache.Add(tName, item);
+ }
+
+ // Initialize.
+ foreach (CodegenBase item in _bases)
+ {
+ item.Initialize(this);
+ if (!item.ImportReferences())
+ return false;
+ }
+
+ return true;
+ }
+
+ #region Logging.
+ public string MethodDefinitionTraceText(MethodDefinition methodDef) => methodDef == null ? " Null MethodDef" : $" TypeDef [{methodDef.DeclaringType.FullName}] Method [{methodDef.Name}]";
+ public string TypeDefinitionTraceText(TypeDefinition typeDef) => typeDef == null ? " Null TypeDef" : $" TypeDef [{typeDef.FullName}]";
+ public string TypeReferenceTraceText(TypeReference typeRef) => typeRef == null ? " Null TypeRef" : $" TypeRef [{typeRef.FullName}]";
+ public string FieldDefinitionTraceText(FieldDefinition fieldDef) => fieldDef == null ? " Null FieldRef" : $" TypeRef [{fieldDef.DeclaringType.FullName}] FieldDef [{fieldDef.Name}]";
+ public string PropertyDefinitionTraceText(PropertyDefinition propertyDef) => propertyDef == null ? " Null PropertydRef" : $" TypeRef [{propertyDef.DeclaringType.FullName}] PropertyDef [{propertyDef.Name}]";
+
+ ///
+ /// Logs a warning.
+ ///
+ ///
+ internal void LogWarning(string msg)
+ {
+ Diagnostics.AddWarning(msg);
+ }
+
+ ///
+ /// Logs an error.
+ ///
+ ///
+ internal void LogError(string msg)
+ {
+ Diagnostics.AddError(msg);
+ }
+ #endregion
+
+ #region ImportReference.
+ public MethodReference ImportReference(SR.MethodBase method)
+ {
+ return Module.ImportReference(method);
+ }
+
+ public MethodReference ImportReference(SR.MethodBase method, IGenericParameterProvider context)
+ {
+ return Module.ImportReference(method, context);
+ }
+
+ public TypeReference ImportReference(TypeReference type)
+ {
+ return Module.ImportReference(type);
+ }
+
+ public TypeReference ImportReference(TypeReference type, IGenericParameterProvider context)
+ {
+ return Module.ImportReference(type, context);
+ }
+
+ public FieldReference ImportReference(FieldReference field)
+ {
+ return Module.ImportReference(field);
+ }
+
+ public FieldReference ImportReference(FieldReference field, IGenericParameterProvider context)
+ {
+ return Module.ImportReference(field, context);
+ }
+
+ public MethodReference ImportReference(MethodReference method)
+ {
+ return Module.ImportReference(method);
+ }
+
+ public MethodReference ImportReference(MethodReference method, IGenericParameterProvider context)
+ {
+ return Module.ImportReference(method, context);
+ }
+
+ public TypeReference ImportReference(System.Type type)
+ {
+ return ImportReference(type, null);
+ }
+
+ public TypeReference ImportReference(System.Type type, IGenericParameterProvider context)
+ {
+ return Module.ImportReference(type, context);
+ }
+
+ public FieldReference ImportReference(SR.FieldInfo field)
+ {
+ return Module.ImportReference(field);
+ }
+
+ public FieldReference ImportReference(SR.FieldInfo field, IGenericParameterProvider context)
+ {
+ return Module.ImportReference(field, context);
+ }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Assets/FishNet/CodeGenerating/Helpers/CodegenSession.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/CodegenSession.cs.meta
new file mode 100644
index 00000000..4265e1f4
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Helpers/CodegenSession.cs.meta
@@ -0,0 +1,18 @@
+fileFormatVersion: 2
+guid: 3e8416eee3308f54fa942003de975420
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 207815
+ packageName: 'FishNet: Networking Evolved'
+ packageVersion: 4.6.22R
+ assetPath: Assets/FishNet/CodeGenerating/Helpers/CodegenSession.cs
+ uploadId: 866910
diff --git a/Assets/FishNet/CodeGenerating/Helpers/CreatedSyncVarGenerator.cs b/Assets/FishNet/CodeGenerating/Helpers/CreatedSyncVarGenerator.cs
new file mode 100644
index 00000000..510b5732
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Helpers/CreatedSyncVarGenerator.cs
@@ -0,0 +1,119 @@
+// using FishNet.CodeGenerating.Helping.Extension;
+// using FishNet.CodeGenerating.Processing;
+// using FishNet.Object.Synchronizing;
+// using FishNet.Object.Synchronizing.Internal;
+// using MonoFN.Cecil;
+// using MonoFN.Cecil.Rocks;
+// using System;
+// using System.Collections.Generic;
+
+// namespace FishNet.CodeGenerating.Helping
+// {
+// internal class CreatedSyncVarGenerator : CodegenBase
+// {
+// private readonly Dictionary _createdSyncVars = new Dictionary();
+
+// #region Relfection references.
+// private TypeReference _syncBase_TypeRef;
+// internal TypeReference SyncVar_TypeRef;
+// private MethodReference _syncVar_InitializeOnce_MethodRef;
+// #endregion
+
+// #region Const.
+// private const string GETVALUE_NAME = "GetValue";
+// private const string SETVALUE_NAME = "SetValue";
+// #endregion
+
+// /* // feature add and test the dirty boolean changes
+// * eg... instead of base.Dirty()
+// * do if (!base.Dirty()) return false;
+// * See synclist for more info. */
+
+// ///
+// /// Imports references needed by this helper.
+// ///
+// ///
+// ///
+// public override bool ImportReferences()
+// {
+// Type svType = typeof(SyncVar<>);
+// SyncVar_TypeRef = base.ImportReference(svType);
+// _syncVar_InitializeOnce_MethodRef = base.ImportReference(svType.GetMethod(nameof(SyncVar.InitializeOnce)));
+// Type syncBaseType = typeof(SyncBase);
+// _syncBase_TypeRef = base.ImportReference(syncBaseType);
+
+// return true;
+// }
+
+// ///
+// /// Gets and optionally creates data for SyncVar
+// ///
+// ///
+// ///
+// internal DeclaredSyncType GetCreatedSyncVar(FieldDefinition originalFd, bool createMissing)
+// {
+// TypeReference dataTr = originalFd.FieldType;
+// TypeDefinition dataTd = dataTr.CachedResolve(base.Session);
+
+// string typeHash = dataTr.FullName + dataTr.IsArray.ToString();
+
+// if (_createdSyncVars.TryGetValue(typeHash, out DeclaredSyncType createdSyncVar))
+// {
+// return createdSyncVar;
+// }
+// else
+// {
+// if (!createMissing)
+// return null;
+
+// base.ImportReference(dataTd);
+
+// GenericInstanceType originalFdGit = SyncVar_TypeRef.MakeGenericInstanceType(new TypeReference[] { dataTr });
+// TypeReference genericDataTr = originalFdGit.GenericArguments[0];
+
+// // Make sure can serialize.
+// bool canSerialize = base.GetClass().HasSerializerAndDeserializer(genericDataTr, true);
+// if (!canSerialize)
+// {
+// base.LogError($"SyncVar {originalFd.Name} data type {genericDataTr.FullName} does not support serialization. Use a supported type or create a custom serializer.");
+// return null;
+// }
+
+// // Set needed methods from syncbase.
+// MethodReference setSyncIndexMr;
+// MethodReference initializeOnceMrGit = _syncVar_InitializeOnce_MethodRef.MakeHostInstanceGeneric(base.Session, originalFdGit);
+
+// if (!base.GetClass().SetSyncBaseMethods(_syncBase_TypeRef.CachedResolve(base.Session), out setSyncIndexMr, out _))
+// return null;
+
+// MethodReference setValueMr = null;
+// MethodReference getValueMr = null;
+// foreach (MethodDefinition md in SyncVar_TypeRef.CachedResolve(base.Session).Methods)
+// {
+// // GetValue.
+// if (md.Name == GETVALUE_NAME)
+// {
+// MethodReference mr = base.ImportReference(md);
+// getValueMr = mr.MakeHostInstanceGeneric(base.Session, originalFdGit);
+// }
+// // SetValue.
+// else if (md.Name == SETVALUE_NAME)
+// {
+// MethodReference mr = base.ImportReference(md);
+// setValueMr = mr.MakeHostInstanceGeneric(base.Session, originalFdGit);
+// }
+// }
+
+// if (setValueMr == null || getValueMr == null)
+// return null;
+
+// DeclaredSyncType csv = new DeclaredSyncType(originalFd, originalFdGit, dataTd, initializeOnceMrGit, null);
+// _createdSyncVars.Add(typeHash, csv);
+// return csv;
+// }
+// }
+
+// }
+
+// }
+
diff --git a/Assets/FishNet/CodeGenerating/Helpers/CreatedSyncVarGenerator.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/CreatedSyncVarGenerator.cs.meta
new file mode 100644
index 00000000..ff84c488
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Helpers/CreatedSyncVarGenerator.cs.meta
@@ -0,0 +1,18 @@
+fileFormatVersion: 2
+guid: 935ec97b96b35b94f8c6880c6908304c
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 207815
+ packageName: 'FishNet: Networking Evolved'
+ packageVersion: 4.6.22R
+ assetPath: Assets/FishNet/CodeGenerating/Helpers/CreatedSyncVarGenerator.cs
+ uploadId: 866910
diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension.meta b/Assets/FishNet/CodeGenerating/Helpers/Extension.meta
new file mode 100644
index 00000000..4e7333c8
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Helpers/Extension.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 6fee1744ec071184db72fc2443e77ece
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/CustomAttributeExtensions.cs b/Assets/FishNet/CodeGenerating/Helpers/Extension/CustomAttributeExtensions.cs
new file mode 100644
index 00000000..d83227ad
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Helpers/Extension/CustomAttributeExtensions.cs
@@ -0,0 +1,51 @@
+using MonoFN.Cecil;
+using System.Linq;
+
+namespace FishNet.CodeGenerating.Helping.Extension
+{
+ internal static class CustomAttributeExtensions
+ {
+ ///
+ /// Finds a field within an attribute.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ internal static T GetField(this CustomAttribute customAttr, string field, T defaultValue)
+ {
+ foreach (CustomAttributeNamedArgument customField in customAttr.Fields)
+ {
+ if (customField.Name == field)
+ {
+ return (T)customField.Argument.Value;
+ }
+ }
+
+ return defaultValue;
+ }
+
+ ///
+ /// Returns if any of the attributes match IAtrribute.
+ ///
+ ///
+ ///
+ ///
+ internal static bool HasCustomAttribute(this ICustomAttributeProvider attributeProvider)
+ {
+ return attributeProvider.CustomAttributes.Any(attr => attr.AttributeType.Is());
+ }
+
+ ///
+ /// Returns if ca is of type target.
+ ///
+ ///
+ ///
+ ///
+ internal static bool Is(this CustomAttribute ca, string targetFullName)
+ {
+ return ca.AttributeType.FullName == targetFullName;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/CustomAttributeExtensions.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Extension/CustomAttributeExtensions.cs.meta
new file mode 100644
index 00000000..53fdb931
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Helpers/Extension/CustomAttributeExtensions.cs.meta
@@ -0,0 +1,18 @@
+fileFormatVersion: 2
+guid: a66d771ab331fae408142a5c04abd74e
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 207815
+ packageName: 'FishNet: Networking Evolved'
+ packageVersion: 4.6.22R
+ assetPath: Assets/FishNet/CodeGenerating/Helpers/Extension/CustomAttributeExtensions.cs
+ uploadId: 866910
diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/Diagnostics.cs b/Assets/FishNet/CodeGenerating/Helpers/Extension/Diagnostics.cs
new file mode 100644
index 00000000..bebbb336
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Helpers/Extension/Diagnostics.cs
@@ -0,0 +1,40 @@
+using MonoFN.Cecil;
+using MonoFN.Cecil.Cil;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Unity.CompilationPipeline.Common.Diagnostics;
+
+namespace FishNet.CodeGenerating.Helping
+{
+ internal static class Diagnostics
+ {
+ internal static void AddError(this List diagnostics, string message)
+ {
+ diagnostics.AddMessage(DiagnosticType.Error, (SequencePoint)null, message);
+ }
+
+ internal static void AddWarning(this List diagnostics, string message)
+ {
+ diagnostics.AddMessage(DiagnosticType.Warning, (SequencePoint)null, message);
+ }
+
+ internal static void AddError(this List diagnostics, MethodDefinition methodDef, string message)
+ {
+ diagnostics.AddMessage(DiagnosticType.Error, methodDef.DebugInformation.SequencePoints.FirstOrDefault(), message);
+ }
+
+ internal static void AddMessage(this List diagnostics, DiagnosticType diagnosticType, SequencePoint sequencePoint, string message)
+ {
+ diagnostics.Add(new()
+ {
+ DiagnosticType = diagnosticType,
+ File = sequencePoint?.Document.Url.Replace($"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}", ""),
+ Line = sequencePoint?.StartLine ?? 0,
+ Column = sequencePoint?.StartColumn ?? 0,
+ MessageData = $" - {message}"
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/Diagnostics.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Extension/Diagnostics.cs.meta
new file mode 100644
index 00000000..43641d69
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Helpers/Extension/Diagnostics.cs.meta
@@ -0,0 +1,18 @@
+fileFormatVersion: 2
+guid: fb7b65b572b01444cbe3c9d830cd3587
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 207815
+ packageName: 'FishNet: Networking Evolved'
+ packageVersion: 4.6.22R
+ assetPath: Assets/FishNet/CodeGenerating/Helpers/Extension/Diagnostics.cs
+ uploadId: 866910
diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/GetConstructor.cs b/Assets/FishNet/CodeGenerating/Helpers/Extension/GetConstructor.cs
new file mode 100644
index 00000000..124e7fda
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Helpers/Extension/GetConstructor.cs
@@ -0,0 +1,185 @@
+using FishNet.CodeGenerating.Helping.Extension;
+using MonoFN.Cecil;
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace FishNet.CodeGenerating.Helping
+{
+ internal static class Constructors
+ {
+ ///
+ /// Gets the first constructor that optionally has, or doesn't have parameters.
+ ///
+ ///
+ ///
+ public static MethodDefinition GetFirstConstructor(this TypeReference typeRef, CodegenSession session, bool requireParameters)
+ {
+ return typeRef.CachedResolve(session).GetFirstConstructor(requireParameters);
+ }
+
+ ///
+ /// Gets the first constructor that optionally has, or doesn't have parameters.
+ ///
+ ///
+ ///
+ public static MethodDefinition GetFirstConstructor(this TypeDefinition typeDef, bool requireParameters)
+ {
+ foreach (MethodDefinition methodDef in typeDef.Methods)
+ {
+ if (methodDef.IsConstructor && methodDef.IsPublic)
+ {
+ if (requireParameters && methodDef.Parameters.Count > 0)
+ return methodDef;
+ else if (!requireParameters && methodDef.Parameters.Count == 0)
+ return methodDef;
+ }
+ }
+
+ return null;
+ }
+
+ ///
+ /// Gets the first public constructor with no parameters.
+ ///
+ ///
+ public static MethodDefinition GetDefaultConstructor(this TypeReference typeRef, CodegenSession session)
+ {
+ return typeRef.CachedResolve(session).GetDefaultConstructor();
+ }
+
+ ///
+ /// Gets the first public constructor with no parameters.
+ ///
+ ///
+ public static MethodDefinition GetDefaultConstructor(this TypeDefinition typeDef)
+ {
+ foreach (MethodDefinition methodDef in typeDef.Methods)
+ {
+ if (methodDef.IsConstructor && methodDef.IsPublic && methodDef.Parameters.Count == 0)
+ return methodDef;
+ }
+
+ return null;
+ }
+
+ ///
+ /// Gets all constructors on typeDef.
+ ///
+ ///
+ public static List GetConstructors(this TypeDefinition typeDef)
+ {
+ List lst = new();
+ foreach (MethodDefinition methodDef in typeDef.Methods)
+ {
+ if (methodDef.IsConstructor)
+ lst.Add(methodDef);
+ }
+
+ return lst;
+ }
+
+ ///
+ /// Gets constructor which has arguments.
+ ///
+ ///
+ ///
+ public static MethodDefinition GetConstructor(this TypeReference typeRef, CodegenSession session, Type[] arguments)
+ {
+ return typeRef.CachedResolve(session).GetConstructor(arguments);
+ }
+
+ ///
+ /// Gets constructor which has arguments.
+ ///
+ ///
+ ///
+ public static MethodDefinition GetConstructor(this TypeDefinition typeDef, Type[] arguments)
+ {
+ Type[] argsCopy = arguments == null ? new Type[0] : arguments;
+ foreach (MethodDefinition methodDef in typeDef.Methods)
+ {
+ if (methodDef.IsConstructor && methodDef.IsPublic && methodDef.Parameters.Count == argsCopy.Length)
+ {
+ bool match = true;
+ for (int i = 0; i < argsCopy.Length; i++)
+ {
+ if (methodDef.Parameters[0].ParameterType.FullName != argsCopy[i].FullName)
+ {
+ match = false;
+ break;
+ }
+ }
+
+ if (match)
+ return methodDef;
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Gets constructor which has arguments.
+ ///
+ ///
+ ///
+ public static MethodDefinition GetConstructor(this TypeReference typeRef, CodegenSession session, TypeReference[] arguments)
+ {
+ return typeRef.CachedResolve(session).GetConstructor(arguments);
+ }
+
+ ///
+ /// Gets constructor which has arguments.
+ ///
+ ///
+ ///
+ public static MethodDefinition GetConstructor(this TypeDefinition typeDef, TypeReference[] arguments)
+ {
+ TypeReference[] argsCopy = arguments == null ? new TypeReference[0] : arguments;
+ foreach (MethodDefinition methodDef in typeDef.Methods)
+ {
+ if (methodDef.IsConstructor && methodDef.IsPublic && methodDef.Parameters.Count == argsCopy.Length)
+ {
+ bool match = true;
+ for (int i = 0; i < argsCopy.Length; i++)
+ {
+ if (methodDef.Parameters[0].ParameterType.FullName != argsCopy[i].FullName)
+ {
+ match = false;
+ break;
+ }
+ }
+
+ if (match)
+ return methodDef;
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Resolves the constructor with parameterCount for typeRef.
+ ///
+ ///
+ ///
+ public static MethodDefinition GetConstructor(this TypeReference typeRef, CodegenSession session, int parameterCount)
+ {
+ return typeRef.CachedResolve(session).GetConstructor(parameterCount);
+ }
+
+ ///
+ /// Resolves the constructor with parameterCount for typeRef.
+ ///
+ ///
+ ///
+ public static MethodDefinition GetConstructor(this TypeDefinition typeDef, int parameterCount)
+ {
+ foreach (MethodDefinition methodDef in typeDef.Methods)
+ {
+ if (methodDef.IsConstructor && methodDef.IsPublic && methodDef.Parameters.Count == parameterCount)
+ return methodDef;
+ }
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/GetConstructor.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Extension/GetConstructor.cs.meta
new file mode 100644
index 00000000..25583f4f
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Helpers/Extension/GetConstructor.cs.meta
@@ -0,0 +1,18 @@
+fileFormatVersion: 2
+guid: 1a7e03137ca78704e999f3a3dc68b953
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 207815
+ packageName: 'FishNet: Networking Evolved'
+ packageVersion: 4.6.22R
+ assetPath: Assets/FishNet/CodeGenerating/Helpers/Extension/GetConstructor.cs
+ uploadId: 866910
diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/ILProcessorExtensions.cs b/Assets/FishNet/CodeGenerating/Helpers/Extension/ILProcessorExtensions.cs
new file mode 100644
index 00000000..208e4c6b
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Helpers/Extension/ILProcessorExtensions.cs
@@ -0,0 +1,193 @@
+using MonoFN.Cecil;
+using MonoFN.Cecil.Cil;
+using System.Collections.Generic;
+
+namespace FishNet.CodeGenerating.Helping.Extension
+{
+ internal static class ILProcessorExtensions
+ {
+ ///
+ /// Creates a debug log for text without any conditions.
+ ///
+ public static List DebugLog(this ILProcessor processor, CodegenSession session, string txt)
+ {
+ List insts = new();
+ insts.Add(processor.Create(OpCodes.Ldstr, txt));
+ insts.Add(processor.Create(OpCodes.Call, session.GetClass().Debug_LogCommon_MethodRef));
+ return insts;
+ }
+
+ ///
+ /// Creates a debug log for vd without any conditions.
+ ///
+ public static List DebugLog(this ILProcessor processor, CodegenSession session, VariableDefinition vd)
+ {
+ List insts = new();
+ insts.Add(processor.Create(OpCodes.Ldloc, vd));
+ insts.Add(processor.Create(OpCodes.Box, vd.VariableType));
+ insts.Add(processor.Create(OpCodes.Call, session.GetClass().Debug_LogCommon_MethodRef));
+ return insts;
+ }
+
+ ///
+ /// Creates a debug log for vd without any conditions.
+ ///
+ public static List DebugLog(this ILProcessor processor, CodegenSession session, FieldDefinition fd, bool loadArg0)
+ {
+ List insts = new();
+ if (loadArg0)
+ insts.Add(processor.Create(OpCodes.Ldarg_0));
+ insts.Add(processor.Create(OpCodes.Ldfld, fd));
+ insts.Add(processor.Create(OpCodes.Box, fd.FieldType));
+ insts.Add(processor.Create(OpCodes.Call, session.GetClass().Debug_LogCommon_MethodRef));
+ return insts;
+ }
+
+ ///
+ /// Creates a debug log for pd without any conditions.
+ ///
+ public static List DebugLog(this ILProcessor processor, CodegenSession session, ParameterDefinition pd)
+ {
+ List insts = new();
+ insts.Add(processor.Create(OpCodes.Ldloc, pd));
+ insts.Add(processor.Create(OpCodes.Box, pd.ParameterType));
+ insts.Add(processor.Create(OpCodes.Call, session.GetClass().Debug_LogCommon_MethodRef));
+ return insts;
+ }
+
+ ///
+ /// Removes Ret if the last instruction.
+ ///
+ /// True if ret was removed.
+ public static bool RemoveEndRet(this ILProcessor processor)
+ {
+ int instCount = processor.Body.Instructions.Count;
+ if (instCount == 0)
+ return false;
+
+ if (processor.Body.Instructions[instCount - 1].OpCode == OpCodes.Ret)
+ {
+ processor.Body.Instructions.RemoveAt(instCount - 1);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /////
+ ///// Creates a debug log for mr without any conditions.
+ /////
+ // public static void DebugLog(this ILProcessor processor, MethodReference mr)
+ // {
+ // processor.Emit(OpCodes.Call, mr);
+ // processor.Emit(OpCodes.Box, mr.ReturnType);
+ // processor.Emit(OpCodes.Call, base.GetClass().Debug_LogCommon_MethodRef);
+ // }
+
+ ///
+ /// Inserts instructions at the beginning.
+ ///
+ ///
+ ///
+ public static void InsertAt(this ILProcessor processor, int target, List instructions)
+ {
+ for (int i = 0; i < instructions.Count; i++)
+ processor.Body.Instructions.Insert(i + target, instructions[i]);
+ }
+
+ ///
+ /// Inserts instructions at the beginning.
+ ///
+ ///
+ ///
+ public static void InsertFirst(this ILProcessor processor, List instructions)
+ {
+ for (int i = 0; i < instructions.Count; i++)
+ processor.Body.Instructions.Insert(i, instructions[i]);
+ }
+
+ ///
+ /// Inserts instructions at the end while also moving Ret down.
+ ///
+ ///
+ ///
+ public static void InsertLast(this ILProcessor processor, List instructions)
+ {
+ bool retRemoved = false;
+ int startingCount = processor.Body.Instructions.Count;
+ // Remove ret if it exist and add it back in later.
+ if (startingCount > 0)
+ {
+ if (processor.Body.Instructions[startingCount - 1].OpCode == OpCodes.Ret)
+ {
+ processor.Body.Instructions.RemoveAt(startingCount - 1);
+ retRemoved = true;
+ }
+ }
+
+ foreach (Instruction inst in instructions)
+ processor.Append(inst);
+
+ // Add ret back if it was removed.
+ if (retRemoved)
+ processor.Emit(OpCodes.Ret);
+ }
+
+ ///
+ /// Inserts instructions before target.
+ ///
+ ///
+ ///
+ public static void InsertBefore(this ILProcessor processor, Instruction target, List instructions)
+ {
+ int index = processor.Body.Instructions.IndexOf(target);
+ for (int i = 0; i < instructions.Count; i++)
+ processor.Body.Instructions.Insert(index + i, instructions[i]);
+ }
+
+ ///
+ /// Adds instructions to the end of processor.
+ ///
+ ///
+ ///
+ public static void Add(this ILProcessor processor, List instructions)
+ {
+ for (int i = 0; i < instructions.Count; i++)
+ processor.Body.Instructions.Add(instructions[i]);
+ }
+
+ ///
+ /// Inserts instructions before returns. Only works on void types.
+ ///
+ ///
+ ///
+ public static void InsertBeforeReturns(this ILProcessor processor, CodegenSession session, List instructions)
+ {
+ if (processor.Body.Method.ReturnType.FullName != session.Module.TypeSystem.Void.FullName)
+ {
+ session.LogError($"Cannot insert instructions before returns on {processor.Body.Method.FullName} because it does not return void.");
+ return;
+ }
+
+ /* Insert at the end of the method
+ * and get the first instruction that was inserted.
+ * Any returns or breaks which would exit the method
+ * will jump to this instruction instead. */
+ processor.InsertLast(instructions);
+ Instruction startInst = processor.Body.Instructions[processor.Body.Instructions.Count - instructions.Count];
+
+ // Look for anything that jumps to rets.
+ for (int i = 0; i < processor.Body.Instructions.Count; i++)
+ {
+ Instruction inst = processor.Body.Instructions[i];
+ if (inst.Operand is Instruction operInst)
+ {
+ if (operInst.OpCode == OpCodes.Ret)
+ inst.Operand = startInst;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/ILProcessorExtensions.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Extension/ILProcessorExtensions.cs.meta
new file mode 100644
index 00000000..19cdcd0d
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Helpers/Extension/ILProcessorExtensions.cs.meta
@@ -0,0 +1,18 @@
+fileFormatVersion: 2
+guid: 820cf8401d4d71c4196dda444559ef8a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 207815
+ packageName: 'FishNet: Networking Evolved'
+ packageVersion: 4.6.22R
+ assetPath: Assets/FishNet/CodeGenerating/Helpers/Extension/ILProcessorExtensions.cs
+ uploadId: 866910
diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/InstructionExtensions.cs b/Assets/FishNet/CodeGenerating/Helpers/Extension/InstructionExtensions.cs
new file mode 100644
index 00000000..f2d77831
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Helpers/Extension/InstructionExtensions.cs
@@ -0,0 +1,9 @@
+using MonoFN.Cecil;
+using MonoFN.Cecil.Cil;
+using System;
+using System.Collections.Generic;
+
+namespace FishNet.CodeGenerating.Helping
+{
+ public static class Instructions { }
+}
\ No newline at end of file
diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/InstructionExtensions.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Extension/InstructionExtensions.cs.meta
new file mode 100644
index 00000000..74e38353
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Helpers/Extension/InstructionExtensions.cs.meta
@@ -0,0 +1,18 @@
+fileFormatVersion: 2
+guid: 360667149f16b6c4aba61fd05427cbfb
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 207815
+ packageName: 'FishNet: Networking Evolved'
+ packageVersion: 4.6.22R
+ assetPath: Assets/FishNet/CodeGenerating/Helpers/Extension/InstructionExtensions.cs
+ uploadId: 866910
diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/MethodReferenceExtensions.cs b/Assets/FishNet/CodeGenerating/Helpers/Extension/MethodReferenceExtensions.cs
new file mode 100644
index 00000000..16afaefd
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Helpers/Extension/MethodReferenceExtensions.cs
@@ -0,0 +1,170 @@
+using FishNet.CodeGenerating.Extension;
+using MonoFN.Cecil;
+using MonoFN.Cecil.Rocks;
+using System;
+
+namespace FishNet.CodeGenerating.Helping.Extension
+{
+ internal static class MethodReferenceExtensions
+ {
+ ///
+ /// Returns a custom attribute.
+ ///
+ public static CustomAttribute GetCustomAttribute(this MethodReference mr, string attributeFullName)
+ {
+ MethodDefinition md = mr.Resolve();
+ return MethodDefinitionExtensions.GetCustomAttribute(md, attributeFullName);
+ }
+
+ ///
+ /// Makes a generic method with specified arguments.
+ ///
+ ///
+ ///
+ ///
+ public static GenericInstanceMethod MakeGenericMethod(this MethodReference method, params TypeReference[] genericArguments)
+ {
+ GenericInstanceMethod result = new(method);
+ foreach (TypeReference argument in genericArguments)
+ result.GenericArguments.Add(argument);
+ return result;
+ }
+
+ ///
+ /// Makes a generic method with the same arguments as the original.
+ ///
+ ///
+ ///
+ public static GenericInstanceMethod MakeGenericMethod(this MethodReference method)
+ {
+ GenericInstanceMethod result = new(method);
+ foreach (ParameterDefinition pd in method.Parameters)
+ result.GenericArguments.Add(pd.ParameterType);
+
+ return result;
+ }
+
+ ///
+ /// Returns a method reference for a generic method.
+ ///
+ public static MethodReference GetMethodReference(this MethodReference mr, CodegenSession session, TypeReference typeReference)
+ {
+ return mr.GetMethodReference(session, new TypeReference[] { typeReference });
+ }
+
+ ///
+ /// Returns a method reference for a generic method.
+ ///
+ public static MethodReference GetMethodReference(this MethodReference mr, CodegenSession session, TypeReference[] typeReferences)
+ {
+ if (mr.HasGenericParameters)
+ {
+ if (typeReferences == null || typeReferences.Length == 0)
+ {
+ session.LogError($"Method {mr.Name} has generic parameters but TypeReferences are null or 0 length.");
+ return null;
+ }
+ else
+ {
+ GenericInstanceMethod gim = mr.MakeGenericMethod(typeReferences);
+ return gim;
+ }
+ }
+ else
+ {
+ return mr;
+ }
+ }
+
+ ///
+ /// Gets a Resolve favoring cached results first.
+ ///
+ internal static MethodDefinition CachedResolve(this MethodReference methodRef, CodegenSession session)
+ {
+ return session.GetClass().GetMethodReferenceResolve(methodRef);
+ }
+
+ ///
+ /// Removes ret if it exist at the end of the method. Returns if ret was removed.
+ ///
+ internal static bool RemoveEndRet(this MethodReference mr, CodegenSession session)
+ {
+ MethodDefinition md = mr.CachedResolve(session);
+ return MethodDefinitionExtensions.RemoveEndRet(md, session);
+ }
+
+ ///
+ /// Given a method of a generic class such as ArraySegment`T.get_Count,
+ /// and a generic instance such as ArraySegment`int
+ /// Creates a reference to the specialized method ArraySegment`int`.get_Count
+ /// Note that calling ArraySegment`T.get_Count directly gives an invalid IL error
+ ///
+ ///
+ ///
+ ///
+ public static MethodReference MakeHostInstanceGeneric(this MethodReference self, CodegenSession session, GenericInstanceType instanceType)
+ {
+ MethodReference reference = new(self.Name, self.ReturnType, instanceType)
+ {
+ CallingConvention = self.CallingConvention,
+ HasThis = self.HasThis,
+ ExplicitThis = self.ExplicitThis
+ };
+
+ foreach (ParameterDefinition parameter in self.Parameters)
+ reference.Parameters.Add(new(parameter.ParameterType));
+
+ foreach (GenericParameter generic_parameter in self.GenericParameters)
+ reference.GenericParameters.Add(new(generic_parameter.Name, reference));
+
+ return session.ImportReference(reference);
+ }
+
+ ///
+ /// Given a method of a generic class such as ArraySegment`T.get_Count,
+ /// and a generic instance such as ArraySegment`int
+ /// Creates a reference to the specialized method ArraySegment`int`.get_Count
+ /// Note that calling ArraySegment`T.get_Count directly gives an invalid IL error
+ ///
+ ///
+ ///
+ ///
+ public static MethodReference MakeHostInstanceGeneric(this MethodReference self, TypeReference typeRef, params TypeReference[] args)
+ {
+ GenericInstanceType git = typeRef.MakeGenericInstanceType(args);
+ MethodReference reference = new(self.Name, self.ReturnType, git)
+ {
+ CallingConvention = self.CallingConvention,
+ HasThis = self.HasThis,
+ ExplicitThis = self.ExplicitThis
+ };
+
+ foreach (ParameterDefinition parameter in self.Parameters)
+ reference.Parameters.Add(new(parameter.ParameterType));
+
+ foreach (GenericParameter generic_parameter in self.GenericParameters)
+ reference.GenericParameters.Add(new(generic_parameter.Name, reference));
+
+ return reference;
+ }
+
+ public static bool Is(this MethodReference method, string name)
+ {
+ return method.DeclaringType.Is() && method.Name == name;
+ }
+
+ public static bool Is(this TypeReference td)
+ {
+ return Is(td, typeof(T));
+ }
+
+ public static bool Is(this TypeReference td, Type t)
+ {
+ if (t.IsGenericType)
+ {
+ return td.GetElementType().FullName == t.FullName;
+ }
+ return td.FullName == t.FullName;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/MethodReferenceExtensions.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Extension/MethodReferenceExtensions.cs.meta
new file mode 100644
index 00000000..b8719798
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Helpers/Extension/MethodReferenceExtensions.cs.meta
@@ -0,0 +1,18 @@
+fileFormatVersion: 2
+guid: ee1c15a06ab386e439ec5aa41e3496f7
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 207815
+ packageName: 'FishNet: Networking Evolved'
+ packageVersion: 4.6.22R
+ assetPath: Assets/FishNet/CodeGenerating/Helpers/Extension/MethodReferenceExtensions.cs
+ uploadId: 866910
diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/ModuleDefinitionExtensions.cs b/Assets/FishNet/CodeGenerating/Helpers/Extension/ModuleDefinitionExtensions.cs
new file mode 100644
index 00000000..b5a74cc4
--- /dev/null
+++ b/Assets/FishNet/CodeGenerating/Helpers/Extension/ModuleDefinitionExtensions.cs
@@ -0,0 +1,59 @@
+using FishNet.CodeGenerating.ILCore;
+using MonoFN.Cecil;
+using System;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace FishNet.CodeGenerating.Helping.Extension
+{
+ public static class ModuleDefinitionExtensions
+ {
+ ///
+ /// Gets a class within a module.
+ ///
+ ///
+ ///
+ public static TypeDefinition GetClass(this ModuleDefinition moduleDef, string className, string namespaceName = "")
+ {
+ if (namespaceName.Length == 0)
+ namespaceName = FishNetILPP.RUNTIME_ASSEMBLY_NAME;
+
+ return moduleDef.GetType(namespaceName, className);
+ }
+
+ public static MethodReference ImportReference(this ModuleDefinition moduleDef, Expression expression)
+ {
+ return ImportReference(moduleDef, (LambdaExpression)expression);
+ }
+
+ public static MethodReference ImportReference(this ModuleDefinition module, Expression> expression)
+ {
+ return ImportReference(module, (LambdaExpression)expression);
+ }
+
+ public static MethodReference ImportReference(this ModuleDefinition module, LambdaExpression expression)
+ {
+ if (expression.Body is MethodCallExpression outermostExpression)
+ {
+ MethodInfo methodInfo = outermostExpression.Method;
+ return module.ImportReference(methodInfo);
+ }
+
+ if (expression.Body is NewExpression newExpression)
+ {
+ ConstructorInfo methodInfo = newExpression.Constructor;
+ // constructor is null when creating an ArraySegment