Ejemplo n.º 1
0
        public override void ProcessClass(Type classType, ClassDefinition classDef)
        {
            MethodInfo[] remoteMethods = remoteType.GetMethods();

            bool isServer = !classType.IsSubclassOf(typeof(ClientScope));

            // create and setup writer
            ClassDefinition fakeRemoteClass = new ClassDefinition(string.Format("Remote{0}", remoteType.Name));
            {
                fakeRemoteClass.imports.Add("System.Collections.Generic");
                fakeRemoteClass.imports.Add("UnityEngine.Networking");

                // add interface sender field
                fakeRemoteClass.AddField("_netSender", "INetworkSender", false);

                // add constructor method
                MethodDefinition ctor = new MethodDefinition(fakeRemoteClass.Name);
                ctor.IsConstructor = true;
                ctor.parameters.Add(new ParameterDefinition("netSender", "INetworkSender"));
                fakeRemoteClass.methods.Add(ctor);

                // assign it in the body
                ctor.instructions.AddInstruction("_netSender = netSender;");
            }


            // find remote methods with "Signal" attribute; the SEND methods
            bool didCreateAnySendMethods = false;

            foreach (MethodInfo remoteMethod in remoteMethods)
            {
                if (ReflectionUtility.ContainsAttribute <Signal>(remoteMethod))
                {
                    // create send remote method
                    MethodDefinition fakeMethodDef = CreateSendMethod(remoteMethod);

                    // if method call wasn't found, mark it invalid
                    if (fakeMethodDef == null)
                    {
                        classDef.IsInvalid = true;
                        continue;
                    }
                    // otherwise add it to the list of methods in the inner remote class
                    fakeRemoteClass.methods.Add(fakeMethodDef);

                    // flag that send methods were created to allow the class to be created in a future check
                    didCreateAnySendMethods = true;
                }
            }

            // find local methods with "Signal" attribute; the RECEIVE methods
            foreach (MethodInfo localMethod in classType.GetMethods())
            {
                if (ReflectionUtility.ContainsAttribute <Signal>(localMethod))
                {
                    // create send remote method
                    MethodDefinition localMethodDef = CreateReceiveMethod(localMethod);

                    // if method call wasn't found, mark it invalid
                    if (localMethodDef == null)
                    {
                        classDef.IsInvalid = true;
                    }
                    // otherwise add it to the lsit of methods within the partial class
                    else
                    {
                        classDef.methods.Add(localMethodDef);
                    }
                }
            }

            // add SEND-specific code - ONLY if there's any any send methods generated earlier
            if (didCreateAnySendMethods)
            {
                classDef.classes.Add(fakeRemoteClass);

                if (isServer)
                {
                    string peerTypeName = classType.BaseType.GetGenericArguments()[0].FullName;

                    classDef.AddField("_Remote", fakeRemoteClass.Name, false);

                    // send method (single-peer)
                    MethodDefinition sendPeerMethod = new MethodDefinition("SendToPeer");
                    sendPeerMethod.ReturnType = fakeRemoteClass.Name;
                    sendPeerMethod.parameters.Add(new ParameterDefinition("targetPeer", peerTypeName));

                    sendPeerMethod.instructions.AddInlineIfCheck("_Remote == null", string.Format("_Remote = new {0}(this);", fakeRemoteClass.Name));
                    sendPeerMethod.instructions.AddInstruction("TargetPeer = targetPeer;");
                    sendPeerMethod.instructions.AddInstruction("return _Remote;");

                    classDef.methods.Add(sendPeerMethod);

                    // reply method (single-peer - last sender)
                    sendPeerMethod            = new MethodDefinition("ReplyToPeer");
                    sendPeerMethod.ReturnType = fakeRemoteClass.Name;

                    sendPeerMethod.instructions.AddInlineIfCheck("_Remote == null", string.Format("_Remote = new {0}(this);", fakeRemoteClass.Name));
                    sendPeerMethod.instructions.AddInstruction("TargetPeer = SenderPeer;");
                    sendPeerMethod.instructions.AddInstruction("return _Remote;");

                    classDef.methods.Add(sendPeerMethod);

                    // send method (multi-peer)
                    sendPeerMethod            = new MethodDefinition("SendToPeers");
                    sendPeerMethod.ReturnType = fakeRemoteClass.Name;
                    sendPeerMethod.parameters.Add(new ParameterDefinition("targetPeerGroup", string.Format("IEnumerable<{0}>", peerTypeName)));

                    sendPeerMethod.instructions.AddInlineIfCheck("_Remote == null", string.Format("_Remote = new {0}(this);", fakeRemoteClass.Name));
                    sendPeerMethod.instructions.AddInstruction("TargetPeerGroup = targetPeerGroup;");
                    sendPeerMethod.instructions.AddInstruction("return _Remote;");

                    classDef.methods.Add(sendPeerMethod);
                }
                else
                {
                    // add the 'Server' property by that type
                    classDef.AddField("_Remote", fakeRemoteClass.Name, false);
                    var prop = classDef.AddProperty("SendToServer", fakeRemoteClass.Name);
                    prop.getterBody = new MethodBodyDefinition();

                    prop.getterBody.AddInlineIfCheck("_Remote == null", string.Format("_Remote = new {0}(this);", fakeRemoteClass.Name));
                    prop.getterBody.AddInstruction("return _Remote;");
                }
            }
        }