Exemplo n.º 1
0
        public BinaryFile(byte[] contents)
        {
            using (MemoryStream file = new MemoryStream(contents))
                using (BinaryReader inStream = new BinaryReader(file))
                {
                    Headers   = new BinaryChunkHEAD(inStream);
                    Instances = new ClassDescriptor[Headers.NumInstances];

                    // Begin reading the file chunks.
                    bool firstChunk = true;
                    Chunks = new List <BinaryChunk>();

                    while (true)
                    {
                        try
                        {
                            BinaryChunk chunk = new BinaryChunk(inStream);
                            Chunks.Add(chunk);

                            if (chunk.ChunkType == BinaryChunkType.INST)
                            {
                                BinaryChunkINST inst = new BinaryChunkINST(chunk);
                                INSTs.Add(inst);
                            }
                            else if (chunk.ChunkType == BinaryChunkType.PROP)
                            {
                                BinaryChunkPROP prop = new BinaryChunkPROP(chunk);
                                PROPs.Add(prop);
                            }
                            else if (chunk.ChunkType == BinaryChunkType.PRNT)
                            {
                                ParentLinks = new BinaryChunkPRNT(chunk);
                            }
                            else if (chunk.ChunkType == BinaryChunkType.META)
                            {
                                if (firstChunk)
                                {
                                    Metadata = new BinaryChunkMETA(chunk);
                                }
                                else
                                {
                                    throw new Exception("Unexpected metadata chunk");
                                }
                            }
                            else if (chunk.ChunkType == BinaryChunkType.END)
                            {
                                break;
                            }

                            firstChunk = false;
                        }
                        catch (EndOfStreamException)
                        {
                            throw new Exception("Unexpected end of file!");
                        }
                    }

                    foreach (BinaryChunkINST inst in INSTs)
                    {
                        foreach (int id in inst.InstanceIds)
                        {
                            ClassDescriptor bind = new ClassDescriptor();
                            bind.ClassName = inst.TypeName;
                            Instances[id]  = bind;
                        }
                    }

                    foreach (BinaryChunkPROP prop in PROPs)
                    {
                        BinaryChunkINST inst = INSTs[prop.Index];
                        prop.ReadPropertyValues(inst, Instances);
                    }

                    for (int i = 0; i < ParentLinks.LinkCount; i++)
                    {
                        int objectId = ParentLinks.ObjectIds[i];
                        int parentId = ParentLinks.ParentIds[i];

                        if (parentId >= 0)
                        {
                            Instances[objectId].Parent = Instances[parentId];
                        }
                        else
                        {
                            TreeRoot.Add(Instances[objectId]);
                        }
                    }
                }
        }
