Beispiel #1
0
        /// <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;
        }