brs-js 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,169 +0,0 @@
1
- export interface BRSBytes extends Uint8Array {
2
- brsOffset: number;
3
- }
4
- declare type Modify<T, R> = Omit<T, keyof R> & R;
5
- export declare type Bytes = Uint8Array | BRSBytes;
6
- export declare type Uuid = string;
7
- export declare type UnrealClass = string;
8
- export declare type UnrealObject = string;
9
- export declare type UnrealBoolean = boolean;
10
- export declare type UnrealFloat = number;
11
- export declare type UnrealColor = [number, number, number, number];
12
- export declare type UnrealByte = number;
13
- export declare type UnrealRotator = [number, number, number];
14
- export declare type UnrealType = UnrealClass | UnrealObject | UnrealBoolean | UnrealFloat | UnrealColor | UnrealByte | UnrealRotator;
15
- export interface User {
16
- id: Uuid;
17
- name: string;
18
- }
19
- export interface Owner extends User {
20
- bricks: number;
21
- }
22
- export declare enum Direction {
23
- XPositive = 0,
24
- XNegative = 1,
25
- YPositive = 2,
26
- YNegative = 3,
27
- ZPositive = 4,
28
- ZNegative = 5
29
- }
30
- export declare enum Rotation {
31
- Deg0 = 0,
32
- Deg90 = 1,
33
- Deg180 = 2,
34
- Deg270 = 3
35
- }
36
- export declare type ColorRgb = [number, number, number];
37
- export interface Collision {
38
- player: boolean;
39
- weapon: boolean;
40
- interaction: boolean;
41
- tool: boolean;
42
- }
43
- export interface AppliedComponent {
44
- [property: string]: UnrealType;
45
- }
46
- export interface DefinedComponents {
47
- [component_name: string]: {
48
- version: number;
49
- brick_indices: number[];
50
- properties: {
51
- [property: string]: string;
52
- };
53
- };
54
- }
55
- export interface Components {
56
- [component_name: string]: AppliedComponent;
57
- }
58
- export declare type Vector = [number, number, number];
59
- export interface BrickV1 {
60
- asset_name_index: number;
61
- size: Vector;
62
- position: Vector;
63
- direction: Direction;
64
- rotation: Rotation;
65
- collision: boolean;
66
- visibility: boolean;
67
- color: UnrealColor | number;
68
- }
69
- export interface BrickV2 extends BrickV1 {
70
- material_index: number;
71
- }
72
- export interface BrickV3 extends BrickV2 {
73
- owner_index: number;
74
- }
75
- export interface BrickV8 extends BrickV3 {
76
- components: Components;
77
- }
78
- export declare type BrickV9 = Modify<BrickV8, {
79
- physical_index: number;
80
- material_intensity: number;
81
- color: ColorRgb | number;
82
- }>;
83
- export declare type BrickV10 = Modify<BrickV9, {
84
- collision: Collision;
85
- }>;
86
- export interface BrsV1 {
87
- version: 1;
88
- map: string;
89
- author: User;
90
- description: string;
91
- brick_count: number;
92
- mods: string[];
93
- brick_assets: string[];
94
- colors: UnrealColor[];
95
- bricks: BrickV1[];
96
- }
97
- export declare type BrsV2 = Modify<BrsV1, {
98
- version: 2;
99
- materials: string[];
100
- bricks: BrickV2[];
101
- }>;
102
- export declare type BrsV3 = Modify<BrsV2, {
103
- version: 3;
104
- brick_owners: User[];
105
- bricks: BrickV3[];
106
- }>;
107
- export declare type BrsV4 = Modify<BrsV3, {
108
- version: 4;
109
- save_time: Uint8Array;
110
- }>;
111
- export declare type BrsV8 = Modify<BrsV4, {
112
- version: 8;
113
- host: User;
114
- brick_owners: Owner[];
115
- preview?: Bytes;
116
- game_version: number;
117
- bricks: BrickV8[];
118
- components: DefinedComponents;
119
- }>;
120
- export declare type BrsV9 = Modify<BrsV8, {
121
- version: 9;
122
- physical_materials: string[];
123
- bricks: BrickV9[];
124
- }>;
125
- export declare type BrsV10 = Modify<BrsV9, {
126
- version: 10;
127
- bricks: BrickV10[];
128
- }>;
129
- export declare type ReadSaveObject = BrsV1 | BrsV2 | BrsV3 | BrsV4 | BrsV8 | BrsV9 | BrsV10;
130
- export interface Brick {
131
- asset_name_index?: number;
132
- size: Vector;
133
- position: Vector;
134
- direction?: Direction;
135
- rotation?: Rotation;
136
- collision?: boolean | Partial<Collision>;
137
- visibility?: boolean;
138
- material_index?: number;
139
- physical_index?: number;
140
- material_intensity?: number;
141
- color?: ColorRgb | number;
142
- owner_index?: number;
143
- components?: Components;
144
- }
145
- export interface WriteSaveObject {
146
- game_version?: number;
147
- map?: string;
148
- description?: string;
149
- author?: Partial<User>;
150
- host?: Partial<User>;
151
- mods?: string[];
152
- brick_assets?: string[];
153
- colors?: UnrealColor[];
154
- materials?: string[];
155
- brick_owners?: Partial<Owner>[];
156
- physical_materials?: string[];
157
- preview?: Bytes;
158
- bricks: Brick[];
159
- save_time?: ArrayLike<number>;
160
- components?: DefinedComponents;
161
- }
162
- export interface ReadOptions {
163
- bricks?: boolean;
164
- preview?: boolean;
165
- }
166
- export interface WriteOptions {
167
- compress?: boolean;
168
- }
169
- export {};
@@ -1,86 +0,0 @@
1
- import { BRSBytes, Bytes, UnrealFloat, UnrealType, Uuid } from './types';
2
- export declare const bgra: ([b, g, r, a]: number[]) => [
3
- number,
4
- number,
5
- number,
6
- number
7
- ];
8
- export declare function isEqual<T>(arrA: Array<T>, arrB: Array<T>): boolean;
9
- export declare function subarray(data: Bytes, len: number, isCopy?: boolean): BRSBytes;
10
- export declare function chunk(arr: Bytes, size: number): BRSBytes[];
11
- declare function read_u16(data: Bytes, littleEndian?: boolean): number;
12
- declare function write_u16(num: number, littleEndian?: boolean): Uint8Array;
13
- declare function read_i32(data: Bytes, littleEndian?: boolean): number;
14
- declare function write_i32(num: number, littleEndian?: boolean): Uint8Array;
15
- declare function read_compressed(data: Bytes): Bytes;
16
- declare function write_uncompressed(...args: Uint8Array[]): Uint8Array;
17
- declare function write_compressed(...args: Uint8Array[]): Uint8Array;
18
- declare function read_string(data: Bytes): string;
19
- declare function write_string(str: string): Uint8Array;
20
- declare function read_uuid(data: Bytes): string;
21
- declare function write_uuid(uuid: Uuid): Uint8Array;
22
- declare function read_array<T>(data: Bytes, fn: (_: Bytes) => T): T[];
23
- declare function read_each(data: Bytes, fn: (_: Bytes) => void): void;
24
- declare function write_array<T>(arr: T[], fn: (_: T) => Uint8Array): Uint8Array;
25
- declare class BitReader {
26
- buffer: Uint8Array;
27
- pos: number;
28
- constructor(data: Uint8Array);
29
- empty(): boolean;
30
- bit(): boolean;
31
- align(): void;
32
- int(max: number): number;
33
- uint_packed(): number;
34
- int_packed(): number;
35
- bits(num: number): number[];
36
- bytes(num: number): Uint8Array;
37
- bytesArr(num: number): number[];
38
- array<T>(fn: (_: BitReader) => T): T[];
39
- each(fn: (data: BitReader) => void): void;
40
- string(): string;
41
- float(): number;
42
- unreal(type: string): UnrealType;
43
- }
44
- declare class BitWriter {
45
- buffer: number[];
46
- cur: number;
47
- bitNum: number;
48
- bit(val: boolean): void;
49
- bits(src: number[] | Uint8Array, len: number): void;
50
- bytes(src: number[] | Uint8Array): void;
51
- align(): void;
52
- int(value: number, max: number): void;
53
- uint_packed(value: number): void;
54
- int_packed(value: number): void;
55
- finish(): Uint8Array;
56
- finishSection(): Uint8Array;
57
- string(str: string): void;
58
- float(num: UnrealFloat): void;
59
- self(fn: (this: BitWriter) => void): this;
60
- array<T>(arr: T[], fn: (this: BitWriter, item: T, index: number) => void): this;
61
- each<T>(arr: T[], fn: (this: BitWriter, item: T, index: number) => void): this;
62
- unreal(type: string, value: UnrealType): void;
63
- }
64
- export declare function concat(...arrays: Uint8Array[]): Uint8Array;
65
- export declare const read: {
66
- bytes: typeof subarray;
67
- u16: typeof read_u16;
68
- i32: typeof read_i32;
69
- compressed: typeof read_compressed;
70
- string: typeof read_string;
71
- uuid: typeof read_uuid;
72
- array: typeof read_array;
73
- each: typeof read_each;
74
- bits: (data: Bytes) => BitReader;
75
- };
76
- export declare const write: {
77
- u16: typeof write_u16;
78
- i32: typeof write_i32;
79
- compressed: typeof write_compressed;
80
- uncompressed: typeof write_uncompressed;
81
- string: typeof write_string;
82
- uuid: typeof write_uuid;
83
- array: typeof write_array;
84
- bits: () => BitWriter;
85
- };
86
- export {};
@@ -1,3 +0,0 @@
1
- import { Uuid } from './types';
2
- export declare function uuidStringify(arr: number[]): Uuid;
3
- export declare function uuidParse(uuid: Uuid): Uint8Array;
@@ -1,2 +0,0 @@
1
- import { WriteOptions, WriteSaveObject } from './types';
2
- export default function writeBrs(save: WriteSaveObject, options?: WriteOptions): Uint8Array;
package/src/constants.ts DELETED
@@ -1,6 +0,0 @@
1
- import { Uuid } from './types';
2
-
3
- export const MAGIC = new Uint8Array([66, 82, 83]); // BRS
4
- export const LATEST_VERSION = 10;
5
- export const MAX_INT = ~(1 << 31);
6
- export const DEFAULT_UUID: Uuid = '00000000-0000-0000-0000-000000000000';
package/src/index.ts DELETED
@@ -1,24 +0,0 @@
1
- import read from './read';
2
- import write from './write';
3
- import * as utils from './utils';
4
- import * as constants from './constants';
5
-
6
- // https://i.imgur.com/cv1fDWs.png
7
- const brs = { read, write, utils, constants };
8
- export { read, write, utils, constants };
9
- export default brs;
10
-
11
- declare global {
12
- interface Window {
13
- BRS: {
14
- read: typeof read;
15
- write: typeof write;
16
- utils: typeof utils;
17
- constants: typeof constants;
18
- };
19
- }
20
- }
21
-
22
- if (typeof window !== 'undefined') {
23
- window.BRS = brs;
24
- }
package/src/read.ts DELETED
@@ -1,57 +0,0 @@
1
- import { MAGIC } from './constants';
2
- import readBrsV1 from './read.v1';
3
- import readBrsV10 from './read.v10';
4
- import readBrsV2 from './read.v2';
5
- import readBrsV3 from './read.v3';
6
- import readBrsV4 from './read.v4';
7
- import readBrsV8 from './read.v8';
8
- import readBrsV9 from './read.v9';
9
- import { BRSBytes, ReadOptions, ReadSaveObject } from './types';
10
- import { read } from './utils';
11
-
12
- // Reads in a byte array to build a brs object
13
- export default function readBrs(
14
- rawBytes: Uint8Array,
15
- options: ReadOptions = {}
16
- ): ReadSaveObject {
17
- if (typeof options !== 'object') throw new Error('Invalid options');
18
-
19
- // default enable brick reading
20
- if (typeof options.bricks !== 'boolean') options.bricks = true;
21
-
22
- // default disable preview (a5 only)
23
- if (typeof options.preview !== 'boolean') options.preview = false;
24
-
25
- // Determine if the first 3 bytes are equal to the Brickadia save magic bytes
26
- if (
27
- rawBytes[0] !== MAGIC[0] ||
28
- rawBytes[1] !== MAGIC[1] ||
29
- rawBytes[2] !== MAGIC[2]
30
- ) {
31
- throw new Error('Invalid starting bytes');
32
- }
33
-
34
- const brsData = rawBytes as BRSBytes;
35
- brsData.brsOffset = 3;
36
-
37
- // Determine if the file version supported
38
- const version = read.u16(brsData);
39
- switch (version) {
40
- case 1:
41
- return readBrsV1(brsData, options);
42
- case 2:
43
- return readBrsV2(brsData, options);
44
- case 3:
45
- return readBrsV3(brsData, options);
46
- case 4:
47
- return readBrsV4(brsData, options);
48
- case 8:
49
- return readBrsV8(brsData, options);
50
- case 9:
51
- return readBrsV9(brsData, options);
52
- case 10:
53
- return readBrsV10(brsData, options);
54
- default:
55
- throw new Error('Unsupported version ' + version);
56
- }
57
- }
package/src/read.v1.ts DELETED
@@ -1,99 +0,0 @@
1
- import {
2
- BRSBytes,
3
- ReadOptions,
4
- BrsV1,
5
- UnrealColor,
6
- BrickV1,
7
- Vector,
8
- } from './types';
9
- import { bgra, read } from './utils';
10
-
11
- // Reads in a byte array to build a brs object
12
- export default function readBrsV1(
13
- brsData: BRSBytes,
14
- options: ReadOptions = {}
15
- ): BrsV1 {
16
- // Read in Headers
17
- const header1Data = read.compressed(brsData);
18
- const header2Data = read.compressed(brsData);
19
-
20
- const map = read.string(header1Data);
21
- const author_name = read.string(header1Data);
22
- const description = read.string(header1Data);
23
-
24
- const author_id = read.uuid(header1Data);
25
-
26
- const brick_count = read.i32(header1Data);
27
-
28
- const mods = read.array(header2Data, read.string);
29
- const brick_assets = read.array(header2Data, read.string);
30
- const colors = read.array(
31
- header2Data,
32
- data => bgra(Array.from(read.bytes(data, 4))) as UnrealColor
33
- );
34
-
35
- // Read in bricks
36
- let bricks: BrickV1[] = [];
37
-
38
- const numAssets = Math.max(brick_assets.length, 2);
39
-
40
- if (options.bricks) {
41
- bricks = Array(brick_count);
42
- const brickData = read.compressed(brsData);
43
- const brickBits = read.bits(brickData);
44
-
45
- // Brick reader
46
- for (let i = 0; !brickBits.empty() && i < brick_count; i++) {
47
- brickBits.align();
48
- const asset_name_index = brickBits.int(numAssets);
49
- const size: Vector = brickBits.bit()
50
- ? [
51
- brickBits.uint_packed(),
52
- brickBits.uint_packed(),
53
- brickBits.uint_packed(),
54
- ]
55
- : [0, 0, 0];
56
- const position: Vector = [
57
- brickBits.int_packed(),
58
- brickBits.int_packed(),
59
- brickBits.int_packed(),
60
- ];
61
-
62
- const orientation = brickBits.int(24);
63
- const direction = (orientation >> 2) % 6;
64
- const rotation = orientation & 3;
65
- const collision = brickBits.bit();
66
- const visibility = brickBits.bit();
67
-
68
- const color = brickBits.bit()
69
- ? bgra(brickBits.bytesArr(4) as [number, number, number, number])
70
- : brickBits.int(colors.length);
71
-
72
- bricks[i] = {
73
- asset_name_index,
74
- size,
75
- collision,
76
- position,
77
- direction,
78
- rotation,
79
- visibility,
80
- color,
81
- };
82
- }
83
- }
84
-
85
- return {
86
- version: 1,
87
- map,
88
- description,
89
- author: {
90
- id: author_id,
91
- name: author_name,
92
- },
93
- mods,
94
- brick_assets,
95
- colors,
96
- bricks,
97
- brick_count,
98
- };
99
- }
package/src/read.v10.ts DELETED
@@ -1,185 +0,0 @@
1
- import {
2
- AppliedComponent,
3
- BrickV10,
4
- BRSBytes,
5
- BrsV10,
6
- Collision,
7
- ReadOptions,
8
- UnrealColor,
9
- User,
10
- Vector,
11
- } from './types';
12
- import { bgra, read } from './utils';
13
-
14
- // Reads in a byte array to build a brs object
15
- export default function readBrsV10(
16
- brsData: BRSBytes,
17
- options: ReadOptions = {}
18
- ): BrsV10 {
19
- // game version is included in saves >= v8
20
- const game_version = read.i32(brsData);
21
-
22
- // Read in Headers
23
- const header1Data = read.compressed(brsData);
24
- const header2Data = read.compressed(brsData);
25
-
26
- const map = read.string(header1Data);
27
- const author_name = read.string(header1Data);
28
- const description = read.string(header1Data);
29
- const author_id = read.uuid(header1Data);
30
- const host: User = {
31
- name: read.string(header1Data),
32
- id: read.uuid(header1Data),
33
- };
34
- const save_time = read.bytes(header1Data, 8);
35
-
36
- const brick_count = read.i32(header1Data);
37
-
38
- const mods = read.array(header2Data, read.string);
39
- const brick_assets = read.array(header2Data, read.string);
40
- const colors = read.array(
41
- header2Data,
42
- data => bgra(Array.from(read.bytes(data, 4))) as UnrealColor
43
- );
44
- const materials = read.array(header2Data, read.string);
45
-
46
- const brick_owners = read.array(header2Data, data => ({
47
- id: read.uuid(data),
48
- name: read.string(data),
49
- bricks: read.i32(data),
50
- }));
51
-
52
- const physical_materials = read.array(header2Data, read.string);
53
-
54
- // check for preview byte
55
- let preview = null;
56
- if (read.bytes(brsData, 1)[0]) {
57
- const len = read.i32(brsData);
58
- if (options.preview) {
59
- preview = read.bytes(brsData, len);
60
- } else {
61
- brsData.brsOffset += len;
62
- }
63
- }
64
-
65
- // Read in bricks
66
- let bricks: BrickV10[] = [];
67
- const components: BrsV10['components'] = {};
68
-
69
- const numPhysMats = Math.max(physical_materials.length, 2);
70
- const numMats = Math.max(materials.length, 2);
71
- const numAssets = Math.max(brick_assets.length, 2);
72
-
73
- if (options.bricks) {
74
- bricks = Array(brick_count);
75
- const brickData = read.compressed(brsData);
76
- const brickBits = read.bits(brickData);
77
-
78
- // Brick reader
79
- for (let i = 0; !brickBits.empty() && i < brick_count; i++) {
80
- brickBits.align();
81
- const asset_name_index = brickBits.int(numAssets);
82
- const size: Vector = brickBits.bit()
83
- ? [
84
- brickBits.uint_packed(),
85
- brickBits.uint_packed(),
86
- brickBits.uint_packed(),
87
- ]
88
- : [0, 0, 0];
89
- const position: Vector = [
90
- brickBits.int_packed(),
91
- brickBits.int_packed(),
92
- brickBits.int_packed(),
93
- ];
94
-
95
- const orientation = brickBits.int(24);
96
- const direction = (orientation >> 2) % 6;
97
- const rotation = orientation & 3;
98
- const collision: Collision = {
99
- player: brickBits.bit(),
100
- weapon: brickBits.bit(),
101
- interaction: brickBits.bit(),
102
- tool: brickBits.bit(),
103
- };
104
- const visibility = brickBits.bit();
105
- const material_index = brickBits.int(numMats);
106
- const physical_index = brickBits.int(numPhysMats);
107
- const material_intensity = brickBits.int(11);
108
- const color = brickBits.bit()
109
- ? (brickBits.bytesArr(3) as [number, number, number])
110
- : brickBits.int(colors.length);
111
-
112
- const owner_index = brickBits.uint_packed();
113
-
114
- bricks[i] = {
115
- asset_name_index,
116
- size,
117
- position,
118
- direction,
119
- rotation,
120
- collision: collision as Collision,
121
- visibility,
122
- material_index,
123
- physical_index,
124
- material_intensity,
125
- color,
126
- owner_index,
127
- components: {},
128
- };
129
- }
130
-
131
- const componentData = read.compressed(brsData);
132
- const numBricks = Math.max(bricks.length, 2);
133
-
134
- read.each(componentData, data => {
135
- // read component name
136
- const name = read.string(data);
137
-
138
- // read component body
139
- const bits = read.bits(read.bytes(data, read.i32(data)));
140
-
141
- const version = read.i32(bits.bytes(4));
142
- // list of bricks
143
- const brick_indices = bits.array(() => bits.int(numBricks));
144
-
145
- // list of name, type properties
146
- const properties = bits.array(() => [bits.string(), bits.string()]);
147
-
148
- // read components for each brick
149
- for (const i of brick_indices) {
150
- const props: AppliedComponent = {};
151
- for (const [name, type] of properties) props[name] = bits.unreal(type);
152
- bricks[i].components[name] = props;
153
- }
154
-
155
- components[name] = {
156
- version,
157
- brick_indices,
158
- properties: Object.fromEntries(properties),
159
- };
160
- });
161
- }
162
-
163
- return {
164
- version: 10,
165
- game_version,
166
- map,
167
- description,
168
- author: {
169
- id: author_id,
170
- name: author_name,
171
- },
172
- host,
173
- mods,
174
- brick_assets,
175
- colors,
176
- materials,
177
- brick_owners,
178
- physical_materials,
179
- preview,
180
- bricks,
181
- brick_count,
182
- save_time,
183
- components,
184
- };
185
- }