MethodReference GenerateDeserialization()
        {
            Weaver.DLog(m_TypeDef, "  GenerateDeserialization");
            foreach (var m in m_TypeDef.Methods)
            {
                if (m.Name == "DeserializeItem")
                {
                    return(m);
                }
            }

            MethodDefinition serializeFunc = new MethodDefinition("DeserializeItem", MethodAttributes.Public |
                                                                  MethodAttributes.Virtual |
                                                                  MethodAttributes.Public |
                                                                  MethodAttributes.HideBySig,
                                                                  m_ItemType);

            serializeFunc.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkReaderType)));

            ILProcessor serWorker = serializeFunc.Body.GetILProcessor();

            serWorker.Body.InitLocals = true;
            serWorker.Body.Variables.Add(new VariableDefinition(m_ItemType));

            // init item instance
            serWorker.Append(serWorker.Create(OpCodes.Ldloca, 0));
            serWorker.Append(serWorker.Create(OpCodes.Initobj, m_ItemType));


            foreach (var field in m_ItemType.Resolve().Fields)
            {
                if (field.IsStatic || field.IsPrivate || field.IsSpecialName)
                {
                    continue;
                }

                var importedField = Weaver.scriptDef.MainModule.ImportReference(field);
                var ft            = importedField.FieldType.Resolve();

                MethodReference readerFunc = Weaver.GetReadFunc(field.FieldType);
                if (readerFunc != null)
                {
                    serWorker.Append(serWorker.Create(OpCodes.Ldloca, 0));
                    serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
                    serWorker.Append(serWorker.Create(OpCodes.Call, readerFunc));
                    serWorker.Append(serWorker.Create(OpCodes.Stfld, importedField));
                }
                else
                {
                    Weaver.fail = true;
                    Log.Error("GenerateDeserialization for " + m_TypeDef.Name + " unknown type [" + ft + "]. UNet [SyncVar] member variables must be basic types.");
                    return(null);
                }
            }
            serWorker.Append(serWorker.Create(OpCodes.Ldloc_0));
            serWorker.Append(serWorker.Create(OpCodes.Ret));

            m_TypeDef.Methods.Add(serializeFunc);
            return(serializeFunc);
        }
Пример #2
0
        void GenerateDeSerialization()
        {
            Weaver.DLog(m_td, "  GenerateDeserialization");
            foreach (var m in m_td.Methods)
            {
                if (m.Name == "Deserialize")
                {
                    return;
                }
            }

            if (m_td.Fields.Count == 0)
            {
                return;
            }

            MethodDefinition serializeFunc = new MethodDefinition("Deserialize", MethodAttributes.Public |
                                                                  MethodAttributes.Virtual |
                                                                  MethodAttributes.HideBySig,
                                                                  Weaver.voidType);

            serializeFunc.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkReaderType)));
            ILProcessor serWorker = serializeFunc.Body.GetILProcessor();

            foreach (var field in m_td.Fields)
            {
                if (field.IsStatic || field.IsPrivate || field.IsSpecialName)
                {
                    continue;
                }

                MethodReference readerFunc = Weaver.GetReadFunc(field.FieldType);
                if (readerFunc != null)
                {
                    serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
                    serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
                    serWorker.Append(serWorker.Create(OpCodes.Call, readerFunc));
                    serWorker.Append(serWorker.Create(OpCodes.Stfld, field));
                }
                else
                {
                    Weaver.fail = true;
                    Log.Error("GenerateDeSerialization for " + m_td.Name + " unknown type [" + field.FieldType + "]. [SyncVar] member variables must be basic types.");
                    return;
                }
            }
            serWorker.Append(serWorker.Create(OpCodes.Ret));

            m_td.Methods.Add(serializeFunc);
        }
