/// <summary> /// Serializes a structure into a temporary memory block. /// </summary> /// <param name="context">The serialization context to use.</param> /// <param name="tagStream">The stream to write completed blocks of tag data to.</param> /// <param name="block">The temporary block to write incomplete tag data to.</param> /// <param name="info">Information about the tag structure type.</param> /// <param name="structure">The structure to serialize.</param> /// <exception cref="System.InvalidOperationException">Structure type must have TagStructureAttribute</exception> private void SerializeStruct(ISerializationContext context, MemoryStream tagStream, IDataBlock block, TagStructureInfo info, object structure) { var baseOffset = block.Stream.Position; var enumerator = new TagFieldEnumerator(info); while (enumerator.Next()) { SerializeProperty(context, tagStream, block, structure, enumerator, baseOffset); } // Honor the struct size if it's defined if (info.TotalSize > 0) { block.Stream.Position = baseOffset + info.TotalSize; if (block.Stream.Position > block.Stream.Length) { block.Stream.SetLength(block.Stream.Position); } } // Honor alignment if (info.Structure.Align > 0) { block.SuggestAlignment(info.Structure.Align); } }
/// <summary> /// Deserializes a structure. /// </summary> /// <param name="reader">The reader.</param> /// <param name="context">The serialization context to use.</param> /// <param name="info">Information about the structure to deserialize.</param> /// <returns>The deserialized structure.</returns> /// <exception cref="System.InvalidOperationException">Target type must have TagStructureAttribute</exception> private object DeserializeStruct(BinaryReader reader, ISerializationContext context, TagStructureInfo info) { var baseOffset = reader.BaseStream.Position; var instance = Activator.CreateInstance(info.Types[0]); var enumerator = new TagFieldEnumerator(info); while (enumerator.Next()) { DeserializeProperty(reader, context, instance, enumerator, baseOffset); } if (enumerator.Info.TotalSize > 0) { reader.BaseStream.Position = baseOffset + enumerator.Info.TotalSize; } return(instance); }
public override bool Execute(List<string> args) { if (args.Count > 1) return false; var match = (args.Count == 1); var token = match ? args[0].ToLower() : ""; var enumerator = new TagFieldEnumerator(Structure); while (enumerator.Next()) { var nameString = enumerator.Field.Name; if (match && !nameString.ToLower().Contains(token)) continue; var fieldType = enumerator.Field.FieldType; var fieldValue = enumerator.Field.GetValue(Value); var typeString = fieldType.IsGenericType ? $"{fieldType.Name}<{fieldType.GenericTypeArguments[0].Name}>" : fieldType.Name; string valueString; if (fieldValue == null) valueString = "null"; else if (fieldType.GetInterface(typeof(IList).Name) != null) valueString = ((IList)fieldValue).Count != 0 ? $"{{...}}[{((IList)fieldValue).Count}]" : "null"; else if (fieldType == typeof(StringId)) valueString = Info.StringIds.GetString((StringId)fieldValue); else valueString = fieldValue.ToString(); Console.WriteLine("{0}: {1} = {2}", nameString, typeString, valueString); } return true; }
/// <summary> /// Serializes a structure into a temporary memory block. /// </summary> /// <param name="context">The serialization context to use.</param> /// <param name="tagStream">The stream to write completed blocks of tag data to.</param> /// <param name="block">The temporary block to write incomplete tag data to.</param> /// <param name="info">Information about the tag structure type.</param> /// <param name="structure">The structure to serialize.</param> /// <exception cref="System.InvalidOperationException">Structure type must have TagStructureAttribute</exception> private void SerializeStruct(ISerializationContext context, MemoryStream tagStream, IDataBlock block, TagStructureInfo info, object structure) { var baseOffset = block.Stream.Position; var enumerator = new TagFieldEnumerator(info); while (enumerator.Next()) SerializeProperty(context, tagStream, block, structure, enumerator, baseOffset); // Honor the struct size if it's defined if (info.TotalSize > 0) { block.Stream.Position = baseOffset + info.TotalSize; if (block.Stream.Position > block.Stream.Length) block.Stream.SetLength(block.Stream.Position); } // Honor alignment if (info.Structure.Align > 0) block.SuggestAlignment(info.Structure.Align); }
private static void CompareBlocks(object leftData, EngineVersion leftVersion, object rightData, EngineVersion rightVersion, TagVersionMap result, Queue<QueuedTag> tagQueue) { if (leftData == null || rightData == null) return; var type = leftData.GetType(); if (type == typeof(TagInstance)) { // If the objects are tags, then we've found a match var leftTag = (TagInstance)leftData; var rightTag = (TagInstance)rightData; if (leftTag.Group.Tag != rightTag.Group.Tag) return; if (leftTag.IsInGroup("rmt2") || leftTag.IsInGroup("rmdf") || leftTag.IsInGroup("vtsh") || leftTag.IsInGroup("pixl") || leftTag.IsInGroup("rm ") || leftTag.IsInGroup("bitm")) return; var translated = result.Translate(leftVersion, leftTag.Index, rightVersion); if (translated >= 0) return; result.Add(leftVersion, leftTag.Index, rightVersion, rightTag.Index); tagQueue.Enqueue(new QueuedTag { Tag = rightTag }); } else if (type.IsArray) { if (type.GetElementType().IsPrimitive) return; // If the objects are arrays, then loop through each element var leftArray = (Array)leftData; var rightArray = (Array)rightData; if (leftArray.Length != rightArray.Length) return; // If the sizes are different, we probably can't compare them for (var i = 0; i < leftArray.Length; i++) CompareBlocks(leftArray.GetValue(i), leftVersion, rightArray.GetValue(i), rightVersion, result, tagQueue); } else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>)) { if (type.GenericTypeArguments[0].IsPrimitive) return; // If the objects are lists, then loop through each element var countProperty = type.GetProperty("Count"); var leftCount = (int)countProperty.GetValue(leftData); var rightCount = (int)countProperty.GetValue(rightData); if (leftCount != rightCount) return; // If the sizes are different, we probably can't compare them var getItem = type.GetMethod("get_Item"); for (var i = 0; i < leftCount; i++) { var leftItem = getItem.Invoke(leftData, new object[] { i }); var rightItem = getItem.Invoke(rightData, new object[] { i }); CompareBlocks(leftItem, leftVersion, rightItem, rightVersion, result, tagQueue); } } else if (type.GetCustomAttributes(typeof(TagStructureAttribute), false).Length > 0) { // The objects are structures var left = new TagFieldEnumerator(new TagStructureInfo(leftData.GetType(), leftVersion)); var right = new TagFieldEnumerator(new TagStructureInfo(rightData.GetType(), rightVersion)); while (left.Next() && right.Next()) { // Keep going on the left until the field is on the right while (!VersionDetection.IsBetween(rightVersion, left.MinVersion, left.MaxVersion)) { if (!left.Next()) return; } // Keep going on the right until the field is on the left while (!VersionDetection.IsBetween(leftVersion, right.MinVersion, right.MaxVersion)) { if (!right.Next()) return; } if (left.Field.MetadataToken != right.Field.MetadataToken) throw new InvalidOperationException("WTF, left and right fields don't match!"); // Process the fields var leftFieldData = left.Field.GetValue(leftData); var rightFieldData = right.Field.GetValue(rightData); CompareBlocks(leftFieldData, leftVersion, rightFieldData, rightVersion, result, tagQueue); } } }
private object CreateElement(Type elementType) { var element = Activator.CreateInstance(elementType); var isTagStructure = Attribute.IsDefined(elementType, typeof(TagStructureAttribute)); if (isTagStructure) { var enumerator = new TagFieldEnumerator( new TagStructureInfo(elementType)); while (enumerator.Next()) { var fieldType = enumerator.Field.FieldType; if (fieldType.IsArray && enumerator.Attribute.Count > 0) { var array = (IList)Activator.CreateInstance(enumerator.Field.FieldType, new object[] { enumerator.Attribute.Count }); for (var i = 0; i < enumerator.Attribute.Count; i++) array[i] = CreateElement(fieldType.GetElementType()); } else { try { enumerator.Field.SetValue(element, CreateElement(enumerator.Field.FieldType)); } catch { enumerator.Field.SetValue(element, null); } } } } return element; }