Пример #1
0
        public object Clone()
        {
            var zoneObject = new ZoneObject
            {
                ClassnameHash = this.ClassnameHash,
                Handle        = this.Handle,
                Bmin          = this.Bmin,
                Bmax          = this.Bmax,
                Flags         = this.Flags,
                BlockSize     = this.BlockSize,
                Parent        = this.Parent,
                Sibling       = this.Sibling,
                Child         = this.Child,
                Num           = this.Num,

                NumProps = this.NumProps,
                Size     = this.Size,

                Properties = this.Properties.ConvertAll(prop => prop),

                Classname   = this.Classname,
                Description = this.Description,
            };

            return(zoneObject);
        }
Пример #2
0
        /// <summary>
        /// Attempt to read xml data from document.
        /// </summary>
        public void ReadFromXml(XDocument document)
        {
            var root = document.Root;

            //Read header
            var header = root.GetRequiredElement("Header");

            Signature     = header.GetRequiredAttributeValue("Signature").ToUint32();
            Version       = header.GetRequiredAttributeValue("Version").ToUint32();
            NumObjects    = header.GetRequiredAttributeValue("NumObjects").ToUint32();
            NumHandles    = header.GetRequiredAttributeValue("NumHandles").ToUint32();
            DistrictHash  = header.GetRequiredAttributeValue("DistrictHash").ToUint32();
            DistrictFlags = header.GetRequiredAttributeValue("DistrictFlags").ToUint32();

            //Would load relation data here if that section turns out to be necessary

            //Read zone objects
            var zoneObjectsNode = root.GetRequiredElement("ZoneObjects");

            foreach (var objectNode in zoneObjectsNode.Elements("ZoneObject"))
            {
                var zoneObject = new ZoneObject();
                zoneObject.ReadFromXml(objectNode);
                Objects.Add(zoneObject);
            }
            NumObjects = (uint)Objects.Count; //Update object count in case whoever edited the xml forgot to
        }
Пример #3
0
        public ZoneObject DuplicateObject(ZoneObject obj)
        {
            int objIndex = Objects.IndexOf(obj);

            if (objIndex == -1)
            {
                return(null);
            }

            var newObj = obj.Clone() as ZoneObject;

            if (newObj == null)
            {
                return(null);
            }

            newObj.Num    = GetUniqueNum(); //Further testing needed to see if this is necessary, likely can have same num as other objs as long as they are a different class
            newObj.Handle = GetUniqueHandle();

            Objects.Insert(objIndex + 1, newObj);
            return(newObj);
        }
Пример #4
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
        }