예제 #1
0
        // Methods
        public override void Load(Stream fileStream,
                                  Dictionary <string, SetObjectType> objectTemplates)
        {
            // Header
            var reader = new BINAReader(fileStream);

            Header = reader.ReadHeader();

            //Set Name (hardcoded to ASSUME it's four characters long)
            long namePosition = reader.BaseStream.Position; //Save position so we can jump back after reading name, type and parameters

            reader.JumpAhead(0xC);
            Name = reader.ReadNullTerminatedString();
            reader.JumpTo(namePosition, true);
            reader.JumpAhead(0x2C);

            uint objectCount       = reader.ReadUInt32();
            uint objectTableOffset = reader.ReadUInt32();
            uint groupCount        = reader.ReadUInt32();
            uint groupTableOffset  = reader.ReadUInt32();

            //Objects
            reader.JumpTo(objectTableOffset, false);
            for (uint i = 0; i < objectCount; i++)
            {
                var obj = new SetObject();
                obj.ObjectID = i;
                uint objectNameOffset = reader.ReadUInt32();
                uint objectTypeOffset = reader.ReadUInt32();
                obj.UnknownBytes       = reader.ReadBytes(16); //parameter.Unknown 16 bytes (pattern tends to be 40 00 00 00/01 (depending on whether object is activated by a group) 00 00 00 00 00 00 00 00 00 00 00 00)
                obj.Transform.Position = reader.ReadVector3();
                obj.DrawDistance       = reader.ReadSingle();
                obj.Transform.Rotation = reader.ReadQuaternion();
                uint parameterCount  = reader.ReadUInt32();
                uint parameterOffset = reader.ReadUInt32();

                long position = reader.BaseStream.Position; //Save position so we can jump back after reading name, type and parameters

                //Object Name and Type
                reader.JumpTo(objectNameOffset, false);
                obj.ObjectName = reader.ReadNullTerminatedString();
                reader.JumpTo(objectTypeOffset, false);
                obj.ObjectType = reader.ReadNullTerminatedString();

                reader.JumpTo(parameterOffset, false);
                //Object Parameters
                for (uint c = 0; c < parameterCount; c++)
                {
                    var  parameter     = new SetObjectParam();
                    uint parameterType = reader.ReadUInt32();
                    switch (parameterType)
                    {
                    case 0:     //boolean
                        parameter.DataType = typeof(bool);
                        parameter.Data     = reader.ReadUInt32() == 1;
                        parameter.Unknown1 = reader.ReadUInt32();
                        parameter.Unknown2 = reader.ReadUInt32();
                        parameter.Unknown3 = reader.ReadUInt32();
                        break;

                    case 1:     //int
                        parameter.DataType = typeof(int);
                        parameter.Data     = reader.ReadInt32();
                        parameter.Unknown1 = reader.ReadUInt32();
                        parameter.Unknown2 = reader.ReadUInt32();
                        parameter.Unknown3 = reader.ReadUInt32();
                        break;

                    case 2:     //single
                        parameter.DataType = typeof(float);
                        parameter.Data     = reader.ReadSingle();
                        parameter.Unknown1 = reader.ReadUInt32();
                        parameter.Unknown2 = reader.ReadUInt32();
                        parameter.Unknown3 = reader.ReadUInt32();
                        break;

                    case 3:     //string
                        uint offset = reader.ReadUInt32();
                        parameter.Unknown1 = reader.ReadUInt32();
                        parameter.Unknown2 = reader.ReadUInt32();
                        parameter.Unknown3 = reader.ReadUInt32();

                        long stringParameterPosition = reader.BaseStream.Position;     //Save position so we can jump back after reading name, type and parameters
                        reader.JumpTo(offset, false);

                        parameter.DataType = typeof(string);
                        parameter.Data     = reader.ReadNullTerminatedString();

                        reader.JumpTo(stringParameterPosition, true);
                        break;

                    case 4:     //Vector3
                        parameter.DataType = typeof(Vector3);
                        parameter.Data     = reader.ReadVector3();
                        parameter.Unknown3 = reader.ReadUInt32();
                        break;

                    case 6:     //uint
                        parameter.DataType = typeof(uint);
                        parameter.Data     = reader.ReadUInt32();
                        parameter.Unknown1 = reader.ReadUInt32();
                        parameter.Unknown2 = reader.ReadUInt32();
                        parameter.Unknown3 = reader.ReadUInt32();
                        break;

                    default:
                        Console.WriteLine("Unhandled Data Type!");
                        break;
                    }
                    obj.Parameters.Add(parameter);
                }

                //Save Object and jump back for the next one
                Objects.Add(obj);
                reader.JumpTo(position, true);
            }

            //Groups
            reader.JumpTo(groupTableOffset, false);
            for (uint i = 0; i < groupCount; i++)
            {
                var  group           = new SetGroup();
                uint groupNameOffset = reader.ReadUInt32();
                uint groupTypeOffset = reader.ReadUInt32();
                group.GroupObjectCount = reader.ReadUInt32();
                uint groupObjectListOffset = reader.ReadUInt32();

                long position = reader.BaseStream.Position; //Save position so we can jump back after reading name, type and object list

                //Group Name and Type
                reader.JumpTo(groupNameOffset, false);
                group.GroupName = reader.ReadNullTerminatedString();
                reader.JumpTo(groupTypeOffset, false);
                group.GroupType = reader.ReadNullTerminatedString();

                //Group Object List
                reader.JumpTo(groupObjectListOffset, false);
                for (uint c = 0; c < group.GroupObjectCount; c++)
                {
                    reader.JumpAhead(4);
                    group.ObjectIDs.Add(reader.ReadUInt32());
                }

                //Save Group and jump back for the next one
                Groups.Add(group);
                reader.JumpTo(position, true);
            }
        }