Пример #3
0
        static MethodReference GenerateDeserialization(string methodName, TypeDefinition td, TypeReference itemType)
        {
            Weaver.DLog(td, "  GenerateDeserialization");
            foreach (var m in td.Methods)
            {
                if (m.Name == methodName)
                {
                    return(m);
                }
            }

            MethodDefinition deserializeFunction = new MethodDefinition(methodName, MethodAttributes.Public |
                                                                        MethodAttributes.Virtual |
                                                                        MethodAttributes.Public |
                                                                        MethodAttributes.HideBySig,
                                                                        itemType);

            deserializeFunction.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkReaderType)));

            ILProcessor serWorker = deserializeFunction.Body.GetILProcessor();

            MethodReference readerFunc = Weaver.GetReadFunc(itemType);

            if (readerFunc != null)
            {
                serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
                serWorker.Append(serWorker.Create(OpCodes.Call, readerFunc));
                serWorker.Append(serWorker.Create(OpCodes.Ret));
            }
            else
            {
                Weaver.Error("GenerateDeserialization for " + td.Name + " unknown type [" + itemType + "]. Member variables must be basic types.");
                return(null);
            }

            td.Methods.Add(deserializeFunction);
            return(deserializeFunction);
        }
Пример #4
0
        public static bool ProcessNetworkReaderParameters(TypeDefinition td, MethodDefinition md, ILProcessor worker, bool skipFirst)
        {
            int count = 0;

            // read cmd args from NetworkReader
            foreach (ParameterDefinition arg in md.Parameters)
            {
                if (count++ == 0 && skipFirst)
                {
                    continue;
                }
                MethodReference readFunc = Weaver.GetReadFunc(arg.ParameterType); //?

                if (readFunc != null)
                {
                    worker.Append(worker.Create(OpCodes.Ldarg_1));
                    worker.Append(worker.Create(OpCodes.Call, readFunc));

                    // conversion.. is this needed?
                    if (arg.ParameterType.FullName == Weaver.singleType.FullName)
                    {
                        worker.Append(worker.Create(OpCodes.Conv_R4));
                    }
                    else if (arg.ParameterType.FullName == Weaver.doubleType.FullName)
                    {
                        worker.Append(worker.Create(OpCodes.Conv_R8));
                    }
                }
                else
                {
                    Log.Error("ProcessNetworkReaderParameters for " + td.Name + ":" + md.Name + " type " + arg.ParameterType + " not supported");
                    Weaver.fail = true;
                    return(false);
                }
            }
            return(true);
        }
