Example #1
0
 private void TrySetClassnameString()
 {
     if (HashGuesser.TryGuessHashString(ClassnameHash, out var maybeClassname))
     {
         Classname = maybeClassname;
     }
 }
Example #2
0
        public XElement WriteToXml()
        {
            //Create object node
            HashGuesser.TryGuessHashString(ClassnameHash, out string className);
            var objectRoot = new XElement("ZoneObject", new XAttribute("Type", className));

            var objectData = new XElement("Data");

            objectRoot.Add(objectData);

            //Write 56 byte data block
            objectData.Add(new XAttribute("ClassnameHash", ClassnameHash));
            objectData.Add(new XElement("Handle", Handle));
            objectData.Add(Bmin.ToXElement("Bmin"));
            objectData.Add(Bmax.ToXElement("Bmax"));

            var flagsNode = new XElement("Flags", new XAttribute("Value", Flags));

            flagsNode.Add(new XElement("Flag0", (Flags & (ushort)ZoneObjectFlags.Flag0) != 0));
            flagsNode.Add(new XElement("Flag1", (Flags & (ushort)ZoneObjectFlags.Flag1) != 0));
            flagsNode.Add(new XElement("Flag2", (Flags & (ushort)ZoneObjectFlags.Flag2) != 0));
            flagsNode.Add(new XElement("Flag3", (Flags & (ushort)ZoneObjectFlags.Flag3) != 0));
            flagsNode.Add(new XElement("Flag4", (Flags & (ushort)ZoneObjectFlags.Flag4) != 0));
            flagsNode.Add(new XElement("Flag5", (Flags & (ushort)ZoneObjectFlags.Flag5) != 0));
            flagsNode.Add(new XElement("Flag6", (Flags & (ushort)ZoneObjectFlags.Flag6) != 0));
            flagsNode.Add(new XElement("Flag7", (Flags & (ushort)ZoneObjectFlags.Flag7) != 0));
            flagsNode.Add(new XElement("Flag8", (Flags & (ushort)ZoneObjectFlags.Flag8) != 0));
            flagsNode.Add(new XElement("Flag9", (Flags & (ushort)ZoneObjectFlags.Flag9) != 0));
            flagsNode.Add(new XElement("Flag10", (Flags & (ushort)ZoneObjectFlags.Flag10) != 0));
            flagsNode.Add(new XElement("Flag11", (Flags & (ushort)ZoneObjectFlags.Flag11) != 0));
            flagsNode.Add(new XElement("Flag12", (Flags & (ushort)ZoneObjectFlags.Flag12) != 0));
            flagsNode.Add(new XElement("Flag13", (Flags & (ushort)ZoneObjectFlags.Flag13) != 0));
            flagsNode.Add(new XElement("Flag14", (Flags & (ushort)ZoneObjectFlags.Flag14) != 0));
            flagsNode.Add(new XElement("Flag15", (Flags & (ushort)ZoneObjectFlags.Flag15) != 0));
            objectData.Add(flagsNode);

            objectData.Add(new XAttribute("BlockSize", BlockSize));
            objectData.Add(new XElement("Parent", Parent));
            objectData.Add(new XElement("Sibling", Sibling));
            objectData.Add(new XElement("Child", Child));
            objectData.Add(new XElement("Num", Num));
            objectData.Add(new XAttribute("NumProps", NumProps));
            objectData.Add(new XAttribute("Size", Size));

            var propertiesNode = new XElement("Properties");

            objectRoot.Add(propertiesNode);
            //Write properties
            foreach (var property in Properties)
            {
                propertiesNode.Add(property.WriteToXml());
            }
            //Return object node
            return(objectRoot);
        }
Example #3
0
        /// <summary>
        /// Attempt to read the rfgzone_pc/layer_pc format from the stream. Fill this class with that data.
        /// </summary>
        /// <param name="stream">The stream to read the data from.</param>
        public void ReadFromBinary(Stream stream)
        {
            var reader = new BinaryReader(stream);

            //Read header
            Signature = reader.ReadUInt32();
            if (Signature != 1162760026) //Should equal ascii value for "ZONE"
            {
                Console.WriteLine($"Error! Invalid file signature. Expected 1162760026, detected {Signature}. Make sure the vpp/str2 containing this file was extracted properly. Exiting.");
                return;
            }
            Version = reader.ReadUInt32();
            if (Version != 36) //Only have seen and reversed version 36
            {
                Console.WriteLine($"Error! Unsupported format version. Expected 36, detected {Version}. Exiting.");
                return;
            }
            NumObjects    = reader.ReadUInt32();
            NumHandles    = reader.ReadUInt32();
            DistrictHash  = reader.ReadUInt32(); //Todo: Figure out how district hashes are generated
            DistrictFlags = reader.ReadUInt32();

            //Try to get district name from hash. Note that p_ files always have 0 for the hash. Game likely pulls from matching non p_ file
            if (HashGuesser.TryGuessHashString(DistrictHash, out string districtName))
            {
                DistrictName = districtName;
            }

            //Todo: Make sure it's safe to skip this on zones with numHandles != 0
            //Todo: Try deleting relational data on all zones and seeing if that causes an issue.

            /*
             * Relation data section. Likely a structure directly mapped to memory.
             * Isn't present if districtFlags equals 1, 4, or 5 (if the 0th and 2nd bits are true)
             * I've only seen layer_pc have a flag equal to 4 and rfgzone_pc either 1 or 0 (0 means they have relational_data)
             * Skip by default, since in my tests so far this entire section can be zeroed out without issue.
             * Can later add code to handle it if it turns out to be required.
             */
#if IgnoreRelationData
            if ((DistrictFlags & 5) == 0)                          //Relation data section only present when this condition is met.
            {
                reader.BaseStream.Seek(87368, SeekOrigin.Current); //Offset: 87392
            }
#else
            if ((DistrictFlags & 5) == 0)
            {
                //Totals to 87368
                var stupid_vtable_padding = reader.ReadBytes(4);   //4
                var free = reader.ReadBytes(2);                    //2
                var slot = reader.ReadBytes(14560);                //2 * 7280 //starts at 30
                var next = reader.ReadBytes(14560);                //2 * 7280 //starts at 14590
                var more_stupid_padding = reader.ReadBytes(2);     //2 //starts at 29150
                var entry_key           = reader.ReadBytes(29120); //4 * 7280 //starts at 29152 //Might be 4 * numObjects bytes of data for keys, rest is useless, can be deleted/omitted. (Same with other arrays)
                var entry_data          = reader.ReadBytes(29120); //4 * 7280 //starts at 58272
                //Ends at 87392
            }
#endif

            //Read zone objects
            for (int i = 0; i < NumObjects; i++)
            {
                var zoneObject = new ZoneObject();
                zoneObject.ReadFromBinary(stream);
                Objects.Add(zoneObject);
            }
#if DEBUG
            Console.WriteLine($"Last zone object ends at offset {reader.BaseStream.Position}");
#endif
        }