private static TagStructureAttribute GetStructureAttribute(Type type, EngineVersion version) { // First match against any TagStructureAttributes that have version restrictions var attrib = type.GetCustomAttributes(typeof(TagStructureAttribute), false) .Cast <TagStructureAttribute>() .Where(a => a.MinVersion != EngineVersion.Unknown || a.MaxVersion != EngineVersion.Unknown) .FirstOrDefault(a => VersionDetection.IsBetween(version, a.MinVersion, a.MaxVersion)); // If nothing was found, find the first attribute without any version restrictions return(attrib ?? type.GetCustomAttributes(typeof(TagStructureAttribute), false) .Cast <TagStructureAttribute>() .FirstOrDefault(a => a.MinVersion == EngineVersion.Unknown && a.MaxVersion == EngineVersion.Unknown)); }
private bool GetCurrentPropertyInfo() { // If the field has a TagFieldAttribute, use it, otherwise use the default Attribute = Field.GetCustomAttributes(typeof(TagFieldAttribute), false).FirstOrDefault() as TagFieldAttribute ?? DefaultFieldAttribute; if (Attribute.Offset >= Info.TotalSize) { throw new InvalidOperationException("Offset for property \"" + Field.Name + "\" is outside of its structure"); } // Read version restrictions, if any var minVersionAttrib = Field.GetCustomAttributes(typeof(MinVersionAttribute), false).FirstOrDefault() as MinVersionAttribute; var maxVersionAttrib = Field.GetCustomAttributes(typeof(MaxVersionAttribute), false).FirstOrDefault() as MaxVersionAttribute; MinVersion = (minVersionAttrib != null) ? minVersionAttrib.Version : EngineVersion.Unknown; MaxVersion = (maxVersionAttrib != null) ? maxVersionAttrib.Version : EngineVersion.Unknown; return(VersionDetection.IsBetween(Info.Version, MinVersion, MaxVersion)); }
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); } } }