Exemplo n.º 2
0
        public void ReadPropertyValues(BinaryChunkINST instChunk, ClassDescriptor[] instMap)
        {
            int[] ids       = instChunk.InstanceIds;
            int   instCount = ids.Length;

            props = new PropertyDescriptor[instCount];

            for (int i = 0; i < instCount; i++)
            {
                PropertyDescriptor prop = new PropertyDescriptor();
                prop.Name   = Name;
                prop.Format = Format;

                props[i] = prop;
                instMap[ids[i]].Properties.Add(prop);
            }

            if (Format == BinaryPropertyFormat.String)
            {
                for (int i = 0; i < instCount; i++)
                {
                    props[i].Value = BinaryFile.ReadString(reader);
                }
            }
            else if (Format == BinaryPropertyFormat.Bool)
            {
                for (int i = 0; i < instCount; i++)
                {
                    props[i].Value = reader.ReadBoolean();
                }
            }
            else if (Format == BinaryPropertyFormat.Int)
            {
                int[] values = BinaryFile.ReadInts(reader, instCount);
                for (int i = 0; i < instCount; i++)
                {
                    props[i].Value = values[i];
                }
            }
            else if (Format == BinaryPropertyFormat.Float)
            {
                float[] values = BinaryFile.ReadFloats(reader, instCount);
                for (int i = 0; i < instCount; i++)
                {
                    props[i].Value = values[i];
                }
            }
            else if (Format == BinaryPropertyFormat.Double)
            {
                for (int i = 0; i < instCount; i++)
                {
                    props[i].Value = reader.ReadDouble();
                }
            }
            else if (Format == BinaryPropertyFormat.UDim)
            {
                float[] scales  = BinaryFile.ReadFloats(reader, instCount);
                int[]   offsets = BinaryFile.ReadInts(reader, instCount);

                for (int i = 0; i < instCount; i++)
                {
                    props[i].Value = new UDim(scales[i], offsets[i]);
                }
            }
            else if (Format == BinaryPropertyFormat.UDim2)
            {
                float[] sx = BinaryFile.ReadFloats(reader, instCount);
                float[] sy = BinaryFile.ReadFloats(reader, instCount);

                int[] ox = BinaryFile.ReadInts(reader, instCount);
                int[] oy = BinaryFile.ReadInts(reader, instCount);

                for (int i = 0; i < instCount; i++)
                {
                    UDim x = new UDim(sx[i], ox[i]);
                    UDim y = new UDim(sy[i], oy[i]);
                    props[i].Value = new UDim[2] {
                        x, y
                    };
                }
            }
            else if (Format == BinaryPropertyFormat.Ray)
            {
                for (int i = 0; i < instCount; i++)
                {
                    Ray ray = new Ray();
                    ray.Origin     = BinaryFile.ReadFloats(reader, 3);
                    ray.Direction  = BinaryFile.ReadFloats(reader, 3);
                    props[i].Value = ray;
                }
            }
            else if (Format == BinaryPropertyFormat.Faces)
            {
                for (int i = 0; i < instCount; i++)
                {
                    props[i].Value = (Faces)reader.ReadByte();
                }
            }
            else if (Format == BinaryPropertyFormat.Axes)
            {
                for (int i = 0; i < instCount; i++)
                {
                    props[i].Value = (Axes)reader.ReadByte();
                }
            }
            else if (Format == BinaryPropertyFormat.BrickColor)
            {
                int[] values = BinaryFile.ReadInts(reader, instCount);
                for (int i = 0; i < instCount; i++)
                {
                    props[i].Value = values[i];
                }
            }
            else if (Format == BinaryPropertyFormat.Color3)
            {
                float[] r = BinaryFile.ReadFloats(reader, instCount);
                float[] g = BinaryFile.ReadFloats(reader, instCount);
                float[] b = BinaryFile.ReadFloats(reader, instCount);

                for (int i = 0; i < instCount; i++)
                {
                    props[i].Value = new float[3] {
                        r[i], g[i], b[i]
                    }
                }
                ;
            }
            else if (Format == BinaryPropertyFormat.Vector2)
            {
                float[] x = BinaryFile.ReadFloats(reader, instCount);
                float[] y = BinaryFile.ReadFloats(reader, instCount);

                for (int i = 0; i < instCount; i++)
                {
                    props[i].Value = new float[2] {
                        x[i], y[i]
                    }
                }
                ;
            }
            else if (Format == BinaryPropertyFormat.Vector3)
            {
                float[] x = BinaryFile.ReadFloats(reader, instCount);
                float[] y = BinaryFile.ReadFloats(reader, instCount);
                float[] z = BinaryFile.ReadFloats(reader, instCount);

                for (int i = 0; i < instCount; i++)
                {
                    props[i].Value = new float[3] {
                        x[i], y[i], z[i]
                    }
                }
                ;
            }
            else if (Format == BinaryPropertyFormat.CFrame || Format == BinaryPropertyFormat.Quaternion)
            {
                float[][] matrices = new float[instCount][];
                for (int i = 0; i < instCount; i++)
                {
                    byte orientId = reader.ReadByte();
                    if (orientId > 0)
                    {
                        float[] R0 = BinaryFile.GetNormalFromId((orientId - 1) / 6);
                        float[] R1 = BinaryFile.GetNormalFromId((orientId - 1) % 6);

                        // Compute R2 using the cross product of R0 and R1
                        float[] R2 =
                        {
                            R0[1] * R1[2] - R1[1] * R0[2],
                            R0[2] * R1[0] - R1[2] * R0[0],
                            R0[0] * R1[1] - R1[0] * R0[1]
                        };

                        matrices[i] = R0.Concat(R1).Concat(R2).ToArray();
                    }
                    else if (Format == BinaryPropertyFormat.Quaternion)
                    {
                        float qx = reader.ReadSingle();
                        float qy = reader.ReadSingle();
                        float qz = reader.ReadSingle();
                        float qw = reader.ReadSingle();

                        float xc = qx * 2.0f;
                        float yc = qy * 2.0f;
                        float zc = qz * 2.0f;

                        float xx = qx * xc;
                        float xy = qx * yc;
                        float xz = qx * zc;

                        float wx = qw * xc;
                        float wy = qw * yc;
                        float wz = qw * zc;

                        float yy = qy * yc;
                        float yz = qy * zc;
                        float zz = qz * zc;

                        matrices[i] = new float[9]
                        {
                            1.0f - (yy + zz),
                            xy - wz,
                            xz + wy,
                            xy + wz,
                            1.0f - (xx + zz),
                            yz - wx,
                            xz - wy,
                            yz + wx,
                            1.0f - (xx + yy)
                        };
                    }
                    else
                    {
                        float[] matrix = new float[9];

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

                        matrices[i] = matrix;
                    }
                }

                float[] x = BinaryFile.ReadFloats(reader, instCount);
                float[] y = BinaryFile.ReadFloats(reader, instCount);
                float[] z = BinaryFile.ReadFloats(reader, instCount);

                for (int i = 0; i < instCount; i++)
                {
                    float[] transform = new float[3] {
                        x[i], y[i], z[i]
                    };
                    float[] matrix = matrices[i];
                    props[i].Value = transform.Concat(matrix).ToArray();
                }
            }
            else if (Format == BinaryPropertyFormat.Enum)
            {
                uint[] enums = BinaryFile.ReadUInts(reader, instCount);
                for (int i = 0; i < instCount; i++)
                {
                    props[i].Value = enums[i];
                }
            }
            else if (Format == BinaryPropertyFormat.Ref)
            {
                int[] refs = BinaryFile.ReadInts(reader, instCount);
                for (int i = 0; i < instCount; i++)
                {
                    if (refs[i] >= 0)
                    {
                        props[i].Value = instMap[refs[i]];
                    }
                }
            }
            else if (Format == BinaryPropertyFormat.Vector3int16)
            {
                for (int i = 0; i < instCount; i++)
                {
                    short x = reader.ReadInt16();
                    short y = reader.ReadInt16();
                    short z = reader.ReadInt16();
                    props[i].Value = new short[3] {
                        x, y, z
                    };
                }
            }
            else if (Format == BinaryPropertyFormat.NumberSequence)
            {
                for (int i = 0; i < instCount; i++)
                {
                    int        numKeys  = reader.ReadInt32();
                    Keypoint[] sequence = new Keypoint[numKeys];

                    for (int k = 0; k < numKeys; k++)
                    {
                        Keypoint kp = new Keypoint();
                        kp.Time     = reader.ReadSingle();
                        kp.Value    = reader.ReadSingle();
                        kp.Envelope = reader.ReadSingle();
                        sequence[k] = kp;
                    }

                    props[i].Value = sequence;
                }
            }
            else if (Format == BinaryPropertyFormat.ColorSequence)
            {
                for (int i = 0; i < instCount; i++)
                {
                    int        numKeys  = reader.ReadInt32();
                    Keypoint[] sequence = new Keypoint[numKeys];

                    for (int k = 0; k < numKeys; k++)
                    {
                        Keypoint kp = new Keypoint();
                        kp.Time = reader.ReadSingle();

                        float r = reader.ReadSingle();
                        float g = reader.ReadSingle();
                        float b = reader.ReadSingle();
                        kp.Value = new float[3] {
                            r, g, b
                        };

                        kp.Envelope = reader.ReadSingle();
                        sequence[k] = kp;
                    }

                    props[i].Value = sequence;
                }
            }
            else if (Format == BinaryPropertyFormat.NumberRange)
            {
                for (int i = 0; i < instCount; i++)
                {
                    float min = reader.ReadSingle();
                    float max = reader.ReadSingle();
                    props[i].Value = new float[2] {
                        min, max
                    };
                }
            }
            else if (Format == BinaryPropertyFormat.Rect2D)
            {
                float[] x0 = BinaryFile.ReadFloats(reader, instCount);
                float[] y0 = BinaryFile.ReadFloats(reader, instCount);
                float[] x1 = BinaryFile.ReadFloats(reader, instCount);
                float[] y1 = BinaryFile.ReadFloats(reader, instCount);

                for (int i = 0; i < instCount; i++)
                {
                    props[i].Value = new float[4] {
                        x0[i], y0[i], x1[i], y1[i]
                    }
                }
                ;
            }
            else if (Format == BinaryPropertyFormat.PhysicalProperties)
            {
                for (int i = 0; i < instCount; i++)
                {
                    bool custom = reader.ReadBoolean();
                    if (custom)
                    {
                        float density          = reader.ReadSingle();
                        float friction         = reader.ReadSingle();
                        float elasticity       = reader.ReadSingle();
                        float frictionWeight   = reader.ReadSingle();
                        float elasticityWeight = reader.ReadSingle();
                        props[i].Value = new float[5] {
                            density, friction, elasticity, frictionWeight, elasticityWeight
                        };
                    }
                }
            }
            else if (Format == BinaryPropertyFormat.Color3uint8)
            {
                byte[] r = reader.ReadBytes(instCount);
                byte[] g = reader.ReadBytes(instCount);
                byte[] b = reader.ReadBytes(instCount);

                for (int i = 0; i < instCount; i++)
                {
                    props[i].Value = new byte[3] {
                        r[i], g[i], b[i]
                    }
                }
                ;
            }
            else if (Format == BinaryPropertyFormat.Int64)
            {
                for (int i = 0; i < instCount; i++)
                {
                    byte[] buffer = reader.ReadBytes(8);

                    long v0 = buffer[i];
                    long v1 = buffer[instCount + i];
                    long v2 = buffer[instCount * 2 + i];
                    long v3 = buffer[instCount * 3 + i];
                    long v4 = buffer[instCount * 4 + i];
                    long v5 = buffer[instCount * 5 + i];
                    long v6 = buffer[instCount * 6 + i];
                    long v7 = buffer[instCount * 7 + i];

                    long result = (v0 << 56) | (v1 << 48) | (v2 << 40) | (v3 << 32) | (v4 << 24) | (v5 << 16) | (v6 << 8) | v7;
                    props[i].Value = (long)((ulong)result >> 1) ^ (-(result & 1));
                }
            }
            else
            {
                Console.WriteLine("Unhandled Format {0}!", Format);
            }
        }