Example #1
0
        public FileInstance(string className = "Instance", string name = "Instance")
        {
            FileProperty propName = new FileProperty();

            propName.Type     = PropertyType.String;
            propName.Instance = this;
            propName.Name     = "Name";
            propName.Value    = name;

            ClassName = className;
            Properties.Add(propName);
        }
Example #2
0
        public object ReadProperty(string propertyName)
        {
            FileProperty property = null;

            var query = Properties.Where((prop) => prop.Name.ToLower() == propertyName.ToLower());

            if (query.Count() > 0)
            {
                property = query.First();
            }

            return(property != null ? property.Value : null);
        }
Example #3
0
 public void AddProperty(ref FileProperty prop)
 {
     Properties.Add(prop);
 }
Example #4
0
        public void ReadProperties(RobloxBinaryFile file)
        {
            INST type = file.Types[TypeIndex];

            FileProperty[] props = new FileProperty[type.NumInstances];

            int[] ids       = type.InstanceIds;
            int   instCount = type.NumInstances;

            for (int i = 0; i < instCount; i++)
            {
                int          id       = ids[i];
                FileInstance instance = file.Instances[id];

                FileProperty prop = new FileProperty();
                prop.Instance = instance;
                prop.Name     = Name;
                prop.Type     = Type;

                props[i] = prop;
                instance.AddProperty(ref prop);
            }

            // Setup some short-hand functions for actions frequently used during the read procedure.
            var readInts   = new Func <int[]>(() => Reader.ReadInts(instCount));
            var readFloats = new Func <float[]>(() => Reader.ReadFloats(instCount));

            var loadProperties = new Action <Func <int, object> >(read =>
            {
                for (int i = 0; i < instCount; i++)
                {
                    object result  = read(i);
                    props[i].Value = result;
                }
            });

            // Read the property data based on the property type.
            // NOTE: This only reads the property types needed for Rbx2Source.
            //       You can visit the following link for a full implementation:
            //       https://github.com/CloneTrooper1019/Roblox-File-Format/blob/master/BinaryFormat/ChunkTypes/PROP.cs

            switch (Type)
            {
            case PropertyType.String:
                loadProperties(i => Reader.ReadString());
                break;

            case PropertyType.Bool:
                loadProperties(i => Reader.ReadBoolean());
                break;

            case PropertyType.Int:
                int[] ints = readInts();
                loadProperties(i => ints[i]);
                break;

            case PropertyType.Float:
                float[] floats = readFloats();
                loadProperties(i => floats[i]);
                break;

            case PropertyType.Double:
                loadProperties(i => Reader.ReadDouble());
                break;

            case PropertyType.Vector3:
                float[] Vector3_X = readFloats(),
                Vector3_Y = readFloats(),
                Vector3_Z = readFloats();

                loadProperties(i =>
                {
                    float x = Vector3_X[i],
                    y       = Vector3_Y[i],
                    z       = Vector3_Z[i];

                    return(new Vector3(x, y, z));
                });

                break;

            case PropertyType.BrickColor:
                int[] brickColorIds = readInts();

                loadProperties(i =>
                {
                    int brickColorId = brickColorIds[i];
                    return(BrickColor.FromNumber(brickColorId));
                });

                break;

            case PropertyType.CFrame:
            case PropertyType.Quaternion:
                // Temporarily load the rotation matrices into their properties.
                // We'll update them to CFrames once we iterate over the position data.

                loadProperties(i =>
                {
                    int normXY = Reader.ReadByte();

                    if (normXY > 0)
                    {
                        // Make sure this value is in a safe range.
                        normXY = (normXY - 1) % 36;

                        NormalId normX = (NormalId)(normXY / 6);
                        Vector3 R0     = Vector3.FromNormalId(normX);

                        NormalId normY = (NormalId)(normXY % 6);
                        Vector3 R1     = Vector3.FromNormalId(normY);

                        // Compute R2 using the cross product of R0 and R1.
                        Vector3 R2 = R0.Cross(R1);

                        // Generate the rotation matrix and return it.
                        return(new float[9]
                        {
                            R0.X, R0.Y, R0.Z,
                            R1.X, R1.Y, R1.Z,
                            R2.X, R2.Y, R2.Z,
                        });
                    }
                    else if (Type == PropertyType.Quaternion)
                    {
                        float qx = Reader.ReadFloat(), qy = Reader.ReadFloat(),
                        qz       = Reader.ReadFloat(), qw = Reader.ReadFloat();

                        Quaternion quaternion = new Quaternion(qx, qy, qz, qw);
                        var rotation          = quaternion.ToCFrame();

                        return(rotation.GetComponents());
                    }
                    else
                    {
                        float[] matrix = new float[9];

                        for (int m = 0; m < 9; m++)
                        {
                            float value = Reader.ReadFloat();
                            matrix[m]   = value;
                        }

                        return(matrix);
                    }
                });

                float[] CFrame_X = readFloats(),
                CFrame_Y = readFloats(),
                CFrame_Z = readFloats();

                loadProperties(i =>
                {
                    float[] matrix = props[i].Value as float[];

                    float x = CFrame_X[i],
                    y       = CFrame_Y[i],
                    z       = CFrame_Z[i];

                    float[] position = new float[3] {
                        x, y, z
                    };
                    float[] components = position
                                         .Concat(matrix)
                                         .ToArray();

                    return(new CFrame(components));
                });

                break;

            case PropertyType.Enum:
                uint[] enums = Reader.ReadInterleaved(instCount, BitConverter.ToUInt32);
                loadProperties(i => enums[i]);

                break;

            case PropertyType.Ref:
                int[] instIds = Reader.ReadInstanceIds(instCount);

                loadProperties(i =>
                {
                    int instId = instIds[i];
                    return(instId >= 0 ? file.Instances[instId] : null);
                });

                break;

            case PropertyType.Color3uint8:
                byte[] Color3uint8_R = Reader.ReadBytes(instCount),
                Color3uint8_G = Reader.ReadBytes(instCount),
                Color3uint8_B = Reader.ReadBytes(instCount);

                loadProperties(i =>
                {
                    byte r = Color3uint8_R[i],
                    g      = Color3uint8_G[i],
                    b      = Color3uint8_B[i];

                    return(Color.FromArgb(r, g, b));
                });

                break;

            case PropertyType.Int64:
                long[] int64s = Reader.ReadInterleaved(instCount, (buffer, start) =>
                {
                    long result = BitConverter.ToInt64(buffer, start);
                    return((long)((ulong)result >> 1) ^ (-(result & 1)));
                });

                loadProperties(i => int64s[i]);
                break;
            }

            Reader.Dispose();
        }