Пример #5
0
        void GenerateDeSerialization()
        {
            Weaver.DLog(m_td, "  GenerateDeSerialization");

            foreach (MethodDefinition m in m_td.Methods)
            {
                if (m.Name == "OnDeserialize")
                {
                    return;
                }
            }

            if (m_SyncVars.Count == 0)
            {
                // no synvars,  no need for custom OnDeserialize
                return;
            }

            MethodDefinition serialize = new MethodDefinition("OnDeserialize",
                                                              MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig,
                                                              Weaver.voidType);

            serialize.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkReaderType)));
            serialize.Parameters.Add(new ParameterDefinition("initialState", ParameterAttributes.None, Weaver.boolType));
            ILProcessor serWorker = serialize.Body.GetILProcessor();

            MethodReference baseDeserialize = Resolvers.ResolveMethodInParents(m_td.BaseType, Weaver.scriptDef, "OnDeserialize");

            if (baseDeserialize != null)
            {
                serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // base
                serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); // reader
                serWorker.Append(serWorker.Create(OpCodes.Ldarg_2)); // initialState
                serWorker.Append(serWorker.Create(OpCodes.Call, baseDeserialize));
            }

            // Generates: if (initialState);
            Instruction initialStateLabel = serWorker.Create(OpCodes.Nop);

            serWorker.Append(serWorker.Create(OpCodes.Ldarg_2));
            serWorker.Append(serWorker.Create(OpCodes.Brfalse, initialStateLabel));

            foreach (FieldDefinition syncVar in m_SyncVars)
            {
                // assign value
                serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
                serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));

                if (syncVar.FieldType.FullName == Weaver.gameObjectType.FullName ||
                    syncVar.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
                {
                    // GameObject/NetworkIdentity SyncVar:
                    //   OnSerialize sends writer.Write(go);
                    //   OnDeserialize reads to __netId manually so we can use
                    //     lookups in the getter (so it still works if objects
                    //     move in and out of range repeatedly)
                    FieldDefinition netIdField = m_SyncVarNetIds[syncVar];

                    serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.NetworkReaderReadPacked32));
                    serWorker.Append(serWorker.Create(OpCodes.Stfld, netIdField));
                }
                else
                {
                    MethodReference readFunc = Weaver.GetReadFunc(syncVar.FieldType);
                    if (readFunc != null)
                    {
                        serWorker.Append(serWorker.Create(OpCodes.Call, readFunc));
                    }
                    else
                    {
                        Log.Error("GenerateDeSerialization for " + m_td.Name + " unknown type [" + syncVar.FieldType + "]. UNet [SyncVar] member variables must be basic types.");
                        Weaver.fail = true;
                        return;
                    }
                    serWorker.Append(serWorker.Create(OpCodes.Stfld, syncVar));
                }
            }

            serWorker.Append(serWorker.Create(OpCodes.Ret));

            // Generates: end if (initialState);
            serWorker.Append(initialStateLabel);

            // setup local for dirty bits
            serialize.Body.InitLocals = true;
            VariableDefinition dirtyBitsLocal = new VariableDefinition(Weaver.int64Type);

            serialize.Body.Variables.Add(dirtyBitsLocal);

            // get dirty bits
            serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
            serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.NetworkReaderReadPacked64));
            serWorker.Append(serWorker.Create(OpCodes.Stloc_0));

            // conditionally read each syncvar
            int dirtyBit = Weaver.GetSyncVarStart(m_td.BaseType.FullName); // start at number of syncvars in parent

            foreach (FieldDefinition syncVar in m_SyncVars)
            {
                Instruction varLabel = serWorker.Create(OpCodes.Nop);

                // check if dirty bit is set
                serWorker.Append(serWorker.Create(OpCodes.Ldloc_0));
                serWorker.Append(serWorker.Create(OpCodes.Ldc_I8, 1L << dirtyBit));
                serWorker.Append(serWorker.Create(OpCodes.And));
                serWorker.Append(serWorker.Create(OpCodes.Brfalse, varLabel));

                // check for Hook function
                MethodDefinition foundMethod;
                if (!SyncVarProcessor.CheckForHookFunction(m_td, syncVar, out foundMethod))
                {
                    return;
                }

                if (syncVar.FieldType.FullName == Weaver.gameObjectType.FullName ||
                    syncVar.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
                {
                    // GameObject/NetworkIdentity SyncVar:
                    //   OnSerialize sends writer.Write(go);
                    //   OnDeserialize reads to __netId manually so we can use
                    //     lookups in the getter (so it still works if objects
                    //     move in and out of range repeatedly)
                    FieldDefinition netIdField = m_SyncVarNetIds[syncVar];

                    if (foundMethod == null)
                    {
                        serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
                        serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
                        serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.NetworkReaderReadPacked32));
                        serWorker.Append(serWorker.Create(OpCodes.Stfld, netIdField));
                    }
                    else
                    {
                        // call Hook(this.GetSyncVarGameObject/NetworkIdentity(reader.ReadPackedUInt32()))
                        // because we send/receive the netID, not the GameObject/NetworkIdentity
                        serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // this.
                        serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
                        serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
                        serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.NetworkReaderReadPacked32));
                        serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
                        serWorker.Append(serWorker.Create(OpCodes.Ldflda, syncVar));
                        if (syncVar.FieldType.FullName == Weaver.gameObjectType.FullName)
                        {
                            serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.getSyncVarGameObjectReference));
                        }
                        else if (syncVar.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
                        {
                            serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.getSyncVarNetworkIdentityReference));
                        }
                        serWorker.Append(serWorker.Create(OpCodes.Call, foundMethod));
                    }
                }
                else
                {
                    MethodReference readFunc = Weaver.GetReadFunc(syncVar.FieldType);
                    if (readFunc == null)
                    {
                        Log.Error("GenerateDeSerialization for " + m_td.Name + " unknown type [" + syncVar.FieldType + "]. UNet [SyncVar] member variables must be basic types.");
                        Weaver.fail = true;
                        return;
                    }

                    if (foundMethod == null)
                    {
                        // just assign value
                        serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
                        serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
                        serWorker.Append(serWorker.Create(OpCodes.Call, readFunc));
                        serWorker.Append(serWorker.Create(OpCodes.Stfld, syncVar));
                    }
                    else
                    {
                        // call hook instead
                        serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
                        serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
                        serWorker.Append(serWorker.Create(OpCodes.Call, readFunc));
                        serWorker.Append(serWorker.Create(OpCodes.Call, foundMethod));
                    }
                }
                serWorker.Append(varLabel);
                dirtyBit += 1;
            }

            if (Weaver.generateLogErrors)
            {
                serWorker.Append(serWorker.Create(OpCodes.Ldstr, "Injected Deserialize " + m_td.Name));
                serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.logErrorReference));
            }

            serWorker.Append(serWorker.Create(OpCodes.Ret));
            m_td.Methods.Add(serialize);
        }
