forked from cgvr/DeltaVR
		
	
		
			
				
	
	
		
			165 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			165 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using FishNet.CodeGenerating.Helping;
 | 
						|
using FishNet.CodeGenerating.Helping.Extension;
 | 
						|
using FishNet.CodeGenerating.Processing.Rpc;
 | 
						|
using FishNet.Configuring;
 | 
						|
using FishNet.Managing.Logging;
 | 
						|
using MonoFN.Cecil;
 | 
						|
using MonoFN.Cecil.Cil;
 | 
						|
using System.Collections.Generic;
 | 
						|
using System.Linq;
 | 
						|
 | 
						|
namespace FishNet.CodeGenerating.Processing
 | 
						|
{
 | 
						|
    internal class QolAttributeProcessor : CodegenBase
 | 
						|
    {
 | 
						|
 | 
						|
        internal bool Process(TypeDefinition typeDef, bool moveStrippedCalls)
 | 
						|
        {
 | 
						|
            bool modified = false;
 | 
						|
            List<MethodDefinition> methods = typeDef.Methods.ToList();
 | 
						|
 | 
						|
            
 | 
						|
 | 
						|
            foreach (MethodDefinition md in methods)
 | 
						|
            {
 | 
						|
                //Has RPC attribute, doesn't quality for a quality of life attribute.
 | 
						|
                if (base.GetClass<RpcProcessor>().Attributes.HasRpcAttributes(md))
 | 
						|
                    continue;
 | 
						|
 | 
						|
                QolAttributeType qolType;
 | 
						|
                CustomAttribute qolAttribute = GetQOLAttribute(md, out qolType);
 | 
						|
                if (qolAttribute == null)
 | 
						|
                    continue;
 | 
						|
 | 
						|
                /* This is a one time check to make sure the qolType is
 | 
						|
                 * a supported value. Multiple methods beyond this rely on the
 | 
						|
                 * value being supported. Rather than check in each method a
 | 
						|
                 * single check is performed here. */
 | 
						|
                if (qolType != QolAttributeType.Server && qolType != QolAttributeType.Client)
 | 
						|
                {
 | 
						|
                    base.LogError($"QolAttributeType of {qolType.ToString()} is unhandled.");
 | 
						|
                    continue;
 | 
						|
                }
 | 
						|
 | 
						|
                CreateAttributeMethod(md, qolAttribute, qolType);
 | 
						|
                modified = true;
 | 
						|
            }
 | 
						|
 | 
						|
            return modified;
 | 
						|
        }
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Returns the RPC attribute on a method, if one exist. Otherwise returns null.
 | 
						|
        /// </summary>
 | 
						|
        /// <param name="methodDef"></param>
 | 
						|
        /// <param name="rpcType"></param>
 | 
						|
        /// <returns></returns>
 | 
						|
        private CustomAttribute GetQOLAttribute(MethodDefinition methodDef, out QolAttributeType qolType)
 | 
						|
        {
 | 
						|
            CustomAttribute foundAttribute = null;
 | 
						|
            qolType = QolAttributeType.None;
 | 
						|
            //Becomes true if an error occurred during this process.
 | 
						|
            bool error = false;
 | 
						|
            //Nothing to check.
 | 
						|
            if (methodDef == null || methodDef.CustomAttributes == null)
 | 
						|
                return null;
 | 
						|
 | 
						|
            foreach (CustomAttribute customAttribute in methodDef.CustomAttributes)
 | 
						|
            {
 | 
						|
                QolAttributeType thisQolType = base.GetClass<AttributeHelper>().GetQolAttributeType(customAttribute.AttributeType.FullName);
 | 
						|
                if (thisQolType != QolAttributeType.None)
 | 
						|
                {
 | 
						|
                    //A qol attribute already exist.
 | 
						|
                    if (foundAttribute != null)
 | 
						|
                    {
 | 
						|
                        base.LogError($"{methodDef.Name} {thisQolType.ToString()} method cannot have multiple quality of life attributes.");
 | 
						|
                        error = true;
 | 
						|
                    }
 | 
						|
                    ////Static method.
 | 
						|
                    //if (methodDef.IsStatic)
 | 
						|
                    //{
 | 
						|
                    //    CodegenSession.AddError($"{methodDef.Name} {thisQolType.ToString()} method cannot be static.");
 | 
						|
                    //    error = true;
 | 
						|
                    //}
 | 
						|
                    //Abstract method.
 | 
						|
                    if (methodDef.IsAbstract)
 | 
						|
                    {
 | 
						|
                        base.LogError($"{methodDef.Name} {thisQolType.ToString()} method cannot be abstract.");
 | 
						|
                        error = true;
 | 
						|
                    }
 | 
						|
 | 
						|
                    //If all checks passed.
 | 
						|
                    if (!error)
 | 
						|
                    {
 | 
						|
                        foundAttribute = customAttribute;
 | 
						|
                        qolType = thisQolType;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            //If an error occurred then reset results.
 | 
						|
            if (error)
 | 
						|
            {
 | 
						|
                foundAttribute = null;
 | 
						|
                qolType = QolAttributeType.None;
 | 
						|
            }
 | 
						|
 | 
						|
            return foundAttribute;
 | 
						|
        }
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Modifies the specified method to use QolType.
 | 
						|
        /// </summary>
 | 
						|
        private void CreateAttributeMethod(MethodDefinition methodDef, CustomAttribute qolAttribute, QolAttributeType qolType)
 | 
						|
        {
 | 
						|
            bool inheritsNetworkBehaviour = methodDef.DeclaringType.InheritsNetworkBehaviour(base.Session);
 | 
						|
 | 
						|
            //True to use InstanceFInder.
 | 
						|
            bool useStatic = (methodDef.IsStatic || !inheritsNetworkBehaviour);
 | 
						|
 | 
						|
            if (qolType == QolAttributeType.Client)
 | 
						|
            {
 | 
						|
                if (!StripMethod(methodDef))
 | 
						|
                {
 | 
						|
                    LoggingType logging = qolAttribute.GetField("Logging", LoggingType.Warning);
 | 
						|
                    /* Since isClient also uses insert first
 | 
						|
                     * it will be put ahead of the IsOwner check, since the
 | 
						|
                     * codegen processes it after IsOwner. EG... 
 | 
						|
                     * IsOwner will be added first, then IsClient will be added first over IsOwner. */
 | 
						|
                    bool requireOwnership = qolAttribute.GetField("RequireOwnership", false);
 | 
						|
                    if (requireOwnership && useStatic)
 | 
						|
                    {
 | 
						|
                        base.LogError($"Method {methodDef.Name} has a [Client] attribute which requires ownership but the method may not use this attribute. Either the method is static, or the script does not inherit from NetworkBehaviour.");
 | 
						|
                        return;
 | 
						|
                    }
 | 
						|
                    //If (!base.IsOwner);
 | 
						|
                    if (requireOwnership)
 | 
						|
                        base.GetClass<NetworkBehaviourHelper>().CreateLocalClientIsOwnerCheck(methodDef, logging, true, false, true);
 | 
						|
                    //Otherwise normal IsClient check.
 | 
						|
                    else
 | 
						|
                        base.GetClass<NetworkBehaviourHelper>().CreateIsClientCheck(methodDef, logging, useStatic, true);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else if (qolType == QolAttributeType.Server)
 | 
						|
            {
 | 
						|
                if (!StripMethod(methodDef))
 | 
						|
                {
 | 
						|
                    LoggingType logging = qolAttribute.GetField("Logging", LoggingType.Warning);
 | 
						|
                    base.GetClass<NetworkBehaviourHelper>().CreateIsServerCheck(methodDef, logging, useStatic, true);
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            bool StripMethod(MethodDefinition md)
 | 
						|
            {
 | 
						|
                
 | 
						|
 | 
						|
                //Fall through.
 | 
						|
                return false;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        
 | 
						|
    }
 | 
						|
 | 
						|
}
 |