[Add] FishNet

This commit is contained in:
2026-03-30 20:11:57 +07:00
parent ee793a3361
commit c22c08753a
1797 changed files with 197950 additions and 1 deletions
@@ -0,0 +1,16 @@
using MonoFN.Cecil;
namespace FishNet.CodeGenerating.Helping.Extension
{
internal static class FieldDefinitionExtensions
{
/// <summary>
/// Makes a FieldDefinition generic if it has generic parameters.
/// </summary>
public static FieldReference TryMakeGenericInstance(this FieldDefinition fd, CodegenSession session)
{
FieldReference fr = session.ImportReference(fd);
return fr.TryMakeGenericInstance();
}
}
}
@@ -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
@@ -0,0 +1,35 @@
using FishNet.CodeGenerating.Extension;
using MonoFN.Cecil;
namespace FishNet.CodeGenerating.Helping.Extension
{
internal static class FieldReferenceExtensions
{
/// <summary>
/// Gets a Resolve favoring cached results first.
/// </summary>
internal static FieldDefinition CachedResolve(this FieldReference fieldRef, CodegenSession session)
{
return session.GetClass<GeneralHelper>().GetFieldReferenceResolve(fieldRef);
}
/// <summary>
/// Makes a FieldReference generic if it has generic parameters.
/// </summary>
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;
}
}
}
}
@@ -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
@@ -0,0 +1,25 @@
using FishNet.CodeGenerating.Helping.Extension;
using MonoFN.Cecil;
using MonoFN.Cecil.Cil;
namespace FishNet.CodeGenerating.Extension
{
internal static class ILProcessorExtensions
{
/// <summary>
/// Creates a variable type within the body and returns it's VariableDef.
/// </summary>
internal static VariableDefinition CreateVariable(this ILProcessor processor, CodegenSession session, System.Type variableType)
{
return processor.Body.Method.CreateVariable(session, variableType);
}
/// <summary>
/// Creates a variable type within the body and returns it's VariableDef.
/// </summary>
internal static VariableDefinition CreateVariable(this ILProcessor processor, CodegenSession session, TypeReference variableTr)
{
return processor.Body.Method.CreateVariable(variableTr);
}
}
}
@@ -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
@@ -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;
/// <summary>
/// Returns a custom attribute.
/// </summary>
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;
}
/// <summary>
/// Clears the method content and returns ret.
/// </summary>
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<GeneralHelper>().CreateRetDefault(md, importReturnModule));
}
/// <summary>
/// Returns the ParameterDefinition index from end of parameters.
/// </summary>
/// <param name = "md"></param>
/// <param name = "index"></param>
/// <returns></returns>
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)];
}
/// <summary>
/// Creates a variable type within the body and returns it's VariableDef.
/// </summary>
internal static VariableDefinition CreateVariable(this MethodDefinition methodDef, TypeReference variableTypeRef)
{
VariableDefinition variableDef = new(variableTypeRef);
methodDef.Body.Variables.Add(variableDef);
return variableDef;
}
/// <summary>
/// Creates a variable type within the body and returns it's VariableDef.
/// </summary>
internal static VariableDefinition CreateVariable(this MethodDefinition methodDef, CodegenSession session, System.Type variableType)
{
return CreateVariable(methodDef, session.GetClass<GeneralHelper>().GetTypeReference(variableType));
}
/// <summary>
/// Returns the proper OpCode to use for call methods.
/// </summary>
public static OpCode GetCallOpCode(this MethodDefinition md)
{
if (md.Attributes.HasFlag(MethodAttributes.Virtual))
return OpCodes.Callvirt;
else
return OpCodes.Call;
}
/// <summary>
/// Returns the proper OpCode to use for call methods.
/// </summary>
public static OpCode GetCallOpCode(this MethodReference mr, CodegenSession session)
{
return mr.CachedResolve(session).GetCallOpCode();
}
/// <summary>
/// Adds a parameter and returns added parameters.
/// </summary>
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;
}
/// <summary>
/// Adds otherMd parameters to thisMd and returns added parameters.
/// </summary>
public static List<ParameterDefinition> CreateParameters(this MethodDefinition thisMd, CodegenSession session, MethodDefinition otherMd)
{
List<ParameterDefinition> 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;
}
/// <summary>
/// Returns a method reference while considering if declaring type is generic.
/// </summary>
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;
}
}
/// <summary>
/// Returns a method reference for a generic method.
/// </summary>
public static MethodReference GetMethodReference(this MethodDefinition md, CodegenSession session, TypeReference typeReference)
{
MethodReference methodRef = session.ImportReference(md);
return methodRef.GetMethodReference(session, typeReference);
}
/// <summary>
/// Removes ret if it exist at the end of the method. Returns if ret was removed.
/// </summary>
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;
}
}
/// <summary>
/// Returns a method reference for a generic method.
/// </summary>
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;
}
/// <summary>
/// Makes a method definition public.
/// </summary>
public static void SetPublicAttributes(this MethodDefinition md)
{
md.Attributes = PUBLIC_VIRTUAL_ATTRIBUTES;
}
public static void SetProtectedAttributes(this MethodDefinition md)
{
md.Attributes = PROTECTED_VIRTUAL_ATTRIBUTES;
}
}
}
@@ -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
@@ -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
{
/// <summary>
/// Returns if a TypeDefinition is nullable.
/// </summary>
public static bool IsNullable(this TypeDefinition td)
{
return td.Name == typeof(System.Nullable<>).Name;
}
/// <summary>
/// Finds the first method by a given name.
/// </summary>
/// <param name = "typeDef"></param>
/// <param name = "methodName"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Returns a method in the next base class.
/// </summary>
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);
}
/// <summary>
/// Returns a method in the next base class.
/// </summary>
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);
}
/// <summary>
/// Gets a MethodReference or creates one if missing.
/// </summary>
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);
}
/// <summary>
/// Gets a MethodDefinition or creates one if missing.
/// </summary>
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;
}
/// <summary>
/// Gets a MethodDefinition or creates one if missing.
/// </summary>
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;
}
/// <summary>
/// Returns a method in any inherited classes. The first found method is returned.
/// </summary>
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;
}
/// <summary>
/// Returns a TypeDefintiion found in typeDef or up it's hierarchy.
/// </summary>
/// <param name = "checkTypeDef">True to check if typeDef equals fullName.</param>
/// <returns></returns>
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;
}
/// <summary>
/// Returns the next base type.
/// </summary>
public static TypeDefinition GetNextBaseTypeDefinition(this TypeDefinition typeDef, CodegenSession session)
{
return typeDef.BaseType == null ? null : typeDef.BaseType.CachedResolve(session);
}
/// <summary>
/// Creates a FieldReference.
/// </summary>
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);
}
}
/// <summary>
/// Gets a FieldReference or creates it if missing.
/// </summary>
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;
}
/// <summary>
/// Creates a FieldReference.
/// </summary>
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);
}
/// <summary>
/// Makes a GenericInstanceType.
/// </summary>
public static GenericInstanceType MakeGenericInstanceType(this TypeDefinition self, CodegenSession session)
{
TypeReference tr = session.ImportReference(self);
return tr.MakeGenericInstanceType();
}
}
}
@@ -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
@@ -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
{
/// <summary>
/// Returns if a TypeReference is nullable.
/// </summary>
public static bool IsNullable(this TypeReference tr, CodegenSession session)
{
TypeDefinition td = tr.CachedResolve(session);
return td.IsNullable();
}
/// <summary>
/// Returns the fullname of a TypeReference without <>.
/// </summary>
/// <param name = "tr"></param>
/// <returns></returns>
public static string GetFullnameWithoutBrackets(this TypeReference tr)
{
string str = tr.FullName;
str = str.Replace("<", "");
str = str.Replace(">", "");
return str;
}
/// <summary>
/// Makes a GenericInstanceType.
/// </summary>
public static GenericInstanceType MakeGenericInstanceType(this TypeReference self)
{
GenericInstanceType instance = new(self);
foreach (GenericParameter argument in self.GenericParameters)
instance.GenericArguments.Add(argument);
return instance;
}
}
}
@@ -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