Пример #6
0
        void DeserializeField(FieldDefinition syncVar, ILProcessor serWorker)
        {
            // check for Hook function
            MethodDefinition foundMethod;

            if (!SyncVarProcessor.CheckForHookFunction(m_td, syncVar, out foundMethod))
            {
                return;
            }

            if (syncVar.FieldType.FullName == Weaver.gameObjectType.FullName ||
                syncVar.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
            {
                // GameObject/NetworkIdentity SyncVar:
                //   OnSerialize sends writer.Write(go);
                //   OnDeserialize reads to __netId manually so we can use
                //     lookups in the getter (so it still works if objects
                //     move in and out of range repeatedly)
                FieldDefinition netIdField = m_SyncVarNetIds[syncVar];

                if (foundMethod == null)
                {
                    serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
                    serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
                    serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.NetworkReaderReadPacked32));
                    serWorker.Append(serWorker.Create(OpCodes.Stfld, netIdField));
                }
                else
                {
                    // call Hook(this.GetSyncVarGameObject/NetworkIdentity(reader.ReadPackedUInt32()))
                    // because we send/receive the netID, not the GameObject/NetworkIdentity
                    serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // this.
                    serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
                    serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
                    serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.NetworkReaderReadPacked32));
                    serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
                    serWorker.Append(serWorker.Create(OpCodes.Ldflda, syncVar));
                    if (syncVar.FieldType.FullName == Weaver.gameObjectType.FullName)
                    {
                        serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.getSyncVarGameObjectReference));
                    }
                    else if (syncVar.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
                    {
                        serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.getSyncVarNetworkIdentityReference));
                    }
                    serWorker.Append(serWorker.Create(OpCodes.Call, foundMethod));
                }
            }
            else
            {
                MethodReference readFunc = Weaver.GetReadFunc(syncVar.FieldType);
                if (readFunc == null)
                {
                    Weaver.Error("GenerateDeSerialization for " + m_td.Name + " unknown type [" + syncVar.FieldType + "]. Mirror [SyncVar] member variables must be basic types.");
                    return;
                }

                if (foundMethod == null)
                {
                    // just assign value
                    serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
                    serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
                    serWorker.Append(serWorker.Create(OpCodes.Call, readFunc));
                    serWorker.Append(serWorker.Create(OpCodes.Stfld, syncVar));
                }
                else
                {
                    // call hook instead
                    serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
                    serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
                    serWorker.Append(serWorker.Create(OpCodes.Call, readFunc));
                    serWorker.Append(serWorker.Create(OpCodes.Call, foundMethod));
                }
            }
        }