Roblox Attributes Binary Format
This document describes the Attribute binary format. In this format there is no field for Version, so it is assumed that any future changes will be additions to the existing format or a new format entirely.
Contents
Document Conventions
This document assumes a basic understanding of Rust’s convention for numeric types. For example:
u32
is an unsigned 32-bit integerf32
is a 32-bit floating point
All numeric types are little endian and signed integers are stored using two’s complement. All floats are stored according to the IEEE-754 standard.
Unless otherwise noted, all structs in this document are assumed to be stored with their components in the sequence listed without any modification. That is, if a struct is listed as being composed of an i32
and an f32
, it can be assumed that it is stored as an i32
followed by an f32
.
File Structure
Unlike the normal binary format, the attribute format is not chunk based. Instead, it follows a basic name-type-value sequence.
The exception to this is the beginning of the blob, which indicates how many attributes are stored in the blob.
The first 4 bytes of the blob are a u32
which indicates how many attributes there are in the blob (the Length
). Following that, there are Length
attributes in the layout:
Field Name | Format | Value |
---|---|---|
Name | String | The name of this attribute |
Type | u8 |
The data type of this attribute |
Value | Variant | A value whose type and layout is determined by Type |
Data Types
For every data type that attributes can be, there’s a corresponding value of Type
that’s used to indicate an attribute is of that type. Despite similiarities to the binary file format, these are not transferable between the two (e.g. in the binary format, String is 0x01
but here it is 0x02
). The following are attribute types supported by Roblox Studio.
String
Type ID 0x02
The String
type is stored as a length-prefixed sequence of bytes. The length is stored as a u32
. Strings can contain binary data, and should be considered to be an array of u8
s.
Field Name | Format | Value |
---|---|---|
Length | u32 |
The length of the string |
Data | Array(Bytes) | The actual bytes that make up the string |
Bool
Type ID 0x03
The Bool
type is stored as a single byte. If the byte is 0x00
, the bool is false
. If it is 0x01
, it is true.
It is worth noting that Roblox Studio will interpret any non-zero value as true
.
Int32
Type ID 0x04
The Int32
type is stored as a little-endian 32-bit integer.
Float32
Type ID 0x05
The Float32
type is stored as a single-precision float, also known as an f32
or single
, or sometimes even simply float
.
This type is accepted by Roblox Studio, though will almost never be generated by it. In some cases the Roblox Studio Properties widget may cause this type to appear.
Float64
Type ID 0x06
The Float64
type is stored as a double-precision float, also known as an f64
or double
.
UDim
Type ID 0x09
The UDim
type is stored as a struct composed of a f32
and an i32
:
Field Name | Format | Value |
---|---|---|
Scale | f32 |
The Scale component of the UDim |
Offset | i32 |
The Offset component of the UDim |
As an example, the UDim {123, 456}
would look like this: 00 00 f6 42 c8 01 00 00
.
UDim2
Type ID 0x0A
The UDim2
type is stored as a struct composed of two UDim
s, one for each axis:
Field Name | Format | Value |
---|---|---|
X Scale | UDim |
The X component of the UDim2 |
X Offset | UDim |
The Y component of the UDim2 |
An encoded UDim2 with the value {1, 2, 3, 4}
would look like this: 00 00 80 3f 02 00 00 00 00 00 40 40 04 00 00 00
.
BrickColor
Type ID 0x0E
The BrickColor
type is stored as a single u32
indicating the Number
property of the BrickColor.
Color3
Type ID 0x0F
The Color3
type is stored as a set of three f32
s:
Field Name | Format | Value |
---|---|---|
R | f32 |
The R component of the Color3 |
G | f32 |
The G component of the Color3 |
B | f32 |
The B component of the Color3 |
A Color3 with the RGB value 0, 102, 255
would look like this: 00 00 00 00 cd cc cc 3e 00 00 80 3f
.
Vector2
Type ID 0x10
The Vector2
type is a struct composed of two f32
s:
Field Name | Format | Value |
---|---|---|
X | f32 |
The X component of the Vector2 |
Y | f32 |
The Y component of the Vector2 |
A Vector2 with the value 10, 20
looks like this: 00 00 20 41 00 00 a0 41
.
Vector3
Type ID 0x11
The Vector3
type is a struct composed of three f32
s:
Field Name | Format | Value |
---|---|---|
X | f32 |
The X component of the Vector2 |
Y | f32 |
The Y component of the Vector2 |
Z | f32 |
The Z component of the Vector2 |
A Vector3 with the value 10, 20, 30
looks like this: 00 00 20 41 00 00 a0 41 00 00 f0 41
.
CFrame
Type ID 0x14
The CFrame
type is composed of a Vector3
, a 1-byte rotation ID, and an optional rotation matrix:
Field Name | Format | Value |
---|---|---|
Position | Vector3 |
The positional component of the CFrame . |
Rotation ID | u8 |
An identifier representing axis-alignment of the rotation, determining whether the rotation matrix is present (see Rotation matrix ). If the rotation is axis-aligned, this field is one of the values from the table below; otherwise, it is 00 . |
Rotation matrix | Optional<Matrix3> |
The rotational component of the CFrame , stored as a sequence of nine f32 s. If Rotation ID is 00 , this field is the XVector, the YVector, and ZVector, in that order; otherwise, it is absent. |
A rotation is considered “axis-aligned” if it’s in increments of 90 degrees around one or more axes. The following table shows the mapping between Rotation IDs and rotations (rotations are Euler angles in degrees, applied in the order Y -> X -> Z
):
ID | Rotation | ID | Rotation |
---|---|---|---|
02 |
(0, 0, 0) | 14 |
(0, 180, 0) |
03 |
(90, 0, 0) | 15 |
(-90, -180, 0) |
05 |
(0, 180, 180) | 17 |
(0, 0, 180) |
06 |
(-90, 0, 0) | 18 |
(90, 180, 0) |
07 |
(0, 180, 90) | 19 |
(0, 0, -90) |
09 |
(0, 90, 90) | 1b |
(0, -90, -90) |
0a |
(0, 0, 90) | 1c |
(0, -180, -90) |
0c |
(0, -90, 90) | 1e |
(0, 90, -90) |
0d |
(-90, -90, 0) | 1f |
(90, 90, 0) |
0e |
(0, -90, 0) | 20 |
(0, 90, 0) |
10 |
(90, -90, 0) | 22 |
(-90, 90, 0) |
11 |
(0, 90, 180) | 23 |
(0, -90, 180) |
A CFrame
with the value CFrame.new(1, 2, 3) * CFrame.Angles(0, 45, 0)
looks like this when serialized: 00 00 80 3f 00 00 00 40 00 00 40 40 00 f3 04 35 3f 00 00 00 00 f3 04 35 3f 00 00 00 00 00 00 80 3f 00 00 00 00 f3 04 35 bf 00 00 00 00 f3 04 35 3f
.
Demonstrating the axis-aligned rotation matrix case, a CFrame
with the value CFrame.new(1, 2, 3)
looks like this: 00 00 80 3f 00 00 00 40 00 00 40 40 02
.
EnumItem
Type ID 0x15
The EnumItem
type is composed of two parts:
Field Name | Format | Value |
---|---|---|
Enum Name | String |
The name of the Enum of this EnumItem |
Value | u32 |
The Value field of the EnumItem |
NumberSequence
Type ID 0x17
The NumberSequence
type is stored as a struct composed of a u32
and an array of NumberSequenceKeypoint
s:
Field Name | Format | Value |
---|---|---|
Keypoint Count | u32 |
The number of keypoints in the sequence |
Keypoints | Array(NumberSequenceKeypoint) | The keypoints that make up the sequence |
A NumberSequenceKeypoint
is stored as a struct composed of three f32
s:
Field Name | Format | Value |
---|---|---|
Envelope | f32 | The envelope for the keypoint |
Time | f32 | The time for the keypoint |
Value | f32 | The value of the keypoint |
A NumberSequence with the keypoints 0, 0, 0
, 0.5, 1, 0
, and 1, 1, 0.5
would look like this: 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3f 00 00 80 3f 00 00 00 3f 00 00 80 3f 00 00 80 3f
ColorSequence
Type ID 0x19
The ColorSequence
type is stored as a struct composed of a u32
and an array of ColorSequenceKeypoint
s:
Field Name | Format | Value |
---|---|---|
Keypoint Count | u32 |
The number of keypoints in the sequence |
Keypoints | Array(ColorSequenceKeypoint) | The keypoints that make up the sequence |
A ColorSequenceKeypoint
is stored as a struct composed of three f32
s:
Field Name | Format | Value |
---|---|---|
Envelope* | f32 | The envelope for the keypoint |
Time | f32 | The time for the keypoint |
Value | Color3 |
The value of the keypoint |
*ColorSequenceKeypoint has a field for Envelope despite not having one; it will always be 00 00 00 00
A ColorSequence with the keypoints 0, RGB(255, 0, 0)
, 0.5, RGB(0, 255, 0)
, and 1, RGB(0, 0, 255)
would look like this: 03 00 00 00 00 00 00 00 00 00 00 00 00 00 80 3f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3f 00 00 00 00 00 00 80 3f 00 00 00 00 00 00 00 00 00 00 80 3f 00 00 00 00 00 00 00 00 00 00 80 3f
NumberRange
Type ID 0x1B
The NumberRange
type is a struct composed of two f32
s:
Field Name | Format | Value |
---|---|---|
Min | f32 |
The Min component of the NumberRange |
Max | f32 |
The Max component of the NumberRange |
A NumberRange with the value 10, 20
would look like this: 00 00 a0 40 00 00 20 41
.
Rect
Type ID 0x1C
The Rect
type is a struct composed of two Vector2
s:
Field Name | Format | Value |
---|---|---|
Min | Vector2 |
The Min component of the Rect |
Max | Vector2 |
The Max component of the Rect |
A Rect with the value 10, 20, 30, 40
would look like this: 00 00 20 41 00 00 a0 41 00 00 f0 41 00 00 20 42
.
Font
Type ID 0x21
The Font
type is a struct composed of a u16
, u8
and two String
s
Field Name | Format | Value |
---|---|---|
Weight | u16 |
The weight of the font |
Style | u8 |
The style of the font |
Family | String |
The font family content URI |
CachedFaceId | String |
The cached content URI of the TTF file |
The Weight
and Style
values refer to the FontWeight
and FontStyle
enums respectively. They are stored as unsigned little-endian
The CachedFaceId
field will always be present, but may be an empty string.
A regular Source Sans Pro
font will be stored as 90 01 00 2C 00 00 00 72 62 78 61 73 73 65 74 3A 2F 2F 66 6F 6E 74 73 2F 66 61 6D 69 6C 69 65 73 2F 53 6F 75 72 63 65 53 61 6E 73 50 72 6F 2E 6A 73 6F 6E 2A 00 00 00 72 62 78 61 73 73 65 74 3A 2F 2F 66 6F 6E 74 73 2F 53 6F 75 72 63 65 53 61 6E 73 50 72 6F 2D 52 65 67 75 6C 61 72 2E 74 74 66