Read and write Brickadia save files (.brs)
Currently supports save versions <= 10
Warning: Unreal Engine uses numbers potentially larger than Javascript can handle.
npm install brs-js
Node:
const brs = require('brs-js');
ES6:
import brs from 'brs-js';
Web:
Head: <script src="https://cdn.jsdelivr.net/npm/brs-js/dist/dist.js"></script>
Script: window.BRS
Examples are available in the examples/
directory. All .js
examples are for node, .html
are for web.
The Save Object is the input and output of this program. It represents the decoded/decompressed contents of the save.
Strings can be UCS-2 or UTF-8. UUIDs follow the spec. The save_time
field is 8 bytes (Little Endian) instead of a long.
Unsigned ints, while unlikely, may overflow.
{
version: short,
map: string,
author: {id: uuid, name: string},
host: {id: uuid, name: string} // (v8+ only)
description: string,
save_time: UTC as 8 bytes,
brick_count: int,
mods: string array,
brick_assets: [string],
// --- See bottom of page for known bricks ---
colors: [[byte, byte, byte, byte], ... ],
physical_materials: [string],
materials: [string],
// --- Known available materials
// BMC_Ghost
// BMC_Ghost_Fail
// BMC_Plastic
// BMC_Glow
// BMC_Metallic
// BMC_Hologram
brick_owners: [{
id: uuid,
name: string,
bricks: int // (v8+ only)
}, ... ],
components: {
[componentName]: {
version: int,
brick_indices: [int, ...],
properties: {[name]: [value], ...},
},
...
},
bricks: [{
asset_name_index: int,
size: [uint, uint, uint],
// must be [0, 0, 0] for all B_ prefixed brick_assets
// must NOT be [0, 0, 0] for all PB_ prefixed brick_assets
// 1x1 brick has size [5, 5, 6]
// 1x1F plate has size [5, 5, 2]
position: [int, int, int],
direction: 0-5,
// --- Directions (facing axis) ---
// 0: X Positive
// 1: X Negative
// 2: Y Positive
// 3: Y Negative
// 4: Z Positive
// 5: Z Negative
rotation: 0-3,
// --- Rotations (along the facing axis) ---
// 0: 0 Deg
// 1: 90 Deg
// 2: 180 Deg
// 3: 270 Deg
collision: bool,
visibility: bool,
material_index: uint,
physical_index: uint,
material_intensity: 0-10,
color: uint or [byte, byte, byte, byte] or (v9) -> [byte, byte, byte],
owner_index: uint,
components: {
[componentName]: {
[propName]: [propVal],
...
},
...
},
}, ... ],
}
Fields: (optional fields during brs.write(save)
will be set to default)
field | type | default | optional | description |
---|---|---|---|---|
version | short | Latest Save Version | auto | Save file version |
game_version | int | Game Version | ☑ | Saving version of the game |
map | string | 'Unknown' | ☑ | Map where the save was generated |
author.id | uuid | 00000000-0000-0000-0000-000000000000 | ☑ | Save author UUID |
author.name | string | 'Unknown' | ☑ | Save author name |
description | string | '' (Empty String) | ☑ | Save author name |
save_time | array | [0, 0, 0, 0, 0, 0, 0, 0] | ☑ | UTC in bytes of creation time |
brick_count | int | Number of bricks in bricks |
auto | Number of bricks in save |
mods | array | [] | ☑ | In game mods required for load |
brick_assets | array | ['PB_DefaultBrick'] | ☑ | List of brick assets |
colors | array | [] | ☑ | List of colorset colors |
materials | array | ['BMC_Plastic'] | ☑ | List of used materials |
physical_materials | array | [] | ☑ | List of physical materials |
brick_owners | array | [{}] | ☑ | Brick owner list |
brick_owners[].id | uuid | 00000000-0000-0000-0000-000000000000 | ☑ | Brick owner list user uuid |
brick_owners[].name | string | 'Unknown' | ☑ | Brick owner list user name |
preview | array | undefined | ☑ | 1280x720 png screenshot data |
bricks | array | List of bricks in the save | ||
bricks[].asset_name_index | int | 0 (0 indexed) | ☑ | Index of asset in brick_assets |
bricks[].size | array | Brick size | ||
bricks[].position | array | Brick position | ||
bricks[].direction | int | 4 (Positive Z, Upward) | ☑ | Brick axis / facing direction |
bricks[].rotation | int | 0 (0 degrees) | ☑ | Brick rotation on axis |
bricks[].collision | bool | true | ☑ | Brick has collision with players |
bricks[].visibility | bool | true | ☑ | Brick renders to players |
bricks[].material_index | int | 0 (0 indexed) | ☑ | Index of material in materials |
bricks[].material_intensity | int | 0 (0 indexed) | ☑ | Material intensity (0-10) |
bricks[].physical_index | int | 0 (0 indexed) | ☑ | Index of physical material |
bricks[].color (colorset) | int | 0 | ☑ | Index of color in colors |
bricks[].color (rgba) | array | [255, 255, 255, 255] | ☑ | Color in RGBA Bytes |
bricks[].color (rgb) | array | [255, 255, 255] (v9+) | ☑ | Color in RGBA Bytes |
bricks[].owner_index | int | 1 (1 indexed) | ☑ | Index of owner in brick_owners |
bricks[].components | object | {} | ☑ | Components on this brick |
components | object | {} | ☑ | List of components in the save |
components[].version | int | Game version for this component | ||
components[].brick_indices | array | Indices of assigned bricks | ||
components[].properties | object | Map of properties names and types |
Returns: Save Object
In node, the buffer can be obtained from fs.readFile
without an encoding specified. In web, the buffer can be obtained via File.arrayBuffer()
. Be sure to resolve promises where necessary.
parameter | type | description |
---|---|---|
buffer |
Uint8Array / Buffer | Input bytes to be parsed |
options |
Object | Options for the parser, see table below |
name | type | description | default |
---|---|---|---|
bricks |
boolean | Whether to read bricks | true |
preview |
boolean | Whether to copy previews | false |
Returns: Uint8Array
In node, the buffer can be saved with from fs.writeFile(fileName, buffer)
. In web, the buffer can be made into a new Blob([buffer])
, and can be downloaded with an <a download>
with href
as URL.createObjectURL(blob)
.
parameter | type | description |
---|---|---|
saveObj |
Save Object | Save Object to be turned into a buffer |
Notes:
- Size must be [0, 0, 0] for bricks using non-procedural brick assets
- Size must NOT be [0, 0, 0] for bricks using procedural brick assets
- 1x1 brick has size [5, 5, 6] and 'PB_DefaultBrick' brick asset
- 1x1F plate has size [5, 5, 2] and 'PB_DefaultBrick' brick asset
name | procedural |
---|---|
PB_DefaultBrick | ☑ |
PB_DefaultRamp | ☑ |
PB_DefaultRampCrest | ☑ |
PB_DefaultRampCrestCorner | ☑ |
PB_DefaultRampCrestEnd | ☑ |
PB_DefaultRampInnerCornerInverted | ☑ |
PB_DefaultRampInverted | ☑ |
PB_DefaultSideWedge | ☑ |
PB_DefaultSideWedgeTile | ☑ |
PB_DefaultTile | ☑ |
PB_DefaultWedge | ☑ |
PB_DefaultMicroBrick | ☑ |
PB_DefaultMicroWedge | ☑ |
B_1x1_Brick_Side | |
B_1x1_Brick_Side_Lip | |
B_1x1_Cone | |
B_1x1_Round | |
B_1x1F_Octo | |
B_1x1F_Round | |
B_1x2_Overhang | |
B_1x2f_Plate_Center | |
B_1x2f_Plate_Center_Inv | |
B_1x4_Brick_Side | |
B_1x_Octo | |
B_1x_Octo_90Deg | |
B_1x_Octo_90Deg_Inv | |
B_1x_Octo_T | |
B_1x_Octo_T_Inv | |
B_2x1_Slipper | |
B_2x2_Cone | |
B_2x2_Corner | |
B_2x2_Overhang | |
B_2x2_Round | |
B_2x2_Slipper | |
B_2x2F_Octo | |
B_2x2F_Octo_Converter | |
B_2x2F_Octo_Converter_Inv | |
B_2x2f_Plate_Center | |
B_2x2f_Plate_Center_Inv | |
B_2x2F_Round | |
B_2x4_Door_Frame | |
B_2x_Cube_Side | |
B_2x_Octo | |
B_2x_Octo_90Deg | |
B_2x_Octo_90Deg_Inv | |
B_2x_Octo_Cone | |
B_2x_Octo_T | |
B_2x_Octo_T_Inv | |
B_4x4_Round | |
B_8x8_Lattice_Plate | |
B_Bishop | |
B_Bone | |
B_BoneStraight | |
B_Branch | |
B_Bush | |
B_Cauldron | |
B_Chalice | |
B_CheckPoint | |
B_Coffin | |
B_Coffin_Lid | |
B_Fern | |
B_Flame | |
B_Flower | |
B_Gravestone | |
B_GoalPoint | |
B_Handle | |
B_Hedge_1x1 | |
B_Hedge_1x1_Corner | |
B_Hedge_1x2 | |
B_Hedge_1x4 | |
B_Inverted_Cone | |
B_Jar | |
B_King | |
B_Knight | |
B_Ladder | |
B_Pawn | |
B_Picket_Fence | |
B_Pine_Tree | |
B_Pumpkin | |
B_Pumpkin_Carved | |
B_Queen | |
B_Rook | |
B_Sausage | |
B_Small_Flower | |
B_SpawnPoint | |
B_Swirl_Plate | |
B_Turkey_Body | |
B_Turkey_Leg |
NPM Scripts (npm run <cmd>
)
name | description |
---|---|
build | Build library in development mode |
watch | Auto-build library in development mode when files change |
dist | Build library in production mode |
test | Run tests |