Пример #1
0
        public void FlattenParentInheritance()
        {
            Dictionary <uint, Property> flattenedProperties = new Dictionary <uint, Property>();

            flattenedProperties = GetParentProperties(flattenedProperties, this.Values);

            if (flattenedProperties.ContainsKey(0x0A0209B2))
            {
                ArrayProperty excludedProperties = flattenedProperties[0x0A0209B2] as ArrayProperty;
                if (flattenedProperties.ContainsKey(0x0A0209A2))
                {
                    ArrayProperty prop = flattenedProperties[0x0A0209A2] as ArrayProperty;
                    foreach (KeyProperty keyProp in excludedProperties.Values)
                    {
                        prop.Values.RemoveAll(kp => (kp as KeyProperty).InstanceId == keyProp.InstanceId);
                    }
                }
                if (flattenedProperties.ContainsKey(0x0A0209A3))
                {
                    ArrayProperty prop = flattenedProperties[0x0A0209A3] as ArrayProperty;
                    foreach (KeyProperty keyProp in excludedProperties.Values)
                    {
                        prop.Values.RemoveAll(kp => (kp as KeyProperty).InstanceId == keyProp.InstanceId);
                    }
                }
                if (flattenedProperties.ContainsKey(0x0A0209A4))
                {
                    ArrayProperty prop = flattenedProperties[0x0A0209A4] as ArrayProperty;
                    foreach (KeyProperty keyProp in excludedProperties.Values)
                    {
                        prop.Values.RemoveAll(kp => (kp as KeyProperty).InstanceId == keyProp.InstanceId);
                    }
                }
                if (flattenedProperties.ContainsKey(0x0A0209A5))
                {
                    ArrayProperty prop = flattenedProperties[0x0A0209A5] as ArrayProperty;
                    foreach (KeyProperty keyProp in excludedProperties.Values)
                    {
                        prop.Values.RemoveAll(kp => (kp as KeyProperty).InstanceId == keyProp.InstanceId);
                    }
                }
                flattenedProperties.Remove(0x0A0209B2);
                flattenedProperties.Remove(0x02A907B6);
            }

            this.Values = flattenedProperties;
        }
Пример #2
0
        public void WriteXML(XmlWriter writer)
        {
            writer.WriteStartDocument();
            writer.WriteStartElement("properties");

            // Not necessary, but alpha order makes properties easier to find than hash order,
            //   except for the description and parent usually being at the top, which I do
            //   explicitly
            var keys = from k in this.Values.Keys
                       let n = SporeMaster.NameRegistry.Properties.toName(k).ToLowerInvariant()
                               orderby(
                k == 0x00B2CCCA ? "0" :                     // "description"
                k == 0x00B2CCCB ? "1" :                     // "parent"
                !n.StartsWith("#") ? "2" + n
                            : "3" + n
                )
                               select k;

            foreach (uint hash in keys)
            {
                Property property = this.Values[hash];

                if (!(property is ArrayProperty))
                {
                    writer.WriteStartElement(property.GetType().GetSingularName());
                }
                else
                {
                    ArrayProperty array = (ArrayProperty)property;
                    writer.WriteStartElement(array.PropertyType.GetPluralName());
                }

                var name = SporeMaster.NameRegistry.Properties.toName(hash);
                writer.WriteAttributeString("name", name);

                property.WriteXML(writer);

                writer.WriteEndElement();
            }

            writer.WriteEndDocument();
        }
Пример #3
0
        public static Property AddProperty(uint id, Type propertyType, bool isArray)
        {
            Property newProperty;

            if (isArray)
            {
                ArrayProperty arrProperty = new ArrayProperty();
                arrProperty.Values = new List <Property>();

                Property subProperty = Activator.CreateInstance(propertyType) as Property;

                arrProperty.Values.Add(subProperty);
                newProperty = arrProperty;
            }
            else
            {
                newProperty = Activator.CreateInstance(propertyType) as Property;
            }
            return(newProperty);
        }
