static internal TypeInformation ParseTypeFields(Mono.Cecil.TypeDefinition type, bool onlyFieldWithGhostField = true) { bool isBuffer = CecilExtensions.IsBufferElementData(type); bool isCommandData = CecilExtensions.IsICommandData(type); var root = new TypeInformation(type); if (isBuffer) { root.AttributeMask &= ~(TypeAttribute.AttributeFlags.InterpolatedAndExtrapolated); } if (!type.HasFields) { return(root); } foreach (var field in type.Fields) { if (!field.IsPublic || field.IsStatic) { continue; } var ghostField = CecilExtensions.GetGhostFieldAttribute(type, field); if (!onlyFieldWithGhostField && isCommandData && field.HasAttributeOnMemberOImplementedInterfaces <DontSerializeForCommand>()) { continue; } if (!onlyFieldWithGhostField || (ghostField != null && ghostField.SendData)) { root.Add(ParseTypeField(field, field.FieldType, ghostField, TypeAttribute.Empty(), root.AttributeMask)); } } foreach (var prop in type.Properties) { if (prop.GetMethod == null || !prop.GetMethod.IsPublic || prop.GetMethod.IsStatic) { continue; } if (prop.SetMethod == null || !prop.SetMethod.IsPublic || prop.SetMethod.IsStatic) { continue; } var ghostField = CecilExtensions.GetGhostFieldAttribute(type, prop); if (!onlyFieldWithGhostField && isCommandData && prop.HasAttributeOnMemberOImplementedInterfaces <DontSerializeForCommand>()) { continue; } if (!onlyFieldWithGhostField || (ghostField != null && ghostField.SendData)) { root.Add(ParseTypeField(prop, prop.PropertyType, ghostField, TypeAttribute.Empty(), root.AttributeMask)); } } return(root); }
TypeInformation ParseTypeFields(Mono.Cecil.TypeDefinition type, bool onlyFieldWithGhostField = true) { var root = new TypeInformation(type); if (!type.HasFields) { return(root); } foreach (var field in type.Fields) { if (!field.IsPublic || field.IsStatic) { continue; } if (!onlyFieldWithGhostField || CecilExtensions.HasGhostFieldAttribute(type, field)) { if (!CecilExtensions.HasGhostFieldAttribute(type, field) || CecilExtensions.GetGhostFieldAttribute(type, field).SendData) { root.Add(ParseTypeField(type, field, TypeAttribute.Empty())); } } } return(root); }
public void GenerateSerializer(CodeGenerator.Context context, Mono.Cecil.TypeDefinition type) { var replacements = new Dictionary <string, string>(); if (context.FieldState.curChangeMask > 0) { replacements.Add("GHOST_CHANGE_MASK_BITS", context.FieldState.curChangeMask.ToString()); m_TargetGenerator.GenerateFragment("GHOST_FLUSH_FINAL_COMPONENT_CHANGE_MASK", replacements); } if (type.Namespace != null && type.Namespace != "") { context.imports.Add(type.Namespace); } foreach (var ns in context.imports) { replacements["GHOST_USING"] = CodeGenNamespaceUtils.GetValidNamespaceForType(context.generatedNs, ns); m_TargetGenerator.GenerateFragment("GHOST_USING_STATEMENT", replacements); } context.collectionAssemblies.Add(type.Module.Assembly.Name.Name); replacements.Clear(); replacements.Add("GHOST_NAME", type.FullName.Replace(".", "").Replace("/", "_")); replacements.Add("GHOST_NAMESPACE", context.generatedNs); replacements.Add("GHOST_COMPONENT_TYPE", type.FullName.Replace("/", ".")); replacements.Add("GHOST_CHANGE_MASK_BITS", context.FieldState.numFields.ToString()); replacements.Add("GHOST_FIELD_HASH", context.FieldState.ghostfieldHash.ToString()); replacements.Add("GHOST_COMPONENT_EXCLUDE_FROM_COLLECTION_HASH", context.IsRuntimeAssembly ? "0" : "1"); var ghostAttributes = CecilExtensions.GetGhostComponentAttribute(type); if (ghostAttributes != null && (ghostAttributes.OwnerPredictedSendType == GhostSendType.Interpolated || (ghostAttributes.PrefabType & GhostPrefabType.Client) == GhostPrefabType.InterpolatedClient)) { replacements.Add("GHOST_SEND_MASK", "GhostComponentSerializer.SendMask.Interpolated"); } else if (ghostAttributes != null && (ghostAttributes.OwnerPredictedSendType == GhostSendType.Predicted || (ghostAttributes.PrefabType & GhostPrefabType.Client) == GhostPrefabType.PredictedClient)) { replacements.Add("GHOST_SEND_MASK", "GhostComponentSerializer.SendMask.Predicted"); } else { replacements.Add("GHOST_SEND_MASK", "GhostComponentSerializer.SendMask.Interpolated | GhostComponentSerializer.SendMask.Predicted"); } replacements.Add("GHOST_SEND_CHILD_ENTITY", (ghostAttributes != null && !ghostAttributes.SendDataForChildEntity)?"0":"1"); if (m_TargetGenerator.Fragments["__GHOST_REPORT_PREDICTION_ERROR__"].Content.Length > 0) { m_TargetGenerator.GenerateFragment("GHOST_PREDICTION_ERROR_HEADER", replacements, m_TargetGenerator); } var serializerName = type.FullName.Replace("/", "+") + "Serializer.cs"; m_TargetGenerator.GenerateFile("", context.outputFolder, serializerName, replacements, context.batch); context.generatedTypes.Add(replacements["GHOST_NAME"]); }
static internal TypeInformation ParseVariantTypeFields(Mono.Cecil.TypeDefinition variantType, Mono.Cecil.TypeReference typeReference) { var type = typeReference.Resolve(); var root = new TypeInformation(type); if (!variantType.HasFields) { return(root); } foreach (var field in variantType.Fields) { if (!field.IsPublic || field.IsStatic) { continue; } if (type.Fields.FirstOrDefault(f => f.Name == field.Name) == null) { UnityEngine.Debug.LogError($"Variant {variantType.Name}. field {field.Name} not present in original type {type.Name}"); continue; } //Avoid use ghost fields modifiers for the variant type. passing null prevent that var ghostField = CecilExtensions.GetGhostFieldAttribute(null, field); if (ghostField != null && ghostField.SendData) { root.Add(ParseTypeField(field, field.FieldType, ghostField, TypeAttribute.Empty(), root.AttributeMask)); } } foreach (var prop in type.Properties) { if (prop.GetMethod == null || !prop.GetMethod.IsPublic || prop.GetMethod.IsStatic) { continue; } if (prop.SetMethod == null || !prop.SetMethod.IsPublic || prop.SetMethod.IsStatic) { continue; } if (type.Properties.FirstOrDefault(f => f.Name == prop.Name) == null) { UnityEngine.Debug.LogError($"Variant {variantType.Name}. field {prop.Name} not present in original type {type.Name}"); continue; } var ghostField = CecilExtensions.GetGhostFieldAttribute(type, prop); if (ghostField != null && ghostField.SendData) { root.Add(ParseTypeField(prop, prop.PropertyType, ghostField, TypeAttribute.Empty(), root.AttributeMask)); } } return(root); }
public TypeInformation(Mono.Cecil.TypeReference parentType, Mono.Cecil.FieldDefinition fieldInfo, TypeAttribute inheritedAttribute, string parent = null) { FieldInfo = fieldInfo; Type = fieldInfo.FieldType; Fields = new List <TypeInformation>(); Attribute = inheritedAttribute; ParseAttribute(CecilExtensions.GetGhostFieldAttribute(parentType, fieldInfo)); Parent = string.IsNullOrEmpty(parent) ? "" : parent; }
void GenerateType(Context context, Mono.Cecil.TypeDefinition type) { TypeInformation typeTree; Mono.Cecil.TypeDefinition componentType; GhostComponentAttribute ghostAttribute; var variantAttr = type.GetAttribute <GhostComponentVariationAttribute>(); if (variantAttr != null) { ghostAttribute = CecilExtensions.GetGhostComponentAttribute(type); context.VariantHash = CecilExtensions.ComputeVariantHash(type, variantAttr); var typeReference = variantAttr.ConstructorArguments.First().Value as Mono.Cecil.TypeReference; typeTree = ParseVariantTypeFields(type, typeReference); componentType = typeReference.Resolve(); } else { if (GhostAuthoringModifiers.GhostDefaultOverrides.TryGetValue(type.FullName.Replace('/', '+'), out var newComponent)) { ghostAttribute = newComponent.attribute; } else { ghostAttribute = CecilExtensions.GetGhostComponentAttribute(type); } typeTree = ParseTypeFields(type); componentType = type; } var generator = InternalGenerateType(context, typeTree, type.FullName); generator.GenerateMasks(context); var serializeGenerator = new TypeGenerator(context); generator.AppendTarget(serializeGenerator); serializeGenerator.GenerateSerializer(context, type, componentType, ghostAttribute); }