fishnet installed
This commit is contained in:
@ -0,0 +1,68 @@
|
||||
using FishNet.CodeGenerating.Helping;
|
||||
using FishNet.Object.Helping;
|
||||
using MonoFN.Cecil;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FishNet.CodeGenerating.Processing.Rpc
|
||||
{
|
||||
internal static class AttributeDataExtensions
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Returns RpcTypes in datas.
|
||||
/// </summary>
|
||||
public static List<RpcType> GetRpcTypes(this List<AttributeData> datas)
|
||||
{
|
||||
//RpcTypes for originalMd.
|
||||
List<RpcType> rpcTypes = new List<RpcType>();
|
||||
foreach (AttributeData ad in datas)
|
||||
rpcTypes.Add(ad.RpcType);
|
||||
|
||||
return rpcTypes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets CustomAttribute for rpcType
|
||||
/// </summary>
|
||||
public static CustomAttribute GetAttribute(this List<AttributeData> datas, CodegenSession session, RpcType rpcType)
|
||||
{
|
||||
for (int i = 0; i < datas.Count; i++)
|
||||
{
|
||||
if (datas[i].RpcType == rpcType)
|
||||
return datas[i].Attribute;
|
||||
}
|
||||
|
||||
session.LogError($"RpcType {rpcType} not found in datas.");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns RpcType as flag through combining datas.
|
||||
/// </summary>
|
||||
/// <param name="datas"></param>
|
||||
/// <returns></returns>
|
||||
public static RpcType GetCombinedRpcType(this List<AttributeData> datas)
|
||||
{
|
||||
RpcType result = RpcType.None;
|
||||
for (int i = 0; i < datas.Count; i++)
|
||||
result |= datas[i].RpcType;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
internal class AttributeData
|
||||
{
|
||||
public readonly CustomAttribute Attribute;
|
||||
public readonly RpcType RpcType;
|
||||
|
||||
public AttributeData(CustomAttribute attribute, RpcType rpcType)
|
||||
{
|
||||
Attribute = attribute;
|
||||
RpcType = rpcType;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 91f84e00db3d1ad448fb6a760afb6927
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
166
Assets/FishNet/CodeGenerating/Processing/Rpc/Attributes.cs
Normal file
166
Assets/FishNet/CodeGenerating/Processing/Rpc/Attributes.cs
Normal file
@ -0,0 +1,166 @@
|
||||
using FishNet.CodeGenerating.Helping;
|
||||
using FishNet.CodeGenerating.Helping.Extension;
|
||||
using FishNet.Connection;
|
||||
using FishNet.Object.Helping;
|
||||
using MonoFN.Cecil;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace FishNet.CodeGenerating.Processing.Rpc
|
||||
{
|
||||
internal class Attributes : CodegenBase
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Returns if methodDef has any Rpc attribute.
|
||||
/// </summary>
|
||||
public bool HasRpcAttributes(MethodDefinition methodDef)
|
||||
{
|
||||
foreach (CustomAttribute customAttribute in methodDef.CustomAttributes)
|
||||
{
|
||||
RpcType rt = base.Session.GetClass<AttributeHelper>().GetRpcAttributeType(customAttribute);
|
||||
if (rt != RpcType.None)
|
||||
return true;
|
||||
}
|
||||
|
||||
//Fall through, nothing found.
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a collection of RpcAttribute for methodDef.
|
||||
/// </summary>
|
||||
public List<AttributeData> GetRpcAttributes(MethodDefinition methodDef)
|
||||
{
|
||||
List<AttributeData> results = new List<AttributeData>();
|
||||
string asyncAttributeFullName = typeof(AsyncStateMachineAttribute).FullName;
|
||||
bool isAsync = false;
|
||||
|
||||
foreach (CustomAttribute customAttribute in methodDef.CustomAttributes)
|
||||
{
|
||||
RpcType rt = base.Session.GetClass<AttributeHelper>().GetRpcAttributeType(customAttribute);
|
||||
if (rt != RpcType.None)
|
||||
{
|
||||
results.Add(new AttributeData(customAttribute, rt));
|
||||
}
|
||||
//Not a rpc attribute.
|
||||
else
|
||||
{
|
||||
//Check if async.
|
||||
if (customAttribute.Is(asyncAttributeFullName))
|
||||
isAsync = true;
|
||||
}
|
||||
}
|
||||
|
||||
//Nothing found, exit early.
|
||||
if (results.Count == 0)
|
||||
{
|
||||
return results;
|
||||
}
|
||||
//If has at least one RPC attrivbute and is an async method.
|
||||
else if (isAsync)
|
||||
{
|
||||
base.Session.LogError($"{methodDef.Name} is an async RPC. This feature is not currently supported. You may instead run an async method from this RPC.");
|
||||
return new List<AttributeData>();
|
||||
}
|
||||
//If more than one attribute make sure the combination is allowed.
|
||||
else if (results.Count >= 2)
|
||||
{
|
||||
RpcType allRpcTypes = results.GetCombinedRpcType();
|
||||
if (allRpcTypes != (RpcType.Observers | RpcType.Target))
|
||||
{
|
||||
base.Session.LogError($"{methodDef.Name} contains multiple RPC attributes. Only ObserversRpc and TargetRpc attributes may be combined.");
|
||||
return new List<AttributeData>();
|
||||
}
|
||||
}
|
||||
|
||||
//Next validate that the method is setup properly for each rpcType.
|
||||
foreach (AttributeData ad in results)
|
||||
{
|
||||
//If not valid then return empty list.
|
||||
if (!IsRpcMethodValid(methodDef, ad.RpcType))
|
||||
return new List<AttributeData>();
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if a RpcMethod can be serialized and has a proper signature.
|
||||
/// </summary>
|
||||
private bool IsRpcMethodValid(MethodDefinition methodDef, RpcType rpcType)
|
||||
{
|
||||
//Static method.
|
||||
if (methodDef.IsStatic)
|
||||
{
|
||||
base.Session.LogError($"{methodDef.Name} RPC method cannot be static.");
|
||||
return false;
|
||||
}
|
||||
//Is generic type.
|
||||
else if (methodDef.HasGenericParameters)
|
||||
{
|
||||
base.Session.LogError($"{methodDef.Name} RPC method cannot contain generic parameters.");
|
||||
return false;
|
||||
}
|
||||
//Abstract method.
|
||||
else if (methodDef.IsAbstract)
|
||||
{
|
||||
base.Session.LogError($"{methodDef.Name} RPC method cannot be abstract.");
|
||||
return false;
|
||||
}
|
||||
//Non void return.
|
||||
else if (methodDef.ReturnType != methodDef.Module.TypeSystem.Void)
|
||||
{
|
||||
base.Session.LogError($"{methodDef.Name} RPC method must return void.");
|
||||
return false;
|
||||
}
|
||||
//Misc failing conditions.
|
||||
else
|
||||
{
|
||||
//Check for async attribute.
|
||||
foreach (CustomAttribute ca in methodDef.CustomAttributes)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
//TargetRpc but missing correct parameters.
|
||||
if (rpcType == RpcType.Target)
|
||||
{
|
||||
if (methodDef.Parameters.Count == 0 || !methodDef.Parameters[0].Is(typeof(NetworkConnection)))
|
||||
{
|
||||
base.Session.LogError($"Target RPC {methodDef.Name} must have a NetworkConnection as the first parameter.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//Make sure all parameters can be serialized.
|
||||
for (int i = 0; i < methodDef.Parameters.Count; i++)
|
||||
{
|
||||
ParameterDefinition parameterDef = methodDef.Parameters[i];
|
||||
|
||||
//If NetworkConnection, TargetRpc, and first parameter.
|
||||
if ((i == 0) && (rpcType == RpcType.Target) && parameterDef.Is(typeof(NetworkConnection)))
|
||||
continue;
|
||||
|
||||
if (parameterDef.ParameterType.IsGenericParameter)
|
||||
{
|
||||
base.Session.LogError($"RPC method{methodDef.Name} contains a generic parameter. This is currently not supported.");
|
||||
return false;
|
||||
}
|
||||
|
||||
//Can be serialized/deserialized.
|
||||
bool canSerialize = base.GetClass<GeneralHelper>().HasSerializerAndDeserializer(parameterDef.ParameterType, true);
|
||||
if (!canSerialize)
|
||||
{
|
||||
base.Session.LogError($"RPC method {methodDef.Name} parameter type {parameterDef.ParameterType.FullName} does not support serialization. Use a supported type or create a custom serializer.");
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Fall through, success.
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 974ebf09757267941a86f92e5072258c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
58
Assets/FishNet/CodeGenerating/Processing/Rpc/CreatedRpc.cs
Normal file
58
Assets/FishNet/CodeGenerating/Processing/Rpc/CreatedRpc.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using FishNet.Object.Helping;
|
||||
using MonoFN.Cecil;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FishNet.CodeGenerating.Processing.Rpc
|
||||
{
|
||||
|
||||
internal class CreatedRpc
|
||||
{
|
||||
public MethodDefinition OriginalMethodDef;
|
||||
public uint MethodHash;
|
||||
public AttributeData AttributeData;
|
||||
public MethodDefinition WriterMethodDef;
|
||||
public MethodDefinition ReaderMethodDef;
|
||||
public MethodDefinition LogicMethodDef;
|
||||
public MethodDefinition RedirectMethodDef;
|
||||
public bool RunLocally;
|
||||
|
||||
public RpcType RpcType => AttributeData.RpcType;
|
||||
public CustomAttribute Attribute => AttributeData.Attribute;
|
||||
public TypeDefinition TypeDef => OriginalMethodDef.DeclaringType;
|
||||
public ModuleDefinition Module => OriginalMethodDef.Module;
|
||||
}
|
||||
|
||||
|
||||
internal static class CreatedRpcExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns CreatedRpc for rpcType.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static CreatedRpc GetCreatedRpc(this List<CreatedRpc> lst, RpcType rpcType)
|
||||
{
|
||||
for (int i = 0; i < lst.Count; i++)
|
||||
{
|
||||
if (lst[i].RpcType == rpcType)
|
||||
return lst[i];
|
||||
}
|
||||
//Fall through.
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns combined RpcType for all entries.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static RpcType GetCombinedRpcType(this List<CreatedRpc> lst)
|
||||
{
|
||||
RpcType result = RpcType.None;
|
||||
for (int i = 0; i < lst.Count; i++)
|
||||
result |= lst[i].RpcType;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c2176b6bfcc49934d8f36fba3df74d0c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
1084
Assets/FishNet/CodeGenerating/Processing/Rpc/RpcProcessor.cs
Normal file
1084
Assets/FishNet/CodeGenerating/Processing/Rpc/RpcProcessor.cs
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d4adb5891ee44f4397cd07ac2df0ce0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user