Пример #4
0
        public void ReadXML(XmlReader reader)
        {
            reader.ReadToFollowing("properties");
            while (reader.Read())
            {
                if (reader.IsStartElement())
                {
                    string typeName = reader.Name;
                    uint hash;
                    string hashText = reader.GetAttribute("id");
                    if (hashText != null)
                    {
                        // This is a "legacy" file generated by Gibbed.Modmaker etc
                        hash = hashText.GetHexNumber();
                    }
                    else
                    {
                        hash = SporeMaster.NameRegistry.Properties.toHash(reader.GetAttribute("name"));
                    }

                    PropertyLookup lookup = PropTypes.FindPropertyType(typeName);

                    if (lookup == null)
                    {
                        throw new Exception("unknown type " + typeName);
                    }

                    Property property = null;

                    // Singular
                    if (lookup.Definition.Name == typeName)
                    {
                        property = Activator.CreateInstance(lookup.Type) as Property;
                        property.ReadXML(reader);
                    }
                    // Plural
                    else if (lookup.Definition.PluralName == typeName)
                    {
                        ArrayProperty array = new ArrayProperty();
                        array.PropertyType = lookup.Type;

                        var subtree = reader.ReadSubtree();
                        subtree.ReadToFollowing(typeName);

                        while (subtree.Read())
                        {
                            if (subtree.IsStartElement())
                            {
                                if (subtree.Name != lookup.Definition.Name)
                                {
                                    throw new Exception("array element for " + typeName + " is not the right type");
                                }

                                Property subproperty = Activator.CreateInstance(lookup.Type) as Property;
                                subproperty.ReadXML(subtree);

                                array.Values.Add(subproperty);
                            }
                        }

                        property = array;
                    }

                    this.Values[hash] = property;
                }
            }
        }
Пример #5
0
        public void Read(Stream input)
        {
            uint count = input.ReadU32BE();
            uint lasthash = 0;

            for (uint i = 0; i < count; i++)
            {
                uint hash = input.ReadU32BE();
                ushort fileType = input.ReadU16BE();
                ushort flags = input.ReadU16BE();

                if (i > 0 && hash < lasthash)
                    throw new Exception("property file has keys out of order: " + lasthash.ToString("X8") + ", " + hash.ToString("X8"));
                lasthash = hash;

                if (this.Values.ContainsKey(hash))
                {
                    throw new Exception("property file already has " + hash.ToString("X8") + " defined");
                }

                Property property = null;
                Type type = PropTypes.GetTypeFromFileType(fileType);

                if (type == null)
                {
                    throw new Exception("invalid type " + fileType.ToString());
                }

                if ((flags & 0x30) == 0) // is not variant?
                {
                    property = Activator.CreateInstance(type) as Property;
                    property.ReadProp(input, false);

                    this.Values[hash] = property;
                }
                // Variant
                else if ((flags & 0x40) == 0) // is not empty?
                {
                    ArrayProperty array = new ArrayProperty();
                    array.PropertyType = type;

                    int arrayCount = input.ReadS32BE();
                    int arrayItemSize = input.ReadS32BE();

                    for (uint j = 0; j < arrayCount; j++)
                    {
                        Property subproperty = Activator.CreateInstance(type) as Property;

                        if (subproperty is ComplexProperty)
                        {
                            MemoryStream memory = new MemoryStream();
                            byte[] data = new byte[arrayItemSize];
                            input.Read(data, 0, arrayItemSize);
                            memory.Write(data, 0, arrayItemSize);
                            memory.Seek(0, SeekOrigin.Begin);

                            subproperty.ReadProp(memory, true);
                        }
                        else
                        {
                            subproperty.ReadProp(input, true);
                        }

                        array.Values.Add(subproperty);
                    }

                    property = array;

                    this.Values[hash] = property;
                }
            }
        }
