Beispiel #1
0
        void ProcessMethod(MethodDefinition md, FoundType foundType)
        {
            if (IgnoreMethod(md))
            {
                return;
            }

            ProcessMethodAttributes(md, foundType);
        }
Beispiel #2
0
 void ProcessMethodAttributes(MethodDefinition md, FoundType foundType)
 {
     InjectGuard <ServerAttribute>(md, foundType, IsServer, "[Server] function '{0}' called when server not active");
     InjectGuard <ClientAttribute>(md, foundType, IsClient, "[Client] function '{0}' called when client not active");
     InjectGuard <HasAuthorityAttribute>(md, foundType, HasAuthority, "[Has Authority] function '{0}' called on player without authority");
     InjectGuard <LocalPlayerAttribute>(md, foundType, IsLocalPlayer, "[Local Player] function '{0}' called on nonlocal player");
     CheckAttribute <ServerRpcAttribute>(md, foundType);
     CheckAttribute <ClientRpcAttribute>(md, foundType);
 }
Beispiel #3
0
        /// <summary>
        /// Check if Syncvar or SyncObject are used outside of NetworkBehaviour
        /// </summary>
        /// <param name="fd"></param>
        /// <param name="foundType"></param>
        void ProcessFields(FieldDefinition fd, FoundType foundType)
        {
            if (fd.HasCustomAttribute <SyncVarAttribute>())
            {
                logger.Error($"SyncVar {fd.Name} must be inside a NetworkBehaviour. {foundType.TypeDefinition.Name} is not a NetworkBehaviour", fd);
            }

            // only check SyncObjects inside Monobehaviours
            if (foundType.IsMonoBehaviour && SyncObjectProcessor.ImplementsSyncObject(fd.FieldType))
            {
                logger.Error($"{fd.Name} is a SyncObject and can not be used inside Monobehaviour. {foundType.TypeDefinition.Name} is not a NetworkBehaviour", fd);
            }
        }
Beispiel #4
0
        void CheckAttribute <TAttribute>(MethodDefinition md, FoundType foundType)
        {
            CustomAttribute attribute = md.GetCustomAttribute <TAttribute>();

            if (attribute == null)
            {
                return;
            }

            if (!foundType.IsNetworkBehaviour)
            {
                logger.Error($"{attribute.AttributeType.Name} method {md.Name} must be declared in a NetworkBehaviour", md);
            }
        }
Beispiel #5
0
        void ProcessType(FoundType foundType)
        {
            foreach (MethodDefinition md in foundType.TypeDefinition.Methods)
            {
                ProcessMethod(md, foundType);
            }

            if (!foundType.IsNetworkBehaviour)
            {
                foreach (FieldDefinition fd in foundType.TypeDefinition.Fields)
                {
                    ProcessFields(fd, foundType);
                }
            }
        }
Beispiel #6
0
        void InjectGuard <TAttribute>(MethodDefinition md, FoundType foundType, MethodReference predicate, string format)
        {
            CustomAttribute attribute = md.GetCustomAttribute <TAttribute>();

            if (attribute == null)
            {
                return;
            }

            if (md.IsAbstract)
            {
                logger.Error($"{typeof(TAttribute)} can't be applied to abstract method. Apply to override methods instead.", md);
                return;
            }

            if (!foundType.IsNetworkBehaviour)
            {
                logger.Error($"{attribute.AttributeType.Name} method {md.Name} must be declared in a NetworkBehaviour", md);
                return;
            }

            if (md.Name == "Awake" && !md.HasParameters)
            {
                logger.Error($"{attribute.AttributeType.Name} will not work on the Awake method.", md);
                return;
            }

            // dont need to set modified for errors, so we set it here when we start doing ILProcessing
            modified = true;

            bool        throwError = attribute.GetField("error", true);
            ILProcessor worker     = md.Body.GetILProcessor();
            Instruction top        = md.Body.Instructions[0];

            worker.InsertBefore(top, worker.Create(OpCodes.Ldarg_0));
            worker.InsertBefore(top, worker.Create(OpCodes.Call, predicate));
            worker.InsertBefore(top, worker.Create(OpCodes.Brtrue, top));
            if (throwError)
            {
                string message = string.Format(format, md.Name);
                worker.InsertBefore(top, worker.Create(OpCodes.Ldstr, message));
                worker.InsertBefore(top, worker.Create(OpCodes.Newobj, () => new MethodInvocationException("")));
                worker.InsertBefore(top, worker.Create(OpCodes.Throw));
            }
            InjectGuardParameters(md, worker, top);
            InjectGuardReturnValue(md, worker, top);
            worker.InsertBefore(top, worker.Create(OpCodes.Ret));
        }
Beispiel #7
0
        /// <summary>
        /// Returns all base types that are between the type and NetworkBehaviour
        /// </summary>
        /// <param name="foundType"></param>
        /// <returns></returns>
        static List <TypeDefinition> FindAllBaseTypes(FoundType foundType)
        {
            var behaviourClasses = new List <TypeDefinition>();

            TypeDefinition type = foundType.TypeDefinition;

            while (type != null)
            {
                if (type.Is <NetworkBehaviour>())
                {
                    break;
                }

                behaviourClasses.Add(type);
                type = type.BaseType.TryResolve();
            }

            return(behaviourClasses);
        }
Beispiel #8
0
        bool WeaveNetworkBehavior(FoundType foundType)
        {
            List <TypeDefinition> behaviourClasses = FindAllBaseTypes(foundType);

            bool modified = false;

            // process this and base classes from parent to child order
            for (int i = behaviourClasses.Count - 1; i >= 0; i--)
            {
                TypeDefinition behaviour = behaviourClasses[i];
                if (NetworkBehaviourProcessor.WasProcessed(behaviour))
                {
                    continue;
                }

                modified |= new NetworkBehaviourProcessor(behaviour, readers, writers, propertySiteProcessor, logger).Process();
            }
            return(modified);
        }