Esempio n. 1
0
        public void Write_AdditionalData()
        {
            var typeHeader    = new TypeHeader("Part", 0x13, new[] { 0x2, 0x1, 0x3 }, new byte[] { 0x1, 0x1, 0x1 });
            var expectedBytes = new byte[] { 0x13, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x50, 0x61, 0x72, 0x74, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x04, 0x01, 0x01, 0x01 };

            var bytes = typeHeader.Serialize();

            Assert.AreEqual(expectedBytes, bytes);
        }
Esempio n. 2
0
        public void Serialziation()
        {
            var rand = new Random(20121230);

            for (int i = 0; i < 1000; i += 1)
            {
                int kind    = rand.Next(0, 3);
                int ordinal = rand.Next(1, 32767);
                int length  = 0;

                if (kind == 3)
                {
                    length = rand.Next(8, 2147483647);
                }

                var head1 = new TypeHeader
                {
                    Kind    = (TypeKind)kind,
                    Size    = length,
                    Ordinal = ordinal,
                };
                var head2 = new TypeHeader {
                };

                Assert.Equal((TypeKind)kind, head1.Kind);
                Assert.Equal(length, head1.Size);
                Assert.Equal(ordinal, head1.Ordinal);

                Assert.NotEqual(head1, head2);

                Assert.Equal((TypeKind)0, head2.Kind);
                Assert.Equal(0, head2.Size);
                Assert.Equal(0, head2.Ordinal);

                Guid buf = Guid.Empty;

                int size = head1.Serialize((byte *)&buf, sizeof(Guid));
                int read = head2.Deserialize((byte *)&buf, sizeof(Guid));

                Assert.Equal(size, read);
                Assert.Equal(head1, head2, new TypeHeaderComparer());
            }
        }
Esempio n. 3
0
        public void Save(Stream stream)
        {
            var writer     = new EndianAwareBinaryWriter(stream);
            var serializer = new RobloxSerializer(this);

            ReferentProvider.ClearCache(); // Clearing existing referent cache guarantees that referents won't be fragmented
            var instances  = GetChildFirstInstanceEnumerator().ToArray();
            var typeGroups = instances.GroupBy(n => n.ClassName).OrderBy(n => n.Key).ToDictionary(n => n.Key, n => n.ToArray());

            var typeCount   = typeGroups.Count;
            var objectCount = typeGroups.Aggregate(0, (acc, pair) => acc + pair.Value.Length);

            writer.WriteBytes(Signatures.Signature); // File signature
            writer.WriteInt32(typeCount);            // Generic header values
            writer.WriteInt32(objectCount);
            writer.WriteInt32(0);                    // Reserved
            writer.WriteInt32(0);                    // Reserved

            // Write type headers
            var typeHeaders = new TypeHeader[typeCount];
            var nextTypeId  = 0;

            foreach (var typeGroup in typeGroups)
            {
                var typeHeader = new TypeHeader(typeGroup.Key, nextTypeId, typeGroup.Value.Select(n => ReferentProvider.GetReferent(n)).ToArray());
                if (IsSingleton(typeGroup))
                {
                    typeHeader.AdditionalData = new byte[typeHeader.InstanceCount];
                    for (var i = 0; i < typeHeader.InstanceCount; i++)
                    {
                        typeHeader.AdditionalData[i] = 0x1;
                    }
                }
                typeHeaders[nextTypeId] = typeHeader;
                var bytes = typeHeader.Serialize();
                writer.WriteBytes(Signatures.TypeHeaderSignature);
                RobloxLZ4.WriteBlock(stream, bytes);
                nextTypeId++;
            }

            // Write property data
            foreach (var typeGroup in typeGroups)
            {
                var typeHeader     = typeHeaders.First(n => n.Name == typeGroup.Key);
                var instanceTypes  = serializer.GetUniqueProperties(typeGroup.Value);
                var propertyBlocks = instanceTypes.Select(propertyDescriptor => serializer.FillPropertyBlock(propertyDescriptor.Name, propertyDescriptor.Type, typeHeader.TypeId, typeGroup.Value, ReferentProvider)).ToList();
                foreach (var propertyBlock in propertyBlocks)
                {
                    var bytes = propertyBlock.Serialize();
                    writer.WriteBytes(Signatures.PropBlockSignature);
                    RobloxLZ4.WriteBlock(stream, bytes);
                }
            }

            // Build parent child referent arrays
            var parentData = Util.BuildParentData(instances, ReferentProvider);

            var parentDataBytes = Util.SerializeParentData(parentData);

            writer.WriteBytes(Signatures.ParentDataSignature);
            RobloxLZ4.WriteBlock(stream, parentDataBytes);

            // Write ending signature
            writer.WriteBytes(Signatures.EndSignature);
            writer.WriteBytes(Signatures.FileEndSignature);
        }