Пример #6
0
        public void Write(Stream output)
        {
            output.WriteS32BE(this.Values.Count);

            // Important!  Rick's code didn't do this, which meant packed property files could randomly break
            // (order of keys from Dictionary is undefined).  In practice it seems to have worked when input XML
            // is in order, but people didn't know that...
            var keys = from k in this.Values.Keys orderby k select k;

            // var keys = this.Values.Keys;

            foreach (uint hash in keys)
            {
                Property property = this.Values[hash];

                output.WriteU32BE(hash);



                if (property is ArrayProperty)
                {
                    ArrayProperty array    = (ArrayProperty)property;
                    ushort        fileType = PropTypes.FindPropertyType(array.PropertyType).FileType;
                    output.WriteU16BE(fileType);
                    if ((array.PropertyType.BaseType == typeof(ComplexProperty)) && (array.Values.Count == 1))
                    {
                        if (array.PropertyType == typeof(TransformProperty))
                        {
                            output.WriteU16BE(0x809C);
                        }
                        else
                        {
                            output.WriteU16BE(0x801C);
                        }
                    }
                    else
                    {
                        output.WriteU16BE(0x809C);
                    }
                }
                else
                {
                    output.WriteU16BE(PropTypes.FindPropertyType(this.Values[hash].GetType()).FileType);
                    output.WriteU16BE(0x8000);
                }



                if (property is ArrayProperty)
                {
                    ArrayProperty array = (ArrayProperty)property;

                    MemoryStream[] memories = new MemoryStream[array.Values.Count];

                    int  index           = 0;
                    uint maxSize         = 0;
                    Type subPropertyType = null;
                    foreach (Property subproperty in array.Values)
                    {
                        memories[index] = new MemoryStream();
                        subproperty.WriteProp(memories[index], true);

                        if (memories[index].Length > maxSize)
                        {
                            maxSize = (uint)memories[index].Length;
                        }
                        subPropertyType = subproperty.GetType();

                        index++;
                    }

                    // if (subPropertyType == typeof(String8Property))
                    // {
                    //     maxSize = maxSize / 2;
                    //}
                    output.WriteU32BE((uint)memories.Length);
                    if (maxSize == 8)
                    {
                        output.WriteU32BE(maxSize | 0x0200);
                    }
                    else
                    {
                        if (subPropertyType == typeof(String8Property))
                        {
                            output.WriteU32BE(16);
                        }
                        else if (maxSize == 14)
                        {
                            output.WriteU32BE(56);
                        }
                        else if (maxSize == 50)
                        {
                            //added for one specific case... don't know if there's anything else to this
                            output.WriteU32BE(56);
                        }
                        else if (maxSize == 54)
                        {
                            //added for one specific case... don't know if there's anything else to this
                            output.WriteU32BE(56);
                        }
                        else
                        {
                            output.WriteU32BE(maxSize);
                        }
                    }


                    for (int i = 0; i < memories.Length; i++)
                    {
                        byte[] data = new byte[array.Values[i] is ComplexProperty ? maxSize : memories[i].Length];

                        memories[i].Seek(0, SeekOrigin.Begin);
                        memories[i].Read(data, 0, (int)(memories[i].Length));
                        output.Write(data, 0, data.Length);
                    }
                }
                else
                {
                    MemoryStream memory = new MemoryStream();
                    property.WriteProp(memory, false);

                    memory.Seek(0, SeekOrigin.Begin);

                    if (property is ComplexProperty)
                    {
                        output.WriteU32BE(1);
                        output.WriteU32BE((uint)memory.Length | 0x0200);
                    }

                    byte[] data = new byte[memory.Length];
                    memory.Read(data, 0, (int)memory.Length);
                    output.Write(data, 0, data.Length);
                }
            }
        }
