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); }
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); }
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); }
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); }
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); }
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)); } } }