예제 #2
0
        public void ImportXML(Stream fileStream)
        {
            // Load XML and add loaded data to set data
            var xml = XDocument.Load(fileStream);

            Name = xml.Root.Attribute("name").Value;
            uint objID = 0; // For Object elements with no ID attribute.

            foreach (var objElem in xml.Root.Elements("Object"))
            {
                // Generate Object
                var typeAttr    = objElem.Attribute("type");
                var objIDAttr   = objElem.Attribute("id");
                var objNameAttr = objElem.Attribute("name");
                if (typeAttr == null)
                {
                    continue;
                }

                var obj = new SetObject()
                {
                    ObjectType = typeAttr.Value,
                    ObjectName = objNameAttr.Value,
                    ObjectID   = (objIDAttr == null) ?
                                 objID : Convert.ToUInt32(objIDAttr.Value),
                };

                // Assign CustomData to Object
                var customDataElem = objElem.Element("CustomData");
                if (customDataElem != null)
                {
                    foreach (var customData in customDataElem.Elements())
                    {
                        obj.CustomData.Add(customData.Name.LocalName,
                                           LoadParam(customData));
                    }
                }

                //Assign Draw Distance to Object
                var drawDistanceElem = objElem.Element("DrawDistance");
                obj.DrawDistance = float.Parse(drawDistanceElem.Value);

                //Assign Unknown Bytes to object
                var    unknownBytesElem = objElem.Element("UnknownBytes");
                int    byteNumber       = 0;
                byte[] bytesXML         = new byte[16];
                foreach (var bytes in unknownBytesElem.Elements())
                {
                    bytesXML[byteNumber] = (byte)int.Parse(bytes.Value);
                    byteNumber++;
                }
                obj.UnknownBytes = bytesXML;

                // Assign Parameters to Object
                var parametersElem = objElem.Element("Parameters");
                if (parametersElem != null)
                {
                    foreach (var paramElem in parametersElem.Elements())
                    {
                        obj.Parameters.Add(LoadParam(paramElem));
                    }
                }

                // Assign Transforms to Object
                var transformsElem = objElem.Element("Transforms");
                if (transformsElem != null)
                {
                    var transforms     = transformsElem.Elements("Transform");
                    int transformCount = transforms.Count();

                    if (transformCount > 0)
                    {
                        uint i = 0;
                        obj.Children = new SetObjectTransform[transformCount - 1];

                        foreach (var transformElem in transforms)
                        {
                            var transform = LoadTransform(transformElem);
                            if (i > 0)
                            {
                                obj.Children[i - 1] = transform;
                            }
                            else
                            {
                                obj.Transform = transform;
                            }

                            ++i;
                        }
                    }
                }

                ++objID;
                Objects.Add(obj);
            }

            foreach (var groupElm in xml.Root.Elements("Group"))
            {
                var groupNameElem        = groupElm.Element("Name");
                var groupObjectCountElem = groupElm.Element("ObjectCount");
                var groupTypeElem        = groupElm.Element("Type");
                var group = new SetGroup()
                {
                    GroupName        = groupNameElem.Value,
                    GroupObjectCount = uint.Parse(groupObjectCountElem.Value),
                    GroupType        = groupTypeElem.Value
                };
                var objectsElem = groupElm.Element("ObjectIDs");
                if (objectsElem != null)
                {
                    foreach (var objectIDElem in objectsElem.Elements())
                    {
                        group.ObjectIDs.Add(uint.Parse(objectIDElem.Value));
                    }
                }
                Groups.Add(group);
            }

            // Sub-Methods
            SetObjectParam LoadParam(XElement paramElem)
            {
                // Groups
                var dataTypeAttr = paramElem.Attribute("type");

                if (dataTypeAttr == null)
                {
                    var  padAttr = paramElem.Attribute("padding");
                    uint?padding = null;

                    if (uint.TryParse(padAttr?.Value, out var pad))
                    {
                        padding = pad;
                    }

                    var group      = new SetObjectParamGroup(padding);
                    var parameters = group.Parameters;

                    foreach (var param in paramElem.Elements())
                    {
                        parameters.Add(LoadParam(param));
                    }

                    return(group);
                }

                // Parameters
                var    dataType = Types.GetTypeFromString(dataTypeAttr.Value);
                object data     = null;

                if (dataType == typeof(Vector2))
                {
                    data = Helpers.XMLReadVector2(paramElem);
                }
                else if (dataType == typeof(Vector3))
                {
                    data = Helpers.XMLReadVector3(paramElem);
                }
                else if (dataType == typeof(Vector4))
                {
                    data = Helpers.XMLReadVector4(paramElem);
                }
                else if (dataType == typeof(Quaternion))
                {
                    data = Helpers.XMLReadQuat(paramElem);
                }
                else if (dataType == typeof(uint[]))
                {
                    var  countAttr = paramElem.Attribute("count");
                    uint arrLength = 0;

                    if (countAttr != null)
                    {
                        uint.TryParse(countAttr.Value, out arrLength);
                    }

                    var values = paramElem.Value.Split(',');
                    var arr    = new uint[arrLength];
                    for (uint i = 0; i < arrLength; ++i)
                    {
                        if (i >= values.Length)
                        {
                            break;
                        }

                        uint.TryParse(values[i], out arr[i]);
                    }

                    data = arr;
                }
                else if (dataType == typeof(ForcesSetData.ObjectReference[]))
                {
                    var  countAttr = paramElem.Attribute("count");
                    uint arrLength = 0;

                    if (countAttr != null)
                    {
                        uint.TryParse(countAttr.Value, out arrLength);
                    }

                    uint i   = 0;
                    var  arr = new ForcesSetData.ObjectReference[arrLength];

                    foreach (var refElem in paramElem.Elements("ForcesObjectReference"))
                    {
                        var objRef = new ForcesSetData.ObjectReference();
                        objRef.ImportXML(refElem);
                        arr[i] = objRef;
                        ++i;
                    }

                    data = arr;
                }
                else if (dataType == typeof(ForcesSetData.ObjectReference))
                {
                    var objRef = new ForcesSetData.ObjectReference();
                    objRef.ImportXML(paramElem);
                    data = objRef;
                }
                else
                {
                    data = Convert.ChangeType(paramElem.Value, dataType);
                }

                return(new SetObjectParam(dataType, data));
            }

            SetObjectTransform LoadTransform(XElement elem)
            {
                var posElem   = elem.Element("Position");
                var rotElem   = elem.Element("Rotation");
                var scaleElem = elem.Element("Scale");

                return(new SetObjectTransform()
                {
                    Position = Helpers.XMLReadVector3(posElem),
                    Rotation = Helpers.XMLReadQuat(rotElem),
                    Scale = Helpers.XMLReadVector3(scaleElem)
                });
            }
        }