Пример #7
0
        public void Read(Stream input)
        {
            _propertyCount = input.ReadU32BE();
            uint lasthash = 0;

            //  Debug.WriteLine(string.Format("Opening property file with {0} properties", _propertyCount));

            //added check for eof as one PROPs file has less properties than it claims it does.
            for (uint i = 0; i < _propertyCount && input.Position < input.Length; i++)
            {
                long   pos      = input.Position;
                uint   hash     = input.ReadU32BE();
                ushort fileType = input.ReadU16BE();
                ushort flags    = input.ReadU16BE();

                //Debug.WriteLine(string.Format("Found property with at pos {3} hash {0} and type {1} and flags {2}", hash.ToHex(), fileType.ToString("X"), flags.ToString("X"), input.Position));

                // if (i > 0 && hash < lasthash)
                //      throw new Exception("property file has keys out of order: " + lasthash.ToString("X8") + ", " + hash.ToString("X8"));
                lasthash = hash;

                if (this.Values.ContainsKey(hash))
                {
                    throw new Exception("property file already has " + hash.ToString("X8") + " defined");
                }

                Property property = null;
                Type     type     = PropTypes.GetTypeFromFileType(fileType);


                if (type == null)
                {
                    throw new Exception(string.Format("type {0} is Unknown2", fileType.ToString("X")));
                    // Debug.WriteLine(string.Format("Hash {0} with type {1} is not a valid type...apparently", hash.ToHex(), fileType.ToString("X")));
                }
                else
                {
                    // Debug.WriteLine(string.Format("Found property {0} with type {1}", hash.ToHex(), type.ToString()));
                    if ((flags & 0x30) == 0) // is not variant?
                    {
                        property = Activator.CreateInstance(type) as Property;
                        //added flags to read prop for string8 property
                        property.ReadProp(input, flags, false);

                        this.Values[hash] = property;
                    }
                    // Variant
                    else if ((flags & 0x40) == 0) // is not empty?
                    {
                        ArrayProperty array = new ArrayProperty();
                        array.PropertyType = type;

                        int arrayCount    = input.ReadS32BE();
                        int arrayItemSize = input.ReadS32BE();

                        //var test = input.ReadArrayCount();

                        //Debug.WriteLine("Found an array property with {0} items", arrayItemSize);
                        //var test = input.ReadS16();
                        //arrayItemSize = input.ReadS8();


                        for (uint j = 0; j < arrayCount; j++)
                        {
                            Property subproperty = Activator.CreateInstance(type) as Property;

                            /* if (subproperty is ComplexProperty)
                             * {
                             *   if (subproperty is TextProperty)
                             *   {
                             *       arrayItemSize = 8;
                             *   }
                             *   else if (subproperty is BoundingBoxProperty)
                             *   {
                             *       arrayItemSize = 48;
                             *   }
                             *   else if (subproperty is TransformProperty)
                             *   {
                             *       arrayItemSize = 8;
                             *
                             *   }
                             *
                             *
                             *
                             *   MemoryStream memory = new MemoryStream();
                             *   byte[] data = new byte[arrayItemSize];
                             *   input.Read(data, 0, arrayItemSize);
                             *   memory.Write(data, 0, arrayItemSize);
                             *   memory.Seek(0, SeekOrigin.Begin);
                             *
                             *   subproperty.ReadProp(memory, true);
                             *
                             * }
                             * else
                             * {*/
                            subproperty.ReadProp(input, true);
                            //}

                            array.Values.Add(subproperty);
                        }


                        property = array;

                        this.Values[hash] = property;
                    }
                    else // is not empty?
                    {
                        // Debug.WriteLine(string.Format("Hash {0} with type {1} does not have a valid flag thingy...apparently", hash.ToHex(), fileType.ToString("X")));
                    }
                }
            }
            if (input.Position != input.Length)
            {
                //throw new Exception("Incomplete!");
            }
        }
Пример #8
0
        public void ReadXML(XmlReader reader)
        {
            reader.ReadToFollowing("properties");
            while (reader.Read())
            {
                if (reader.IsStartElement())
                {
                    string typeName = reader.Name;
                    uint   hash;
                    string hashText = reader.GetAttribute("id");
                    if (hashText != null)
                    {
                        // This is a "legacy" file generated by Gibbed.Modmaker etc
                        hash = hashText.GetHexNumber();
                    }
                    else
                    {
                        hash = SporeMaster.NameRegistry.Properties.toHash(reader.GetAttribute("name"));
                    }

                    PropertyLookup lookup = PropTypes.FindPropertyType(typeName);

                    if (lookup == null)
                    {
                        throw new Exception("unknown type " + typeName);
                    }

                    Property property = null;

                    // Singular
                    if (lookup.Definition.Name == typeName)
                    {
                        property = Activator.CreateInstance(lookup.Type) as Property;
                        property.ReadXML(reader);
                    }
                    // Plural
                    else if (lookup.Definition.PluralName == typeName)
                    {
                        ArrayProperty array = new ArrayProperty();
                        array.PropertyType = lookup.Type;

                        var subtree = reader.ReadSubtree();
                        subtree.ReadToFollowing(typeName);

                        while (subtree.Read())
                        {
                            if (subtree.IsStartElement())
                            {
                                if (subtree.Name != lookup.Definition.Name)
                                {
                                    throw new Exception("array element for " + typeName + " is not the right type");
                                }

                                Property subproperty = Activator.CreateInstance(lookup.Type) as Property;
                                subproperty.ReadXML(subtree);

                                array.Values.Add(subproperty);
                            }
                        }

                        property = array;
                    }

                    this.Values[hash] = property;
                }
            }
        }
