コード例 #1
0
        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));
        }
コード例 #2
0
        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));
        }
コード例 #3
0
        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);
                }
            }
        }