private static void WriteUpdate(Type dataType, ObjectType objectType, UpdateFieldHandlers fieldHandler) { // Update - if the value is a complex structure, it gets its own bits for each field // -- dynamic only if sizeof(struct) > 32 // -- arrays always // if next array field is same size, merge it into previous loop // Order // * bools (as bits, not part of masks) // * blz::vectors (CGItemData::m_modifiers) // * JamDynamicField.Count // * JamDynamicField[].Count (CGActivePlayerData::m_research is a blz::array<JamDynamicField, 1>) // * JamDynamicField[].Values (separate loop from count) // * JamDynamicField.Values // * Values // * Arrays var allFields = dataType.GetFields(BindingFlags.Static | BindingFlags.Public) .Where(field => typeof(UpdateField).IsAssignableFrom(field.FieldType)) .Select(field => ResolveField(field)) .GroupBy(field => GetUpdateTypeOrder(field.Field)) .Select(group => (group.Key, group.OrderBy(field => field.Field.Order))) .ToDictionary(thing => thing.Key, thing => thing.Item2); var hasChangesMask = dataType.GetCustomAttribute <HasChangesMaskAttribute>(); fieldHandler.OnStructureBegin(dataType, objectType, false, hasChangesMask != null); IOrderedEnumerable <(UpdateField Field, string Name)> fieldGroup; if (allFields.TryGetValue(UpdateTypeOrder.Bits, out fieldGroup)) { foreach (var(Field, Name) in fieldGroup) { fieldHandler.OnField(Name, Field); } } if (allFields.TryGetValue(UpdateTypeOrder.BlzVector, out fieldGroup)) { foreach (var(Field, Name) in fieldGroup) { fieldHandler.OnField(Name, Field); } fieldHandler.FinishControlBlocks(); fieldHandler.FinishBitPack(); } if (allFields.TryGetValue(UpdateTypeOrder.JamDynamicField, out fieldGroup)) { foreach (var(Field, Name) in fieldGroup) { fieldHandler.OnDynamicFieldSizeUpdate(Name, Field); } fieldHandler.FinishControlBlocks(); } if (allFields.TryGetValue(UpdateTypeOrder.JamDynamicFieldArray, out fieldGroup)) { foreach (var(Field, Name) in fieldGroup) { fieldHandler.OnDynamicFieldSizeUpdate(Name, Field); } fieldHandler.FinishControlBlocks(); } if (allFields.TryGetValue(UpdateTypeOrder.JamDynamicFieldArray, out fieldGroup)) { foreach (var(Field, Name) in fieldGroup) { fieldHandler.OnField(Name, Field); } } if (hasChangesMask != null || allFields.ContainsKey(UpdateTypeOrder.Bits) || allFields.ContainsKey(UpdateTypeOrder.JamDynamicField) || allFields.ContainsKey(UpdateTypeOrder.JamDynamicFieldArray)) { fieldHandler.FinishControlBlocks(); fieldHandler.FinishBitPack(); } if (allFields.TryGetValue(UpdateTypeOrder.JamDynamicField, out fieldGroup)) { foreach (var(Field, Name) in fieldGroup.Where(field => !StructureHasBitFields(field.Field.Type.GenericTypeArguments[0]))) { fieldHandler.OnField(Name, Field); } foreach (var(Field, Name) in fieldGroup.Where(field => StructureHasBitFields(field.Field.Type.GenericTypeArguments[0]))) { fieldHandler.OnField(Name, Field); } } if (allFields.TryGetValue(UpdateTypeOrder.Default, out fieldGroup)) { foreach (var(Field, Name) in fieldGroup) { fieldHandler.OnField(Name, Field); } } if (allFields.TryGetValue(UpdateTypeOrder.Optional, out fieldGroup)) { fieldHandler.FinishControlBlocks(); fieldHandler.FinishBitPack(); foreach (var(Field, Name) in fieldGroup) { fieldHandler.OnOptionalFieldInitUpdate(Name, Field); } } if (allFields.TryGetValue(UpdateTypeOrder.Optional, out fieldGroup)) { foreach (var(Field, Name) in fieldGroup) { fieldHandler.OnField(Name, Field); } } if (allFields.TryGetValue(UpdateTypeOrder.Array, out fieldGroup)) { foreach (var(Field, Name) in fieldGroup) { fieldHandler.OnField(Name, Field); } } fieldHandler.OnStructureEnd(StructureHasBitFields(dataType), hasChangesMask != null && hasChangesMask.ForceMaskMask); }
private static void WriteCreate(Type dataType, ObjectType objectType, UpdateFieldHandlers fieldHandler) { // Create // * In declaration order // * JamDynamicField[].Count (CGActivePlayerData::m_research is a blz::array<JamDynamicField, 1>) // * JamDynamicField[].Values (separate loop from count) // * JamDynamicField.Values // * Bits // * JamDynamicField.Values that have bits in them var allFields = dataType.GetFields(BindingFlags.Static | BindingFlags.Public) .Where(field => typeof(UpdateField).IsAssignableFrom(field.FieldType)) .Select(field => ResolveField(field)) .GroupBy(field => GetCreateTypeOrder(field.Field)) .Select(group => (group.Key, group.OrderBy(field => field.Field.Order))) .ToDictionary(thing => thing.Key, thing => thing.Item2); fieldHandler.OnStructureBegin(dataType, objectType, true, dataType.GetCustomAttribute <HasChangesMaskAttribute>() != null); IOrderedEnumerable <(UpdateField Field, string Name)> fieldGroup; var firstBunchOfFields = Enumerable.Empty <(UpdateField Field, string Name)>(); if (allFields.TryGetValue(CreateTypeOrder.Default, out fieldGroup)) { firstBunchOfFields = firstBunchOfFields.Concat(fieldGroup); } if (allFields.TryGetValue(CreateTypeOrder.JamDynamicField, out fieldGroup)) { firstBunchOfFields = firstBunchOfFields.Concat(fieldGroup); } if (allFields.TryGetValue(CreateTypeOrder.JamDynamicFieldArray, out fieldGroup)) { firstBunchOfFields = firstBunchOfFields.Concat(fieldGroup); } if (allFields.TryGetValue(CreateTypeOrder.JamDynamicFieldWithBits, out fieldGroup)) { firstBunchOfFields = firstBunchOfFields.Concat(fieldGroup); } foreach (var(Field, Name) in firstBunchOfFields.OrderBy(field => field.Field.Order)) { if (typeof(DynamicUpdateField).IsAssignableFrom(Field.Type) || (Field.Type.IsArray && typeof(DynamicUpdateField).IsAssignableFrom(Field.Type.GetElementType()))) { fieldHandler.OnDynamicFieldSizeCreate(Name, Field); } else { fieldHandler.OnField(Name, Field); } } if (allFields.TryGetValue(CreateTypeOrder.JamDynamicFieldArray, out fieldGroup)) { foreach (var(Field, Name) in fieldGroup) { fieldHandler.OnField(Name, Field); } } if (allFields.TryGetValue(CreateTypeOrder.JamDynamicField, out fieldGroup)) { foreach (var(Field, Name) in fieldGroup) { fieldHandler.OnField(Name, Field); } } if (allFields.TryGetValue(CreateTypeOrder.DefaultWithBits, out fieldGroup)) { foreach (var(Field, Name) in fieldGroup) { fieldHandler.OnField(Name, Field); } } if (allFields.TryGetValue(CreateTypeOrder.ArrayWithBits, out fieldGroup)) { foreach (var(Field, Name) in fieldGroup) { fieldHandler.OnField(Name, Field); } } if ((allFields.ContainsKey(CreateTypeOrder.DefaultWithBits) || allFields.ContainsKey(CreateTypeOrder.ArrayWithBits)) && (allFields.ContainsKey(CreateTypeOrder.Bits) || allFields.ContainsKey(CreateTypeOrder.Optional))) { fieldHandler.FinishControlBlocks(); fieldHandler.FinishBitPack(); } if (allFields.TryGetValue(CreateTypeOrder.Bits, out fieldGroup)) { foreach (var(Field, Name) in fieldGroup) { fieldHandler.OnField(Name, Field); } } if (allFields.TryGetValue(CreateTypeOrder.Optional, out fieldGroup)) { foreach (var(Field, Name) in fieldGroup) { fieldHandler.OnOptionalFieldInitCreate(Name, Field); } } if (allFields.TryGetValue(CreateTypeOrder.Optional, out fieldGroup)) { foreach (var(Field, Name) in fieldGroup) { fieldHandler.OnField(Name, Field); } } if (allFields.TryGetValue(CreateTypeOrder.JamDynamicFieldWithBits, out fieldGroup)) { foreach (var(Field, Name) in fieldGroup) { fieldHandler.OnField(Name, Field); } } fieldHandler.OnStructureEnd(StructureHasBitFields(dataType), false); }