Пример #9
0
        public void Write(Stream output)
        {
            output.WriteS32BE(this.Values.Count);

            // Important!  Rick's code didn't do this, which meant packed property files could randomly break
            // (order of keys from Dictionary is undefined).  In practice it seems to have worked when input XML
            // is in order, but people didn't know that...
            var keys = from k in this.Values.Keys orderby k select k;

            foreach (uint hash in keys)
            {
                Property property = this.Values[hash];

                output.WriteU32BE(hash);

                if (property is ArrayProperty)
                {
                    ArrayProperty array = (ArrayProperty)property;
                    output.WriteU16BE(PropTypes.FindPropertyType(array.PropertyType).FileType);
                    output.WriteU16BE(0x30);
                }
                else if (property is ComplexProperty)
                {
                    output.WriteU16BE(PropTypes.FindPropertyType(this.Values[hash].GetType()).FileType);
                    output.WriteU16BE(0x30);
                }
                else
                {
                    output.WriteU16BE(PropTypes.FindPropertyType(this.Values[hash].GetType()).FileType);
                    output.WriteU16BE(0);
                }

                if (property is ArrayProperty)
                {
                    ArrayProperty array = (ArrayProperty)property;

                    MemoryStream[] memories = new MemoryStream[array.Values.Count];

                    int  index   = 0;
                    uint maxSize = 0;
                    foreach (Property subproperty in array.Values)
                    {
                        memories[index] = new MemoryStream();
                        subproperty.WriteProp(memories[index], true);

                        if (memories[index].Length > maxSize)
                        {
                            maxSize = (uint)memories[index].Length;
                        }

                        index++;
                    }

                    output.WriteU32BE((uint)memories.Length);
                    output.WriteU32BE(maxSize);

                    for (int i = 0; i < memories.Length; i++)
                    {
                        byte[] data = new byte[array.Values[i] is ComplexProperty ? maxSize : memories[i].Length];
                        memories[i].Seek(0, SeekOrigin.Begin);
                        memories[i].Read(data, 0, (int)(memories[i].Length));
                        output.Write(data, 0, data.Length);
                    }
                }
                else
                {
                    MemoryStream memory = new MemoryStream();
                    property.WriteProp(memory, false);

                    memory.Seek(0, SeekOrigin.Begin);

                    if (property is ComplexProperty)
                    {
                        output.WriteU32BE(1);
                        output.WriteU32BE((uint)memory.Length);
                    }

                    byte[] data = new byte[memory.Length];
                    memory.Read(data, 0, (int)memory.Length);
                    output.Write(data, 0, data.Length);
                }
            }
        }
Пример #10
0
        public void Read(Stream input)
        {
            uint count    = input.ReadU32BE();
            uint lasthash = 0;

            for (uint i = 0; i < count; i++)
            {
                uint   hash     = input.ReadU32BE();
                ushort fileType = input.ReadU16BE();
                ushort flags    = input.ReadU16BE();

                if (i > 0 && hash < lasthash)
                {
                    throw new Exception("property file has keys out of order: " + lasthash.ToString("X8") + ", " + hash.ToString("X8"));
                }
                lasthash = hash;

                if (this.Values.ContainsKey(hash))
                {
                    throw new Exception("property file already has " + hash.ToString("X8") + " defined");
                }

                Property property = null;
                Type     type     = PropTypes.GetTypeFromFileType(fileType);

                if (type == null)
                {
                    throw new Exception("invalid type " + fileType.ToString());
                }

                if ((flags & 0x30) == 0)                 // is not variant?
                {
                    property = Activator.CreateInstance(type) as Property;
                    property.ReadProp(input, false);

                    this.Values[hash] = property;
                }
                // Variant
                else if ((flags & 0x40) == 0)                 // is not empty?
                {
                    ArrayProperty array = new ArrayProperty();
                    array.PropertyType = type;

                    int arrayCount    = input.ReadS32BE();
                    int arrayItemSize = input.ReadS32BE();

                    for (uint j = 0; j < arrayCount; j++)
                    {
                        Property subproperty = Activator.CreateInstance(type) as Property;

                        if (subproperty is ComplexProperty)
                        {
                            MemoryStream memory = new MemoryStream();
                            byte[]       data   = new byte[arrayItemSize];
                            input.Read(data, 0, arrayItemSize);
                            memory.Write(data, 0, arrayItemSize);
                            memory.Seek(0, SeekOrigin.Begin);

                            subproperty.ReadProp(memory, true);
                        }
                        else
                        {
                            subproperty.ReadProp(input, true);
                        }

                        array.Values.Add(subproperty);
                    }

                    property = array;

                    this.Values[hash] = property;
                }
            }
        }