public void Read_AdditionalData() { var data = 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, 0x02, 0x06, 0x01, 0x02, 0x03 }; var parsed = TypeHeader.Deserialize(data); Assert.AreEqual("Part", parsed.Name); Assert.AreEqual(0x13, parsed.TypeId); Assert.AreEqual(3, parsed.InstanceCount); Assert.AreEqual(new[] { 2, 3, 6 }, parsed.Referents); Assert.AreEqual(new byte[] { 0x1, 0x2, 0x3 }, parsed.AdditionalData); }
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()); } }
internal static void ReadRaw(EndianAwareBinaryReader reader, out int typeCount, out int objectCount, out TypeHeader[] typeHeaders, out Dictionary <int, List <PropertyBlock> > propertyData, out Tuple <int, int>[] childParentPairs) { // Check file signature var signatureBytes = reader.ReadBytes(Signatures.Signature.Length); if (!signatureBytes.SequenceEqual(Signatures.Signature)) { throw new InvalidRobloxFileException("The file signature does not match."); } typeCount = reader.ReadInt32(); objectCount = reader.ReadInt32(); reader.ReadInt32(); // Reserved reader.ReadInt32(); // Reserved // Deserialize type headers typeHeaders = new TypeHeader[typeCount]; for (var i = 0; i < typeCount; i++) { var typeHeaderSignature = reader.ReadBytes(Signatures.TypeHeaderSignature.Length); if (!typeHeaderSignature.SequenceEqual(Signatures.TypeHeaderSignature)) { throw new InvalidRobloxFileException("Invalid type header signature."); } var decompressedBytes = RobloxLZ4.ReadBlock(reader.Stream); var typeHeader = TypeHeader.Deserialize(decompressedBytes); typeHeaders[i] = typeHeader; } // Read property data propertyData = new Dictionary <int, List <PropertyBlock> >(); // Key is type id byte[] lastPropSignature; while (true) { lastPropSignature = reader.ReadBytes(Signatures.PropBlockSignature.Length); if (!lastPropSignature.SequenceEqual(Signatures.PropBlockSignature)) { break; } var decompressedBytes = RobloxLZ4.ReadBlock(reader.Stream); var propertyBlock = PropertyBlock.Deserialize(decompressedBytes, typeHeaders); if (propertyBlock == null) { continue; } if (!propertyData.ContainsKey(propertyBlock.TypeId)) { propertyData.Add(propertyBlock.TypeId, new List <PropertyBlock>()); } propertyData[propertyBlock.TypeId].Add(propertyBlock); } if (!lastPropSignature.SequenceEqual(Signatures.ParentDataSignature)) { throw new InvalidRobloxFileException("Missing parent data section."); } var parentData = RobloxLZ4.ReadBlock(reader.Stream); childParentPairs = Util.ReadParentData(parentData); var endSignature = reader.ReadBytes(Signatures.EndSignature.Length); if (!endSignature.SequenceEqual(Signatures.EndSignature)) { throw new InvalidRobloxFileException("End signature is missing or invalid."); } }