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"]); }
public CommandGenerator(CodeGenerator.Context context, Type t) { CommandType = t; var template = t == Type.Rpc ? "Packages/com.unity.netcode/Editor/CodeGenTemplates/RpcCommandSerializer.cs" : "Packages/com.unity.netcode/Editor/CodeGenTemplates/CommandDataSerializer.cs"; if (!context.typeCodeGenCache.TryGetValue(template, out var generator)) { generator = new GhostCodeGen(template); context.typeCodeGenCache.Add(template, generator); } m_CommandGenerator = generator.Clone(); }
public TypeGenerator(CodeGenerator.Context context) { var template = "Packages/com.unity.netcode/Editor/CodeGenTemplates/GhostComponentSerializer.cs"; if (!context.typeCodeGenCache.TryGetValue(template, out var generator)) { generator = new GhostCodeGen(template); context.typeCodeGenCache.Add(template, generator); } m_TargetGenerator = generator.Clone(); foreach (var frag in k_OverridableFragments.Cast <string>()) { if (!m_OverridableFragmentsList.Contains(frag)) { m_OverridableFragmentsList += " " + frag; } } ; }
public void GenerateFields(CodeGenerator.Context context, string parent = null) { if (m_Template == null) { return; } if (!context.typeCodeGenCache.TryGetValue(m_Template.TemplatePath + m_Template.TemplateOverridePath, out var generator)) { generator = new GhostCodeGen(m_Template.TemplatePath); if (!string.IsNullOrEmpty(m_Template.TemplateOverridePath)) { generator.AddTemplateOverrides(m_Template.TemplateOverridePath); } context.typeCodeGenCache.Add(m_Template.TemplatePath + m_Template.TemplateOverridePath, generator); } var fieldName = string.IsNullOrEmpty(parent) ? m_TypeInformation.FieldName : $"{parent}.{m_TypeInformation.FieldName}"; generator = generator.Clone(); generator.Replacements.Add("COMMAND_FIELD_NAME", fieldName); generator.Replacements.Add("COMMAND_FIELD_TYPE_NAME", m_TypeInformation.Type.GetFieldTypeName()); generator.GenerateFragment("COMMAND_READ", generator.Replacements, m_CommandGenerator); generator.GenerateFragment("COMMAND_WRITE", generator.Replacements, m_CommandGenerator); if (CommandType != CommandGenerator.Type.Rpc) { generator.GenerateFragment("COMMAND_READ_PACKED", generator.Replacements, m_CommandGenerator); generator.GenerateFragment("COMMAND_WRITE_PACKED", generator.Replacements, m_CommandGenerator); } if (m_TypeInformation.Type.Scope != null) { context.collectionAssemblies.Add(m_TypeInformation.Type.Scope.Name); } }
public void GenerateMasks(CodeGenerator.Context context, bool composite = false, int index = 0) { if (m_ActiveGenerator == null) { return; } var generator = m_ActiveGenerator; var target = m_TargetGenerator; var numFields = context.FieldState.numFields; var curChangeMask = context.FieldState.curChangeMask; // Mask Generation if (curChangeMask == 32) { generator.Replacements.Add("GHOST_CHANGE_MASK_BITS", numFields.ToString()); target.GenerateFragment("GHOST_FLUSH_COMPONENT_CHANGE_MASK", generator.Replacements, target, "GHOST_CALCULATE_CHANGE_MASK"); target.GenerateFragment("GHOST_REFRESH_CHANGE_MASK", generator.Replacements, target, "GHOST_READ"); target.GenerateFragment("GHOST_REFRESH_CHANGE_MASK", generator.Replacements, target, "GHOST_WRITE"); curChangeMask = 0; } generator.Replacements.Add("GHOST_MASK_INDEX", curChangeMask.ToString()); generator.Replacements.Add("GHOST_MASK_BATCH", ""); // Calculate Change Mask if ((!composite && curChangeMask == 0) || (composite && index == 0 && curChangeMask == 0)) { generator.GenerateFragment("GHOST_CALCULATE_CHANGE_MASK_ZERO", generator.Replacements, target, "GHOST_CALCULATE_CHANGE_MASK"); } else { generator.GenerateFragment("GHOST_CALCULATE_CHANGE_MASK", generator.Replacements, target, "GHOST_CALCULATE_CHANGE_MASK"); } // Serialize generator.GenerateFragment("GHOST_WRITE", generator.Replacements, target); // Deserialize generator.GenerateFragment("GHOST_READ", generator.Replacements, target); context.FieldState.curChangeMask = curChangeMask; }
public void GenerateSerializer(CodeGenerator.Context context, Mono.Cecil.TypeDefinition typeDefinition) { var replacements = new Dictionary <string, string>(); replacements.Add("COMMAND_NAME", typeDefinition.FullName.Replace(".", "").Replace("/", "_")); replacements.Add("COMMAND_NAMESPACE", context.generatedNs); replacements.Add("COMMAND_COMPONENT_TYPE", typeDefinition.FullName.Replace("/", ".")); context.collectionAssemblies.Add(typeDefinition.Module.Assembly.Name.Name); if (typeDefinition.Namespace != null && typeDefinition.Namespace != "") { context.imports.Add(typeDefinition.Namespace); } foreach (var ns in context.imports) { replacements["COMMAND_USING"] = CodeGenNamespaceUtils.GetValidNamespaceForType(context.generatedNs, ns); m_CommandGenerator.GenerateFragment("COMMAND_USING_STATEMENT", replacements); } var serializerName = typeDefinition.FullName.Replace("/", "+") + "CommandSerializer.cs"; m_CommandGenerator.GenerateFile("", context.outputFolder, serializerName, replacements, context.batch); }
public CommandGenerator(CodeGenerator.Context context, Type t, TypeInformation information, TypeTemplate template) : this(context, t) { m_TypeInformation = information; m_Template = template; }
public CommandGenerator(CodeGenerator.Context context, Type t, TypeInformation information) : this(context, t) { m_TypeInformation = information; }
public void GenerateFields(CodeGenerator.Context context, string parent = null, Dictionary <string, GhostCodeGen.FragmentData> overrides = null) { if (m_Template == null) { return; } var quantization = m_TypeInformation.Attribute.quantization; var interpolate = m_TypeInformation.Attribute.interpolate; if (!context.typeCodeGenCache.TryGetValue(m_Template.TemplatePath + m_Template.TemplateOverridePath, out var generator)) { generator = new GhostCodeGen(m_Template.TemplatePath); if (!string.IsNullOrEmpty(m_Template.TemplateOverridePath)) { generator.AddTemplateOverrides(m_Template.TemplateOverridePath); } context.typeCodeGenCache.Add(m_Template.TemplatePath + m_Template.TemplateOverridePath, generator); } generator = generator.Clone(); // Prefix and Variable Replacements var reference = string.IsNullOrEmpty(parent) ? m_TypeInformation.FieldInfo.Name : $"{parent}.{m_TypeInformation.FieldInfo.Name}"; var name = reference.Replace('.', '_'); generator.Replacements.Add("GHOST_FIELD_NAME", $"{name}"); generator.Replacements.Add("GHOST_FIELD_REFERENCE", $"{reference}"); generator.Replacements.Add("GHOST_FIELD_TYPE_NAME", m_TypeInformation.Type.GetFieldTypeName()); if (quantization > 0) { generator.Replacements.Add("GHOST_QUANTIZE_SCALE", quantization.ToString()); generator.Replacements.Add("GHOST_DEQUANTIZE_SCALE", $"{(1.0f / quantization).ToString(CultureInfo.InvariantCulture)}f"); } // Skip fragments which have been overridden already for (int i = 0; i < k_OverridableFragments.GetLength(0); i++) { if (overrides == null || !overrides.ContainsKey(k_OverridableFragments[i, 0])) { var fragment = k_OverridableFragments[i, 1]; var targetFragment = k_OverridableFragments[i, 0]; if (targetFragment == "GHOST_COPY_FROM_SNAPSHOT" && !interpolate) { fragment = "GHOST_COPY_FROM_SNAPSHOT"; } generator.GenerateFragment(fragment, generator.Replacements, m_TargetGenerator, targetFragment); } } // Imports var imports = generator.GetFragmentTemplate("GHOST_IMPORTS"); if (!string.IsNullOrEmpty(imports)) { foreach (var import in imports.Split('\n')) { if (string.IsNullOrEmpty(import)) { continue; } var matches = m_usingRegex.Matches(import); if (matches.Count == 1) { context.imports.Add(matches[0].Value); } } } ulong fieldHash = 0; fieldHash = Entities.TypeHash.CombineFNV1A64(fieldHash, Entities.TypeHash.FNV1A64(m_TypeInformation.Attribute.composite?1:0)); fieldHash = Entities.TypeHash.CombineFNV1A64(fieldHash, Entities.TypeHash.FNV1A64(m_TypeInformation.Attribute.interpolate?1:0)); fieldHash = Entities.TypeHash.CombineFNV1A64(fieldHash, (ulong)m_TypeInformation.Attribute.subtype); fieldHash = Entities.TypeHash.CombineFNV1A64(fieldHash, (ulong)m_TypeInformation.Attribute.quantization); context.FieldState.ghostfieldHash = Entities.TypeHash.CombineFNV1A64(context.FieldState.ghostfieldHash, fieldHash); if (m_TypeInformation.Type.Scope != null) { context.collectionAssemblies.Add(m_TypeInformation.Type.Scope.Name); } m_ActiveGenerator = generator; }
public TypeGenerator(CodeGenerator.Context context, TypeInformation information, TypeTemplate template) : this(context, information) { m_Template = template; }
public TypeGenerator(CodeGenerator.Context context, TypeInformation information) : this(context) { m_TypeInformation = information; }
public Dictionary <string, GhostCodeGen.FragmentData> GenerateCompositeOverrides(CodeGenerator.Context context, string parent = null) { var fragments = new Dictionary <string, GhostCodeGen.FragmentData>(); if (m_Template == null || string.IsNullOrEmpty(m_Template.TemplateOverridePath)) { return(null); } var quantization = m_TypeInformation.Attribute.quantization; var interpolate = m_TypeInformation.Attribute.interpolate; if (!context.typeCodeGenCache.TryGetValue(m_Template.TemplateOverridePath, out var generator)) { generator = new GhostCodeGen(m_Template.TemplateOverridePath); context.typeCodeGenCache.Add(m_Template.TemplateOverridePath, generator); } generator = generator.Clone(); // Prefix and Variable Replacements var reference = string.IsNullOrEmpty(parent) ? m_TypeInformation.FieldInfo.Name : $"{parent}.{m_TypeInformation.FieldInfo.Name}"; var name = reference.Replace('.', '_'); generator.Replacements.Add("GHOST_FIELD_NAME", $"{name}"); generator.Replacements.Add("GHOST_FIELD_REFERENCE", $"{reference}"); generator.Replacements.Add("GHOST_FIELD_TYPE_NAME", m_TypeInformation.Type.GetFieldTypeName()); if (quantization > 0) { generator.Replacements.Add("GHOST_QUANTIZE_SCALE", quantization.ToString()); generator.Replacements.Add("GHOST_DEQUANTIZE_SCALE", $"{(1.0f / quantization).ToString(CultureInfo.InvariantCulture)}f"); } // Type Info if (generator.GenerateFragment("GHOST_FIELD", generator.Replacements, m_TargetGenerator, null, null, true)) { fragments.Add("GHOST_FIELD", m_TargetGenerator.Fragments["__GHOST_FIELD__"]); } // CopyToSnapshot if (generator.GenerateFragment("GHOST_COPY_TO_SNAPSHOT", generator.Replacements, m_TargetGenerator, null, null, true)) { fragments.Add("GHOST_COPY_TO_SNAPSHOT", m_TargetGenerator.Fragments["__GHOST_COPY_TO_SNAPSHOT__"]); } // CopyFromSnapshot if (generator.GenerateFragment( interpolate ? "GHOST_COPY_FROM_SNAPSHOT_INTERPOLATE" : "GHOST_COPY_FROM_SNAPSHOT", generator.Replacements, m_TargetGenerator, "GHOST_COPY_FROM_SNAPSHOT", null, true)) { fragments.Add("GHOST_COPY_FROM_SNAPSHOT", generator.Fragments["__GHOST_COPY_FROM_SNAPSHOT__"]); fragments.Add("GHOST_COPY_FROM_SNAPSHOT_INTERPOLATE", generator.Fragments["__GHOST_COPY_FROM_SNAPSHOT_INTERPOLATE__"]); } // RestoreFromBackup if (generator.GenerateFragment("GHOST_RESTORE_FROM_BACKUP", generator.Replacements, m_TargetGenerator, null, null, true)) { fragments.Add("GHOST_RESTORE_FROM_BACKUP", m_TargetGenerator.Fragments["__GHOST_RESTORE_FROM_BACKUP__"]); } // PredictDelta if (generator.GenerateFragment("GHOST_PREDICT", generator.Replacements, m_TargetGenerator, null, null, true)) { fragments.Add("GHOST_PREDICT", m_TargetGenerator.Fragments["__GHOST_PREDICT__"]); } // ReportPredictionError if (generator.GenerateFragment("GHOST_REPORT_PREDICTION_ERROR", generator.Replacements, m_TargetGenerator, null, null, true)) { fragments.Add("GHOST_REPORT_PREDICTION_ERROR", m_TargetGenerator.Fragments["__GHOST_REPORT_PREDICTION_ERROR__"]); } // GetPredictionErrorName if (generator.GenerateFragment("GHOST_GET_PREDICTION_ERROR_NAME", generator.Replacements, m_TargetGenerator, null, null, true)) { fragments.Add("GHOST_GET_PREDICTION_ERROR_NAME", m_TargetGenerator.Fragments["__GHOST_GET_PREDICTION_ERROR_NAME__"]); } ValidateOverridableFragments(generator.Fragments); m_ActiveGenerator = generator; return(fragments); }
public void GenerateFields(CodeGenerator.Context context, string parent = null, Dictionary <string, GhostCodeGen.FragmentData> overrides = null) { if (m_Template == null) { return; } var quantization = m_TypeInformation.Attribute.quantization; var interpolate = m_TypeInformation.Attribute.smoothing > 0; if (!context.typeCodeGenCache.TryGetValue(m_Template.TemplatePath + m_Template.TemplateOverridePath, out var generator)) { generator = new GhostCodeGen(m_Template.TemplatePath); if (!string.IsNullOrEmpty(m_Template.TemplateOverridePath)) { generator.AddTemplateOverrides(m_Template.TemplateOverridePath); } context.typeCodeGenCache.Add(m_Template.TemplatePath + m_Template.TemplateOverridePath, generator); } generator = generator.Clone(); // Prefix and Variable Replacements var reference = string.IsNullOrEmpty(parent) ? m_TypeInformation.FieldName : $"{parent}.{m_TypeInformation.FieldName}"; var name = reference.Replace('.', '_'); generator.Replacements.Add("GHOST_FIELD_NAME", $"{name}"); generator.Replacements.Add("GHOST_FIELD_REFERENCE", $"{reference}"); generator.Replacements.Add("GHOST_FIELD_TYPE_NAME", m_TypeInformation.Type.GetFieldTypeName()); if (quantization > 0) { generator.Replacements.Add("GHOST_QUANTIZE_SCALE", quantization.ToString()); generator.Replacements.Add("GHOST_DEQUANTIZE_SCALE", $"{(1.0f / quantization).ToString(CultureInfo.InvariantCulture)}f"); } float maxSmoothingDistSq = m_TypeInformation.Attribute.maxSmoothingDist * m_TypeInformation.Attribute.maxSmoothingDist; bool enableExtrapolation = m_TypeInformation.Attribute.smoothing == (uint)TypeAttribute.AttributeFlags.InterpolatedAndExtrapolated; generator.Replacements.Add("GHOST_MAX_INTERPOLATION_DISTSQ", maxSmoothingDistSq.ToString(CultureInfo.InvariantCulture)); // Skip fragments which have been overridden already for (int i = 0; i < k_OverridableFragments.GetLength(0); i++) { if (overrides == null || !overrides.ContainsKey(k_OverridableFragments[i, 0])) { var fragment = k_OverridableFragments[i, 1]; var targetFragment = k_OverridableFragments[i, 0]; if (targetFragment == "GHOST_COPY_FROM_SNAPSHOT") { if (interpolate) { m_TargetGenerator.GenerateFragment(enableExtrapolation ? "GHOST_COPY_FROM_SNAPSHOT_ENABLE_EXTRAPOLATION" : "GHOST_COPY_FROM_SNAPSHOT_DISABLE_EXTRAPOLATION", generator.Replacements, m_TargetGenerator, "GHOST_COPY_FROM_SNAPSHOT"); // The setup section is optional, so do not generate error if it is not present generator.GenerateFragment("GHOST_COPY_FROM_SNAPSHOT_INTERPOLATE_SETUP", generator.Replacements, m_TargetGenerator, "GHOST_COPY_FROM_SNAPSHOT", null, true); // only generate max distance checks if clamp is enabled if (maxSmoothingDistSq > 0) { generator.GenerateFragment("GHOST_COPY_FROM_SNAPSHOT_INTERPOLATE_DISTSQ", generator.Replacements, m_TargetGenerator, "GHOST_COPY_FROM_SNAPSHOT"); m_TargetGenerator.GenerateFragment("GHOST_COPY_FROM_SNAPSHOT_INTERPOLATE_CLAMP_MAX", generator.Replacements, m_TargetGenerator, "GHOST_COPY_FROM_SNAPSHOT"); } } else { fragment = "GHOST_COPY_FROM_SNAPSHOT"; } } generator.GenerateFragment(fragment, generator.Replacements, m_TargetGenerator, targetFragment); } } // Imports var imports = generator.GetFragmentTemplate("GHOST_IMPORTS"); if (!string.IsNullOrEmpty(imports)) { foreach (var import in imports.Split('\n')) { if (string.IsNullOrEmpty(import)) { continue; } var matches = m_usingRegex.Matches(import); if (matches.Count == 1) { context.imports.Add(matches[0].Value); } } } ulong fieldHash = 0; fieldHash = Entities.TypeHash.CombineFNV1A64(fieldHash, Entities.TypeHash.FNV1A64(m_TypeInformation.Attribute.composite?1:0)); fieldHash = Entities.TypeHash.CombineFNV1A64(fieldHash, Entities.TypeHash.FNV1A64(m_TypeInformation.Attribute.smoothing > 0 ? 1 : 0)); fieldHash = Entities.TypeHash.CombineFNV1A64(fieldHash, (ulong)m_TypeInformation.Attribute.subtype); fieldHash = Entities.TypeHash.CombineFNV1A64(fieldHash, (ulong)m_TypeInformation.Attribute.quantization); context.FieldState.ghostfieldHash = Entities.TypeHash.CombineFNV1A64(context.FieldState.ghostfieldHash, fieldHash); if (m_TypeInformation.Type.Scope != null) { context.collectionAssemblies.Add(m_TypeInformation.Type.Scope.Name); } m_ActiveGenerator = generator; }
public void GenerateSerializer(CodeGenerator.Context context, Mono.Cecil.TypeDefinition generatorType, Mono.Cecil.TypeDefinition componentType, GhostComponentAttribute ghostAttributes) { 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 (componentType.Namespace != null && componentType.Namespace != "") { context.imports.Add(componentType.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(componentType.Module.Assembly.Name.Name); if (generatorType != componentType) { context.collectionAssemblies.Add(generatorType.Module.Assembly.Name.Name); } replacements.Clear(); replacements.Add("GHOST_NAME", generatorType.FullName.Replace(".", "").Replace("/", "_")); replacements.Add("GHOST_NAMESPACE", context.generatedNs); replacements.Add("GHOST_COMPONENT_TYPE", componentType.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"); replacements.Add("GHOST_VARIANT_HASH", context.VariantHash.ToString()); if (ghostAttributes != null) { if (ghostAttributes.OwnerPredictedSendType == GhostSendType.Interpolated || (ghostAttributes.PrefabType & GhostPrefabType.Client) == GhostPrefabType.InterpolatedClient) { replacements.Add("GHOST_SEND_MASK", "GhostComponentSerializer.SendMask.Interpolated"); } else if (ghostAttributes.OwnerPredictedSendType == GhostSendType.Predicted || (ghostAttributes.PrefabType & GhostPrefabType.Client) == GhostPrefabType.PredictedClient) { replacements.Add("GHOST_SEND_MASK", "GhostComponentSerializer.SendMask.Predicted"); } else if (ghostAttributes.PrefabType == GhostPrefabType.Server) { replacements.Add("GHOST_SEND_MASK", "GhostComponentSerializer.SendMask.None"); } else { replacements.Add("GHOST_SEND_MASK", "GhostComponentSerializer.SendMask.Interpolated | GhostComponentSerializer.SendMask.Predicted"); } replacements.Add("GHOST_SEND_CHILD_ENTITY", ghostAttributes.SendDataForChildEntity?"1":"0"); var ownerType = ghostAttributes.OwnerSendType; if (componentType.IsICommandData() && (ghostAttributes.OwnerSendType & SendToOwnerType.SendToOwner) != 0) { UnityEngine.Debug.LogError($"ICommandData {componentType.FullName} is configured to be sent to ghost owner. It will be ignored"); ownerType &= ~SendToOwnerType.SendToOwner; } replacements.Add("GHOST_SEND_OWNER", "SendToOwnerType." + ownerType); } else if (!componentType.IsICommandData()) { replacements.Add("GHOST_SEND_MASK", "GhostComponentSerializer.SendMask.Interpolated | GhostComponentSerializer.SendMask.Predicted"); replacements.Add("GHOST_SEND_OWNER", "SendToOwnerType.All"); replacements.Add("GHOST_SEND_CHILD_ENTITY", "1"); } else { replacements.Add("GHOST_SEND_MASK", "GhostComponentSerializer.SendMask.Predicted"); replacements.Add("GHOST_SEND_OWNER", "SendToOwnerType.SendToNonOwner"); replacements.Add("GHOST_SEND_CHILD_ENTITY", "0"); } if (componentType.IsBufferElementData()) { m_TargetGenerator.GenerateFragment("GHOST_COPY_FROM_BUFFER", replacements, m_TargetGenerator, "COPY_FROM_SNAPSHOT_SETUP"); } else { m_TargetGenerator.GenerateFragment("GHOST_COPY_FROM_COMPONENT", replacements, m_TargetGenerator, "COPY_FROM_SNAPSHOT_SETUP"); } if (m_TargetGenerator.Fragments["__GHOST_REPORT_PREDICTION_ERROR__"].Content.Length > 0) { m_TargetGenerator.GenerateFragment("GHOST_PREDICTION_ERROR_HEADER", replacements, m_TargetGenerator); } var serializerName = generatorType.FullName.Replace("/", "+") + "Serializer.cs"; m_TargetGenerator.GenerateFile("", context.outputFolder, serializerName, replacements, context.batch); context.generatedTypes.Add(replacements["GHOST_NAME"]); }
public Dictionary <string, GhostCodeGen.FragmentData> GenerateCompositeOverrides(CodeGenerator.Context context, string parent = null) { var fragments = new Dictionary <string, GhostCodeGen.FragmentData>(); if (m_Template == null || string.IsNullOrEmpty(m_Template.TemplateOverridePath)) { return(null); } var quantization = m_TypeInformation.Attribute.quantization; var interpolate = m_TypeInformation.Attribute.smoothing > 0; if (!context.typeCodeGenCache.TryGetValue(m_Template.TemplateOverridePath, out var generator)) { generator = new GhostCodeGen(m_Template.TemplateOverridePath); context.typeCodeGenCache.Add(m_Template.TemplateOverridePath, generator); } generator = generator.Clone(); // Prefix and Variable Replacements var reference = string.IsNullOrEmpty(parent) ? m_TypeInformation.FieldName : $"{parent}.{m_TypeInformation.FieldName}"; var name = reference.Replace('.', '_'); generator.Replacements.Add("GHOST_FIELD_NAME", $"{name}"); generator.Replacements.Add("GHOST_FIELD_REFERENCE", $"{reference}"); generator.Replacements.Add("GHOST_FIELD_TYPE_NAME", m_TypeInformation.Type.GetFieldTypeName()); if (quantization > 0) { generator.Replacements.Add("GHOST_QUANTIZE_SCALE", quantization.ToString()); generator.Replacements.Add("GHOST_DEQUANTIZE_SCALE", $"{(1.0f / quantization).ToString(CultureInfo.InvariantCulture)}f"); } float maxSmoothingDistSq = m_TypeInformation.Attribute.maxSmoothingDist * m_TypeInformation.Attribute.maxSmoothingDist; bool enableExtrapolation = m_TypeInformation.Attribute.smoothing == (uint)TypeAttribute.AttributeFlags.InterpolatedAndExtrapolated; generator.Replacements.Add("GHOST_MAX_INTERPOLATION_DISTSQ", maxSmoothingDistSq.ToString(CultureInfo.InvariantCulture)); // Type Info if (generator.GenerateFragment("GHOST_FIELD", generator.Replacements, m_TargetGenerator, null, null, true)) { fragments.Add("GHOST_FIELD", m_TargetGenerator.Fragments["__GHOST_FIELD__"]); } // CopyToSnapshot if (generator.GenerateFragment("GHOST_COPY_TO_SNAPSHOT", generator.Replacements, m_TargetGenerator, null, null, true)) { fragments.Add("GHOST_COPY_TO_SNAPSHOT", m_TargetGenerator.Fragments["__GHOST_COPY_TO_SNAPSHOT__"]); } // CopyFromSnapshot if (interpolate) { if (generator.HasFragment("GHOST_COPY_FROM_SNAPSHOT_INTERPOLATE")) { m_TargetGenerator.GenerateFragment(enableExtrapolation ? "GHOST_COPY_FROM_SNAPSHOT_ENABLE_EXTRAPOLATION" : "GHOST_COPY_FROM_SNAPSHOT_DISABLE_EXTRAPOLATION", generator.Replacements, m_TargetGenerator, "GHOST_COPY_FROM_SNAPSHOT"); // The setup section is optional, so do not generate error if it is not present generator.GenerateFragment("GHOST_COPY_FROM_SNAPSHOT_INTERPOLATE_SETUP", generator.Replacements, m_TargetGenerator, "GHOST_COPY_FROM_SNAPSHOT", null, true); // only generate max distance checks if clamp is enabled if (maxSmoothingDistSq > 0) { generator.GenerateFragment("GHOST_COPY_FROM_SNAPSHOT_INTERPOLATE_DISTSQ", generator.Replacements, m_TargetGenerator, "GHOST_COPY_FROM_SNAPSHOT"); m_TargetGenerator.GenerateFragment("GHOST_COPY_FROM_SNAPSHOT_INTERPOLATE_CLAMP_MAX", generator.Replacements, m_TargetGenerator, "GHOST_COPY_FROM_SNAPSHOT"); } generator.GenerateFragment("GHOST_COPY_FROM_SNAPSHOT_INTERPOLATE", generator.Replacements, m_TargetGenerator, "GHOST_COPY_FROM_SNAPSHOT"); fragments.Add("GHOST_COPY_FROM_SNAPSHOT", generator.Fragments["__GHOST_COPY_FROM_SNAPSHOT__"]); fragments.Add("GHOST_COPY_FROM_SNAPSHOT_INTERPOLATE", generator.Fragments["__GHOST_COPY_FROM_SNAPSHOT_INTERPOLATE__"]); } } else { if (generator.GenerateFragment("GHOST_COPY_FROM_SNAPSHOT", generator.Replacements, m_TargetGenerator, "GHOST_COPY_FROM_SNAPSHOT", null, true)) { fragments.Add("GHOST_COPY_FROM_SNAPSHOT", generator.Fragments["__GHOST_COPY_FROM_SNAPSHOT__"]); fragments.Add("GHOST_COPY_FROM_SNAPSHOT_INTERPOLATE", generator.Fragments["__GHOST_COPY_FROM_SNAPSHOT_INTERPOLATE__"]); } } // RestoreFromBackup if (generator.GenerateFragment("GHOST_RESTORE_FROM_BACKUP", generator.Replacements, m_TargetGenerator, null, null, true)) { fragments.Add("GHOST_RESTORE_FROM_BACKUP", m_TargetGenerator.Fragments["__GHOST_RESTORE_FROM_BACKUP__"]); } // PredictDelta if (generator.GenerateFragment("GHOST_PREDICT", generator.Replacements, m_TargetGenerator, null, null, true)) { fragments.Add("GHOST_PREDICT", m_TargetGenerator.Fragments["__GHOST_PREDICT__"]); } // ReportPredictionError if (generator.GenerateFragment("GHOST_REPORT_PREDICTION_ERROR", generator.Replacements, m_TargetGenerator, null, null, true)) { fragments.Add("GHOST_REPORT_PREDICTION_ERROR", m_TargetGenerator.Fragments["__GHOST_REPORT_PREDICTION_ERROR__"]); } // GetPredictionErrorName if (generator.GenerateFragment("GHOST_GET_PREDICTION_ERROR_NAME", generator.Replacements, m_TargetGenerator, null, null, true)) { fragments.Add("GHOST_GET_PREDICTION_ERROR_NAME", m_TargetGenerator.Fragments["__GHOST_GET_PREDICTION_ERROR_NAME__"]); } ValidateOverridableFragments(generator.Fragments); m_ActiveGenerator = generator; return(fragments); }