diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..b947077
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,2 @@
+node_modules/
+dist/
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000..6225a60
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,41 @@
+{
+ "root": true,
+ "env": { "node": true },
+ "parser": "@typescript-eslint/parser",
+ "parserOptions": {
+ "project": ["./tsconfig.json", "./scripts/tsconfig.json"]
+ },
+ "plugins": ["@typescript-eslint", "import"],
+ "extends": [
+ "eslint:recommended",
+ "plugin:@typescript-eslint/recommended",
+ "plugin:import/recommended",
+ "plugin:import/typescript",
+ "prettier"
+ ],
+ "settings": {
+ "import/resolver": {
+ "typescript": {
+ "extensions": [".js"],
+ "extensionAlias": {
+ ".js": [".ts"]
+ },
+ "project": ["./tsconfig.json"]
+ }
+ }
+ },
+ "rules": {
+ "no-return-await": "off",
+ "@typescript-eslint/return-await": ["error", "always"],
+ "import/no-unresolved": "error",
+ "import/extensions": ["error", "never", { "js": "always" }],
+ "import/order": [
+ "warn",
+ {
+ "alphabetize": { "order": "asc", "caseInsensitive": false },
+ "groups": ["type", ["builtin", "external", "internal"], "parent", "sibling", "index", "object"],
+ "newlines-between": "always"
+ }
+ ]
+ }
+}
diff --git a/.github/workflows/lint-compile-test.yml b/.github/workflows/lint-compile-test.yml
index bca9d4f..793fb8e 100644
--- a/.github/workflows/lint-compile-test.yml
+++ b/.github/workflows/lint-compile-test.yml
@@ -3,13 +3,12 @@ name: Lint, compile and test
on:
push:
- branches: [ "main" ]
+ branches: ['main']
pull_request:
- branches: [ "main" ]
+ branches: ['main']
jobs:
build:
-
runs-on: ubuntu-latest
strategy:
@@ -17,12 +16,12 @@ jobs:
node-version: [20.x]
steps:
- - uses: actions/checkout@v3
- - name: Use Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v3
- with:
- node-version: ${{ matrix.node-version }}
- - run: npm install
- - run: npm run lint
- - run: npm run compile
- - run: npm run test
+ - uses: actions/checkout@v3
+ - name: Use Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@v3
+ with:
+ node-version: ${{ matrix.node-version }}
+ - run: npm install --force
+ - run: npm run lint
+ - run: npm run compile
+ - run: npm run test
diff --git a/.gitignore b/.gitignore
index e2e6d3a..792a8df 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,147 @@
package-lock.json
-node_modules/
-dist/
scripts/spawnInfodump.json
+
+# asdf
+
+.tool-versions
+
+# eslint
+
+.eslintcache
+
+# Logs
+
+logs
+_.log
+npm-debug.log_
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log\*
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+
+report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
+
+# Runtime data
+
+pids
+_.pid
+_.seed
+\*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+
+lib-cov
+
+# Coverage directory used by tools like istanbul
+
+coverage
+\*.lcov
+
+# nyc test coverage
+
+.nyc_output
+
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
+
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+
+bower_components
+
+# node-waf configuration
+
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+
+build/Release
+
+# Dependency directories
+
+node_modules/
+jspm_packages/
+
+# TypeScript v1 declaration files
+
+typings/
+
+# TypeScript cache
+
+\*.tsbuildinfo
+
+# Optional npm cache directory
+
+.npm
+
+# Optional eslint cache
+
+.eslintcache
+
+# Microbundle cache
+
+.rpt2_cache/
+.rts2_cache_cjs/
+.rts2_cache_es/
+.rts2_cache_umd/
+
+# Optional REPL history
+
+.node_repl_history
+
+# Output of 'npm pack'
+
+\*.tgz
+
+# Yarn Integrity file
+
+.yarn-integrity
+
+# dotenv environment variables file
+
+.env
+.env.test
+
+# parcel-bundler cache (https://parceljs.org/)
+
+.cache
+
+# Next.js build output
+
+.next
+
+# Nuxt.js build / generate output
+
+.nuxt
+dist
+
+# Gatsby files
+
+.cache/
+
+# Comment in the public line in if your project uses Gatsby and _not_ Next.js
+
+# https://nextjs.org/blog/next-9-1#public-directory-support
+
+# public
+
+# vuepress build output
+
+.vuepress/dist
+
+# Serverless directories
+
+.serverless/
+
+# FuseBox cache
+
+.fusebox/
+
+# DynamoDB Local files
+
+.dynamodb/
+
+# TernJS port file
+
+.tern-port
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100755
index 0000000..78727f6
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1,5 @@
+#!/usr/bin/env sh
+. "$(dirname -- "$0")/_/husky.sh"
+
+npx lint-staged
+npm run compile
diff --git a/.lintstagedrc b/.lintstagedrc
index 6a98907..52c2ddb 100644
--- a/.lintstagedrc
+++ b/.lintstagedrc
@@ -1,3 +1,4 @@
{
- "**/*.{js,ts,jsx,tsx,json,css,html}": "prettier --write"
+ "src/**/*.{js,ts}": ["eslint --cache --fix"],
+ "+(*.md|src/**/*.{js,ts,json,md})": ["prettier --write"]
}
diff --git a/.npmignore b/.npmignore
index e4e563c..40916ca 100644
--- a/.npmignore
+++ b/.npmignore
@@ -1,4 +1,3 @@
package-lock.json
node_modules/
src/
-tests/
diff --git a/.prettierignore b/.prettierignore
index 567609b..849ddff 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1 +1 @@
-build/
+dist/
diff --git a/.prettierrc b/.prettierrc
index 7631ff9..f5ce82a 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,5 +1,6 @@
{
"arrowParens": "avoid",
+ "jsxSingleQuote": true,
"printWidth": 120,
"quoteProps": "preserve",
"semi": true,
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..25fa621
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "typescript.tsdk": "node_modules/typescript/lib"
+}
diff --git a/CODE-OF-CONDUCT.md b/CODE-OF-CONDUCT.md
new file mode 100644
index 0000000..e6b6929
--- /dev/null
+++ b/CODE-OF-CONDUCT.md
@@ -0,0 +1,84 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our community include:
+
+- Demonstrating empathy and kindness toward other people
+- Being respectful of differing opinions, viewpoints, and experiences
+- Giving and gracefully accepting constructive feedback
+- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
+- Focusing on what is best not just for us as individuals, but for the overall community
+
+Examples of unacceptable behavior include:
+
+- The use of sexualized language or imagery, and sexual attention or
+ advances of any kind
+- Trolling, insulting or derogatory comments, and personal or political attacks
+- Public or private harassment
+- Publishing others' private information, such as a physical or email
+ address, without their explicit permission
+- Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement through this repository's issue tracker. All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series of actions.
+
+**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within the project community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0,
+available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
+
+Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
+
+[homepage]: https://www.contributor-covenant.org
+
+For answers to common questions about this code of conduct, see the FAQ at
+https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.
diff --git a/README.md b/README.md
index fd1062d..753d020 100644
--- a/README.md
+++ b/README.md
@@ -1,230 +1,51 @@
-![ATT String Transcoder](./att-st.png)
+
+
+
-# ATT String Transcoder
+ATT String Transcoder
-Allows you to decode _A Township Tale_'s save strings for analysing, and encode JS objects into ATT save strings for spawning.
-
-⚠️ Use this library primarily when creating bots for ATT, or when building your own ATT save string project. **If you just want to make string weapons, check out my [ATT String Workshop](https://github.com/mdingena/att-string-workshop) project.**
-
-## Installation
-
-Add this library to your project's dependencies:
-
-```shell
-npm install --save att-string-transcoder
-```
-
-### Decoding a string
-
-```ts
-import { decodeString } from 'att-string-transcoder';
-
-/**
- * You obtain an encoded save string by sending the `select tostring` console command.
- * See: https://docs.google.com/document/d/150PALdbZalylhkI4_iCL7Bl0X_rgvq80gJCUHik3z4I/edit?usp=sharing
- */
-const encodedString = '23644,174,23644,{...very long...},2,';
-const decodedString = decodeString(encodedString);
-```
-
-
-decodedString
will contain:
-
-```ts
-const decodedString = {
- hash: 23644,
- size: 1392,
- prefab: {
- prefabObject: {
- hash: 23644,
- position: {
- x: -699.1250610351562,
- y: 128.15176391601562,
- z: 98.96036529541016
- },
- rotation: {
- x: -0.00007028286927379668,
- y: -0.06372569501399994,
- z: -0.0011925859143957496,
- w: 0.9979667663574219
- },
- scale: 1.0000009536743164
- },
- components: {
- Unknown: [],
- NetworkRigidbody: {
- position: {
- x: -699.1250610351562,
- y: 128.15176391601562,
- z: 98.96036529541016
- },
- rotation: {
- x: -0.00007028286927379668,
- y: -0.06372569501399994,
- z: -0.0011925859143957496,
- w: 0.9979667663574219
- },
- isKinematic: false,
- isServerSleeping: true,
- velocity: {
- x: 0,
- y: 0,
- z: 0
- },
- angularVelocity: {
- x: 0,
- y: 0,
- z: 0
- }
- },
- Pickup: {
- lastInteractorPlayerId: 1965324787
- },
- LiquidContainer: {
- canAddTo: false,
- canRemoveFrom: true,
- contentLevel: 0,
- hasContent: false,
- isCustom: false,
- presetHash: 0,
- customData: null
- },
- BasicDecay: {
- isDisabled: false,
- timelineEntry: 37654637031400
- }
- },
- embeddedEntities: {
- Unknown: [
- {
- hash: 21290,
- isAlive: true,
- components: {
- Unknown: [],
- Pickup: {
- lastInteractorPlayerId: 1965324787
- }
- }
- }
- ]
- },
- childPrefabs: []
- }
-};
-```
+
+
+
+
+
+
+
+
-
+---
-### Encoding a string
+Allows you to decode _A Township Tale_'s save strings for analysing, and encode JS objects into ATT save strings for spawning.
-
-First, create a blade
prefab object:
+⚠️ Use this library primarily when creating bots for ATT, or when building your own ATT save string project. **If you just want to make string weapons, check out our [ATT String Workshop](https://github.com/mdingena/att-string-workshop) project.**
-```ts
-import { Prefab, PrefabData, PhysicalMaterialPartHash } from 'att-string-transcoder';
-
-const blade: PrefabData = {
- prefabObject: {
- hash: Prefab.Large_Longsword_Blade.hash
- },
- components: {
- PhysicalMaterialPart: {
- materialHash: PhysicalMaterialPartHash.EvinonSteelAlloy
- },
- DurabilityModule: {
- integrity: 0.01
- }
- }
-};
-```
+## :speech_balloon: Join the community
-
+Join the ATT string creators community for sharing and troubleshooting strings built with _ATT String Transcoder_.
-
-Then, create a guard
prefab object:
+
-```ts
-import { Prefab, PrefabData, PhysicalMaterialPartHash } from 'att-string-transcoder';
-
-export const guard: PrefabData = {
- prefabObject: {
- hash: Prefab.Large_Guard_Rectangle.hash
- },
- components: {
- PhysicalMaterialPart: {
- materialHash: PhysicalMaterialPartHash.Copper
- },
- DurabilityModule: {
- integrity: 0.01
- }
- },
- childPrefabs: [
- {
- parentHash: Prefab.Large_Guard_Rectangle.embedded.Slot_Large_SwordType_51896,
- prefab: blade
- }
- ]
-};
-```
+## :sparkles: Quickstart
-
+### Installation
-
-Finally, create a handle
prefab object:
+Add this library to your project's dependencies:
-```ts
-import { Prefab, PrefabData } from 'att-string-transcoder';
-
-const position = {
- x: -701,
- y: 128.2,
- z: 100
-};
-
-export const handle: PrefabData = {
- prefabObject: {
- hash: Prefab.Handle_Short.hash,
- position
- },
- components: {
- NetworkRigidbody: {
- position
- }
- },
- childPrefabs: [
- {
- parentHash: Prefab.Handle_Short.embedded.Slot_Large_SwordType_Craft_6134,
- prefab: guard
- }
- ]
-};
+```shell
+npm install --save att-string-transcoder
```
-
-
-Encode the hierarchical prefab object to obtain a string for spawning:
+### Usage
```ts
-import { createString } from 'att-string-transcoder';
-
-/* ... defined prefab objects ... */
-
-/**
- * You spawn an encoded save string by sending the `spawn string-raw` console command.
- * See: https://docs.google.com/document/d/150PALdbZalylhkI4_iCL7Bl0X_rgvq80gJCUHik3z4I/edit?usp=sharing
- */
-const encodedSword = createString(handle);
-```
+import { Prefab } from 'att-string-transcoder';
-
-encodedSword
will contain:
+const blade = new Prefab('Large_Longsword_Blade').setMaterial('Mythril');
+const handle = new Prefab('Handle_Short_Cool')
+ .addChildPrefab('Slot_Large_SwordType_Craft_33946', blade)
+ .setKinematic()
+ .print();
```
-42230,252,42230,3291430912,1124086579,1120403456,0,0,0,1065353216,1065353216,2290978823,418,3291430912,1124086579,1120403456,0,0,0,1065353216,0,0,0,0,0,0,0,0,536871679,1163,0,0,0,0,0,0,133169152,133169152,34023564,2684354564,2523,1307670851,3758096388,126122721,1073741824,0,268438699,2147487155,3221225472,0,0,0,0,0,66584576,66584576,17011782,1342177282,1968,3875060897,4026531842,63061360,2684354560,0,0,|3,2290978823,1,272188517,1,1871432223,1,
-```
-
-
-
-### Encoding a string (alternative method)
-You can also use the `createPrefab` helper function of this library. See the [ATT String Workshop](https://github.com/mdingena/att-string-workshop) project for documentation about this.
+Read the [API Reference Documentation](docs/README.md) for more options.
diff --git a/att-st.png b/att-st.png
deleted file mode 100644
index b62152e..0000000
Binary files a/att-st.png and /dev/null differ
diff --git a/att-string-transcoder.png b/att-string-transcoder.png
new file mode 100644
index 0000000..c123b72
Binary files /dev/null and b/att-string-transcoder.png differ
diff --git a/docs/ATTPrefabHash.md b/docs/ATTPrefabHash.md
new file mode 100644
index 0000000..0678a39
--- /dev/null
+++ b/docs/ATTPrefabHash.md
@@ -0,0 +1,5 @@
+# ``
+
+The `` type is used to narrow `` types to recognised ATT prefab hashes.
+
+You can use the [`isATTPrefabHash(hash)`](./isATTPrefabHash.md) type assertion function to narrow down your `` types.
diff --git a/docs/ATTPrefabName.md b/docs/ATTPrefabName.md
new file mode 100644
index 0000000..5e21d81
--- /dev/null
+++ b/docs/ATTPrefabName.md
@@ -0,0 +1,5 @@
+# ``
+
+The `` type is used to narrow `` types to recognised ATT prefab names.
+
+You can use the [`isATTPrefabName(name)`](./isATTPrefabName.md) type assertion function to narrow down your `` types.
diff --git a/docs/BasicDecayComponent.md b/docs/BasicDecayComponent.md
new file mode 100644
index 0000000..a76c474
--- /dev/null
+++ b/docs/BasicDecayComponent.md
@@ -0,0 +1,131 @@
+# Class: `BasicDecayComponent`
+
+- [Types](#types)
+ - [``](#componentprops)
+ - [``](#basicdecaycomponentprops)
+- [Constructors](#constructors)
+ - [`new BasicDecayComponent(props)`](#new-basicdecaycomponentprops)
+ - [`BasicDecayComponent.fromBinary(reader, version)`](#basicdecaycomponentfrombinaryreader-version)
+- [Properties](#properties)
+ - [`hash`](#hash)
+ - [`name`](#name)
+ - [`version`](#version)
+ - [`isDisabled`](#isdisabled)
+ - [`timelineEntry`](#timelineentry)
+- [Methods](#methods)
+ - [`toBinary(version?)`](#tobinaryversion)
+ - [`write(writer, version?)`](#writewriter-version)
+
+## Types
+
+### ``
+
+See [``](./Component.md#componentprops)
+
+---
+
+### ``
+
+A portion of the configuration object to pass to the `BasicDecayComponent` constructor.
+
+```ts
+type BasicDecayComponentPropsV3 = {
+ isDisabled?: boolean | undefined;
+ timelineEntry?: number | undefined;
+};
+
+type BasicDecayComponentProps = BasicDecayComponentPropsV3;
+```
+
+#### Since v3
+
+- `isDisabled` (optional, default `true`) ``
+- `timelineEntry` (optional, default `31557600000000000`) ``
+
+## Constructors
+
+### `new BasicDecayComponent(props)`
+
+Creates a versioned `BasicDecay` component.
+
+- `props` [``](#types) Configuration of the component to create.
+- Returns: ``
+
+```ts
+import { BasicDecayComponent } from 'att-string-transcoder';
+
+const componentVersion = 3;
+const component = new BasicDecayComponent({ version: componentVersion });
+```
+
+---
+
+### `BasicDecayComponent.fromBinary(reader, version)`
+
+See [`Component.fromBinary(reader, version)`](./Component.md#componentfrombinaryreader-version)
+
+## Properties
+
+Note that the following properties are sorted in order of appearance when decoding component binary data.
+
+### `hash`
+
+See [`Component.hash`](./Component.md#hash)
+
+---
+
+### `name`
+
+See [`Component.name`](./Component.md#name)
+
+---
+
+### `version`
+
+See [`Component.version`](./Component.md#version)
+
+---
+
+### `isDisabled`
+
+- Since: `v3`
+- ``
+
+```ts
+import { BasicDecayComponent } from 'att-string-transcoder';
+
+const componentVersion = 3;
+const component = new BasicDecayComponent({ version: componentVersion });
+
+const isDisabled = component.isDisabled;
+// `isDisabled` is `true`
+```
+
+---
+
+### `timelineEntry`
+
+- Since: `v3`
+- ``
+
+```ts
+import { BasicDecayComponent } from 'att-string-transcoder';
+
+const componentVersion = 3;
+const component = new BasicDecayComponent({ version: componentVersion });
+
+const timelineEntry = component.timelineEntry;
+// `timelineEntry` is `31557600000000000`
+```
+
+## Methods
+
+### `toBinary(version?)`
+
+See [`Component.toBinary(version?)`](./Component.md#tobinaryversion)
+
+---
+
+### `write(writer, version?)`
+
+See [`Component.write(writer, version?)`](./Component.md#writewriter-version)
diff --git a/docs/BinaryData.md b/docs/BinaryData.md
new file mode 100644
index 0000000..a039140
--- /dev/null
+++ b/docs/BinaryData.md
@@ -0,0 +1,455 @@
+# Class: `BinaryData`
+
+- [Types](#types)
+ - [``](#binarydataoptions)
+ - [``](#unpackfloatoptions)
+- [Constructors](#constructors)
+ - [`new BinaryData(binary, options?)`](#new-binarydatabinary-options)
+ - [`BinaryData.fromBoolean(boolean, options?)`](#binarydatafrombooleanboolean-options)
+ - [`BinaryData.fromChar(char, options?)`](#binarydatafromcharchar-options)
+ - [`BinaryData.fromFloat(float, options?)`](#binarydatafromfloatfloat-options)
+ - [`BinaryData.fromNumber(number, options?)`](#binarydatafromnumbernumber-options)
+ - [`BinaryData.fromSignedInteger(signedInteger, options?)`](#binarydatafromsignedintegersignedinteger-options)
+ - [`BinaryData.fromUnsignedInteger(unsignedInteger, options?)`](#binarydatafromunsignedintegerunsignedinteger-options)
+ - [`BinaryData.fromUnsignedIntegerArray(unsignedIntegerArray, options?)`](#binarydatafromunsignedintegerarrayunsignedintegerarray-options)
+ - [`BinaryData.fromUnsignedLong(unsignedLong, options?)`](#binarydatafromunsignedlongunsignedlong-options)
+ - [`BinaryData.fromUnsignedShort(unsignedShort, options?)`](#binarydatafromunsignedshortunsignedshort-options)
+- [Methods](#methods)
+ - [`BinaryData.isBinaryString(data)`](#binarydataisbinarystringdata)
+ - [`BinaryData.isSaveString(data)`](#binarydataissavestringdata)
+ - [`BinaryData.packFloat(number)`](#binarydatapackfloatnumber)
+ - [`BinaryData.unpackFloat(unsignedInteger, options?)`](#binarydataunpackfloatunsignedinteger)
+ - [`toBinaryString()`](#tobinarystring)
+ - [`toBoolean()`](#toboolean)
+ - [`toChar()`](#tochar)
+ - [`toFloat()`](#tofloat)
+ - [`toNumber()`](#tonumber)
+ - [`toSignedInteger()`](#tosignedinteger)
+ - [`toUnsignedInteger()`](#tounsignedinteger)
+ - [`toUnsignedIntegerArray()`](#tounsignedintegerarray)
+ - [`toUnsignedLong()`](#tounsignedlong)
+ - [`toUnsignedShort()`](#tounsignedshort)
+
+## Types
+
+### ``
+
+A configuration object to optionally pass to the `BinaryData` constructor. Any properties that you do not pass will be created with a default value.
+
+```ts
+type BinaryDataOptions = {
+ signedIntegerOffset?: number;
+};
+```
+
+- `signedIntegerOffset` (optional, default `2147483648`) `` The numeric offset used to (de)serialise signed integers.
+
+## Constructors
+
+### `new BinaryData(binary, options?)`
+
+Creates a data structure from the given binary `data` and lets you express it as other data types. You may optionally provide additional options in the second argument.
+
+- `binary` `` The string containing binary data.
+- `options` (optional) [``](#binarydataoptions) Additional configuration options.
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const data = new BinaryData('11110111001100010000', {
+ signedIntegerOffset: 2147483648
+});
+```
+
+---
+
+### `BinaryData.fromBoolean(boolean, options?)`
+
+Creates a BinaryData instance from the given boolean.
+
+- `boolean` `` The boolean from which to create the BinaryData instance.
+- `options` (optional) [``](#binarydataoptions) Additional configuration options.
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const data = BinaryData.fromBoolean(true);
+```
+
+---
+
+### `BinaryData.fromChar(char, options?)`
+
+Creates a BinaryData instance from the given character.
+
+- `char` `` The single string character from which to create the BinaryData instance.
+- `options` (optional) [``](#binarydataoptions) Additional configuration options.
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const data = BinaryData.fromChar('x');
+```
+
+---
+
+### `BinaryData.fromFloat(float, options?)`
+
+Creates a BinaryData instance from the given floating point number.
+
+- `float` `` The floating point number from which to create the BinaryData instance.
+- `options` (optional) [``](#binarydataoptions) Additional configuration options.
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const data = BinaryData.fromFloat(0.69);
+```
+
+---
+
+### `BinaryData.fromNumber(number, options?)`
+
+Creates a BinaryData instance from the given number.
+
+- `number` `` The number from which to create the BinaryData instance.
+- `options` (optional) [``](#binarydataoptions) Additional configuration options.
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const data = BinaryData.fromNumber(1337);
+```
+
+---
+
+### `BinaryData.fromSignedInteger(signedInteger, options?)`
+
+Creates a BinaryData instance from the given signed integer.
+
+- `signedInteger` `` The signed integer from which to create the BinaryData instance.
+- `options` (optional) [``](#binarydataoptions) Additional configuration options.
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const data = BinaryData.fromSignedInteger(-420);
+```
+
+---
+
+### `BinaryData.fromUnsignedInteger(unsignedInteger, options?)`
+
+Creates a BinaryData instance from the given unsigned integer.
+
+- `unsignedInteger` `` The unsigned integer from which to create the BinaryData instance.
+- `options` (optional) [``](#binarydataoptions) Additional configuration options.
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const data = BinaryData.fromUnsignedInteger(69420);
+```
+
+---
+
+### `BinaryData.fromUnsignedIntegerArray(unsignedIntegerArray, options?)`
+
+Creates a BinaryData instance from the given comma-separated array of unsigned integers.
+
+- `unsignedIntegerArray` `` The array of unsigned integers from which to create the BinaryData instance.
+- `options` (optional) [``](#binarydataoptions) Additional configuration options.
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const data = BinaryData.fromUnsignedIntegerArray([69420, 133769]);
+```
+
+---
+
+### `BinaryData.fromUnsignedLong(unsignedLong, options?)`
+
+Creates a BinaryData instance from the given unsigned long integer.
+
+- `unsignedLong` `` The unsigned long integer from which to create the BinaryData instance.
+- `options` (optional) [``](#binarydataoptions) Additional configuration options.
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const data = BinaryData.fromUnsignedLong(133742069);
+```
+
+---
+
+### `BinaryData.fromUnsignedShort(unsignedShort, options?)`
+
+Creates a BinaryData instance from the given unsigned short integer.
+
+- `unsignedShort` `` The unsigned short integer from which to create the BinaryData instance.
+- `options` (optional) [``](#binarydataoptions) Additional configuration options.
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const data = BinaryData.fromUnsignedShort(420);
+```
+
+## Methods
+
+### `BinaryData.isBinaryString(data)`
+
+Confirms whether `data` is a string of binary data, i.e. a string of zeroes and ones.
+
+:bulb: This is also a type assertion function, so if the passed `` is asserted as a ``, it will be considered as such after calling this function.
+
+- `data` `` The string data to confirm is a [``](./BinaryString.md).
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const maybeBinaryString = '11110111001100010000';
+// `maybeBinaryString` is of type `string`
+
+if (BinaryData.isBinaryString(maybeBinaryString)) {
+ // `maybeBinaryString` is of type `BinaryString` inside this closure
+}
+```
+
+---
+
+### `BinaryData.isSaveString(data)`
+
+Confirms whether `data` is a string of unsigned integers and chunk versioning pairs.
+
+:bulb: This is also a type assertion function, so if the passed `` is asserted as a ``, it will be considered as such after calling this function.
+
+- `data` `` The string data to confirm is a [``](./SaveString.md).
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const maybeSaveString = '...';
+// `maybeSaveString` is of type `string`
+
+if (BinaryData.isSaveString(maybeSaveString)) {
+ // `maybeSaveString` is of type `SaveString` inside this closure
+}
+```
+
+---
+
+### `BinaryData.packFloat(number)`
+
+Converts a JavaScript floating point number into an IEEE754 integer.
+
+- `number` `` The number to pack as an IEEE754 integer.
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const packedFloat = BinaryData.packFloat(1337.42069);
+// `packedFloat` is `1151806838`
+```
+
+---
+
+### `BinaryData.unpackFloat(unsignedInteger)`
+
+Converts an IEEE754 integer into a JavaScript floating point number.
+
+- `unsignedInteger` `` The IEEE754 integer to unpack as a floating point number.
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const unpackedFloat = BinaryData.unpackFloat(1151806838);
+// `unpackedFloat` is approximately `1337.42069`
+```
+
+---
+
+### `toBinaryString()`
+
+Returns the binary data as a `BinaryString`.
+
+- Returns: [``](./BinaryString.md)
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const data = new BinaryData('1111011100110001000');
+
+const binary = data.toBinaryString();
+// `binary` is `'1111011100110001000'`
+```
+
+---
+
+### `toBoolean()`
+
+Returns the boolean represenation of the binary data.
+
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const data = new BinaryData('1');
+
+const boolean = data.toBoolean();
+// `boolean` is `true`
+```
+
+---
+
+### `toChar()`
+
+Returns the character represenation of the binary data.
+
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const data = new BinaryData('01000001');
+
+const char = data.toChar();
+// `char` is `'A'`
+```
+
+---
+
+### `toFloat()`
+
+Returns the floating point number represenation of the binary data.
+
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const data = new BinaryData('01000100101001110010110101110110');
+
+const float = data.toFloat();
+// `float` is approximately `1337.42069`
+```
+
+---
+
+### `toNumber()`
+
+Returns the numeric represenation of the binary data.
+
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const data = new BinaryData('10100111001');
+
+const number = data.toNumber();
+// `number` is `1337`
+```
+
+---
+
+### `toSignedInteger()`
+
+Returns the signed integer representation of the binary data.
+
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const data = new BinaryData('01010110100111110101010000000111');
+
+const signedInteger = data.toSignedInteger();
+// `signedInteger` is `-694201337`
+```
+
+---
+
+### `toUnsignedInteger()`
+
+Returns the unsigned integer representation of the binary data.
+
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const data = new BinaryData('00000111111110001011110111110101');
+
+const unsignedInteger = data.toUnsignedInteger();
+// `unsignedInteger` is `133742069`
+```
+
+---
+
+### `toUnsignedIntegerArray()`
+
+Returns the binary data as a comma-separated array of unsigned integers.
+
+- Returns: `>`
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const data = new BinaryData(
+ '000000000000000000000101001110010000000000000000000000011010010000000000000000000000000001000101'
+);
+
+const unsignedIntegers = data.toUnsignedIntegerArray();
+// `unsignedIntegers` is `[1337, 420, 69]`
+```
+
+---
+
+### `toUnsignedLong()`
+
+Returns the unsigned long integer representation of the binary data.
+
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const data = new BinaryData('0000011111111000101111011111010100000000000000000000000000000000');
+
+const unsignedLongInteger = data.toUnsignedLong();
+// `unsignedLongInteger` is `133742069`
+```
+
+---
+
+### `toUnsignedShort()`
+
+Returns the unsigned short integer representation of the binary data.
+
+- Returns: ``
+
+```ts
+import { BinaryData } from 'att-string-transcoder';
+
+const data = new BinaryData('0000010100111001');
+
+const unsignedShortInteger = data.toUnsignedShort();
+// `unsignedShortInteger` is `1337`
+```
diff --git a/docs/BinaryReader.md b/docs/BinaryReader.md
new file mode 100644
index 0000000..abab98b
--- /dev/null
+++ b/docs/BinaryReader.md
@@ -0,0 +1,201 @@
+# Class: `BinaryReader`
+
+- [Constructors](#constructors)
+ - [`new BinaryReader(data)`](#new-binaryreaderdata)
+- [Methods](#methods)
+ - [`readBits(bitCount)`](#readbitsbitcount)
+ - [`readBoolean(options?)`](#readbooleanoptions)
+ - [`readChar(options?)`](#readcharoptions)
+ - [`readFloat(options?)`](#readfloatoptions)
+ - [`readSignedInteger(options?)`](#readsignedintegeroptions)
+ - [`readString(options?)`](#readstringoptions)
+ - [`readUnsignedInteger(options?)`](#readunsignedintegeroptions)
+ - [`readUnsignedLong(options?)`](#readunsignedlongoptions)
+ - [`readUnsignedShort(options?)`](#readunsignedshortoptions)
+
+## Constructors
+
+### `new BinaryReader(data)`
+
+Creates a reader to extract information from `data` using various read methods.
+
+- `data` `` The binary data to read information from. May only contain `"0"` and `"1"`.
+- Returns: ``
+
+```ts
+import { BinaryReader } from 'att-string-transcoder';
+
+const reader = new BinaryReader('11110111001100010000');
+```
+
+## Methods
+
+### `readBits(bitCount)`
+
+Reads the next `bitCount` bits from the binary string.
+
+- `bitCount` `` The amount of bits to read from the current position of the binary data pointer.
+- Returns: [``](./BinaryString.md)
+
+```ts
+import { BinaryReader } from 'att-string-transcoder';
+
+const reader = new BinaryReader('11110111001100010000');
+
+const firstByte = reader.readBits(8);
+// `firstByte` is `'11110111'`
+```
+
+---
+
+### `readBoolean(options?)`
+
+Reads the next bit from the binary string and returns `true` for `"1"` and `false` for `"0"`.
+
+- `options` (optional) [``](./BinaryData.md#binarydataoptions) Configuration options for `BinaryData`.
+- Returns: ``
+
+```ts
+import { BinaryReader } from 'att-string-transcoder';
+
+const reader = new BinaryReader('10');
+
+const boolean1 = reader.readBoolean();
+// `boolean1` is `true`
+const boolean2 = reader.readBoolean();
+// `boolean2` is `false`
+```
+
+---
+
+### `readChar(options?)`
+
+Reads the next 8 bits from the binary string and returns the reconstructed string character.
+
+- `options` (optional) [``](./BinaryData.md#binarydataoptions) Configuration options for `BinaryData`.
+- Returns: ``
+
+```ts
+import { BinaryReader } from 'att-string-transcoder';
+
+const reader = new BinaryReader('01000001011000100110001101000100');
+
+const char1 = reader.readChar();
+// `char1` is `'A'`
+const char2 = reader.readChar();
+// `char2` is `'b'`
+const char3 = reader.readChar();
+// `char3` is `'c'`
+const char4 = reader.readChar();
+// `char4` is `'D'`
+```
+
+---
+
+### `readFloat(options?)`
+
+Reads the next 32 bits from the binary string and returns the reconstructed floating point number.
+
+- `options` (optional) [``](./BinaryData.md#binarydataoptions) Configuration options for `BinaryData`.
+- Returns: ``
+
+```ts
+import { BinaryReader } from 'att-string-transcoder';
+
+const reader = new BinaryReader('01000100101001110010110101110110');
+
+const float = reader.readFloat();
+// `float` is approximately `1337.42069`
+```
+
+---
+
+### `readSignedInteger(options?)`
+
+Reads the next 32 bits from the binary string and returns the reconstructed signed integer.
+
+- `options` (optional) [``](./BinaryData.md#binarydataoptions) Configuration options for `BinaryData`.
+- Returns: ``
+
+```ts
+import { BinaryReader } from 'att-string-transcoder';
+
+const reader = new BinaryReader('01010110100111110101010000000111');
+
+const signedInteger = reader.readSignedInteger();
+// `signedInteger` is `-694201337`
+```
+
+---
+
+### `readString(options?)`
+
+Reads the next 16 bits from the binary string, then reads the number of bits as instructed and returns the reconstructed string text.
+
+- `options` (optional) [``](./BinaryData.md#binarydataoptions) Configuration options for `BinaryData`.
+- Returns: ``
+
+```ts
+import { BinaryReader } from 'att-string-transcoder';
+
+const reader = new BinaryReader(
+ '000000000000110101001000011001010010110001101111011011000110110001110010011011110111011100100000011011000110010000100001'
+);
+
+const string = reader.readString();
+// `string` is `'Hello, world!'`
+```
+
+---
+
+### `readUnsignedInteger(options?)`
+
+Reads the next 32 bits from the binary string and returns the reconstructed unsigned integer.
+
+- `options` (optional) [``](./BinaryData.md#binarydataoptions) Configuration options for `BinaryData`.
+- Returns: ``
+
+```ts
+import { BinaryReader } from 'att-string-transcoder';
+
+const reader = new BinaryReader('00000111111110001011110111110101');
+
+const unsignedInteger = reader.readUnsignedInteger();
+// `unsignedInteger` is `133742069`
+```
+
+---
+
+### `readUnsignedLong(options?)`
+
+Reads the next 64 bits from the binary string and returns the reconstructed unsigned long integer.
+
+- `options` (optional) [``](./BinaryData.md#binarydataoptions) Configuration options for `BinaryData`.
+- Returns: ``
+
+```ts
+import { BinaryReader } from 'att-string-transcoder';
+
+const reader = new BinaryReader('0000011111111000101111011111010100000000000000000000000000000000');
+
+const unsignedLongInteger = reader.readUnsignedLong();
+// `unsignedLongInteger` is `133742069`
+```
+
+---
+
+### `readUnsignedShort(options?)`
+
+Reads the next 16 bits from the binary string and returns the reconstructed unsigned short integer.
+
+- `options` (optional) [``](./BinaryData.md#binarydataoptions) Configuration options for `BinaryData`.
+- Returns: ``
+
+```ts
+import { BinaryReader } from 'att-string-transcoder';
+
+const reader = new BinaryReader('0000010100111001');
+
+const unsignedShortInteger = reader.readUnsignedShort();
+// `unsignedShortInteger` is `1337`
+```
diff --git a/docs/BinaryString.md b/docs/BinaryString.md
new file mode 100644
index 0000000..5c30830
--- /dev/null
+++ b/docs/BinaryString.md
@@ -0,0 +1,5 @@
+# ``
+
+The `` type is used to narrow `` types to those containing only `"0"` and `"1"` characters.
+
+You can use the [`BinaryData.isBinaryString`](./BinaryData.md#binarydataisbinarystring) type assertion function to narrow down your `` types.
diff --git a/docs/BinaryWriter.md b/docs/BinaryWriter.md
new file mode 100644
index 0000000..bc94043
--- /dev/null
+++ b/docs/BinaryWriter.md
@@ -0,0 +1,203 @@
+# Class: `BinaryWriter`
+
+- [Constructors](#constructors)
+ - [`new BinaryWriter()`](#new-binarywriter)
+- [Methods](#methods)
+ - [`flush()`](#flush)
+ - [`writeBits(data)`](#writebitsdata)
+ - [`writeBoolean(boolean)`](#writebooleanboolean)
+ - [`writeChar(char)`](#writecharchar)
+ - [`writeFloat(float)`](#writefloatfloat)
+ - [`writeSignedInteger(signedInteger)`](#writesignedintegersignedinteger)
+ - [`writeString(string)`](#writestringstring)
+ - [`writeUnsignedInteger(unsignedInteger)`](#writeunsignedintegerunsignedinteger)
+ - [`writeUnsignedLong(unsignedLong)`](#writeunsignedlongunsignedlong)
+ - [`writeUnsignedShort(unsignedShort)`](#writeunsignedshortunsignedshort)
+
+## Constructors
+
+### `new BinaryWriter()`
+
+Creates a writer to store information using various write methods.
+
+- Returns: ``
+
+```ts
+import { BinaryReader } from 'att-string-transcoder';
+
+const reader = new BinaryReader('11110111001100010000');
+```
+
+## Methods
+
+### `flush()`
+
+Returns the stored binary string and resets the BinaryWriter's internal memory.
+
+- Returns: [``](./BinaryString.md)
+
+```ts
+import { BinaryWriter } from 'att-string-transcoder';
+
+const writer = new BinaryWriter();
+
+writer.writeBoolean(true); // internal memory is `'1'`
+writer.writeBoolean(true); // internal memory is `'11'`
+writer.writeBoolean(true); // internal memory is `'111'`
+
+const output = writer.flush(); // internal memory is `''`
+// `output` is `'111'`
+```
+
+---
+
+### `writeBits(data)`
+
+Writes raw binary data into BinaryWriter's internal memory.
+
+- `data` `` The binary string data to store in internal memory.
+- Returns: ``
+
+```ts
+import { BinaryWriter } from 'att-string-transcoder';
+
+const writer = new BinaryWriter();
+
+writer.writeBits('11110111001100010000');
+```
+
+---
+
+### `writeBoolean(boolean)`
+
+Writes a boolean into BinaryWriter's internal memory.
+
+- `boolean` `` The boolean to store in internal memory.
+- Returns: ``
+
+```ts
+import { BinaryWriter } from 'att-string-transcoder';
+
+const writer = new BinaryWriter();
+
+writer.writeBoolean(true);
+```
+
+---
+
+### `writeChar(char)`
+
+Writes a character into BinaryWriter's internal memory.
+
+- `char` `` The character to store in internal memory.
+- Returns: ``
+
+```ts
+import { BinaryWriter } from 'att-string-transcoder';
+
+const writer = new BinaryWriter();
+
+writer.writeChar('x');
+```
+
+---
+
+### `writeFloat(float)`
+
+Writes a floating point number into BinaryWriter's internal memory.
+
+- `float` `` The floating point number to store in internal memory.
+- Returns: ``
+
+```ts
+import { BinaryWriter } from 'att-string-transcoder';
+
+const writer = new BinaryWriter();
+
+writer.writeFloat(0.69);
+```
+
+---
+
+### `writeSignedInteger(signedInteger)`
+
+Writes a signed integer into BinaryWriter's internal memory.
+
+- `signedInteger` `` The signed integer to store in internal memory.
+- Returns: ``
+
+```ts
+import { BinaryWriter } from 'att-string-transcoder';
+
+const writer = new BinaryWriter();
+
+writer.writeSignedInteger(-420);
+```
+
+---
+
+### `writeString(string)`
+
+Writes a string into BinaryWriter's internal memory.
+
+- `string` `` The string to store in internal memory.
+- Returns: ``
+
+```ts
+import { BinaryWriter } from 'att-string-transcoder';
+
+const writer = new BinaryWriter();
+
+writer.writeString('Hello, world!');
+```
+
+---
+
+### `writeUnsignedInteger(unsignedInteger)`
+
+Writes an unsigned integer into BinaryWriter's internal memory.
+
+- `unsignedInteger` `` The unsigned integer to store in internal memory.
+- Returns: ``
+
+```ts
+import { BinaryWriter } from 'att-string-transcoder';
+
+const writer = new BinaryWriter();
+
+writer.writeUnsignedInteger(69420);
+```
+
+---
+
+### `writeUnsignedLong(unsignedLong)`
+
+Writes an unsigned long integer into BinaryWriter's internal memory.
+
+- `unsignedLong` `` The unsigned long integer to store in internal memory.
+- Returns: ``
+
+```ts
+import { BinaryWriter } from 'att-string-transcoder';
+
+const writer = new BinaryWriter();
+
+writer.writeUnsignedLong(133742069);
+```
+
+---
+
+### `writeUnsignedShort(unsignedShort)`
+
+Writes an unsigned short integer into BinaryWriter's internal memory.
+
+- `unsignedShort` `` The unsigned short integer to store in internal memory.
+- Returns: ``
+
+```ts
+import { BinaryWriter } from 'att-string-transcoder';
+
+const writer = new BinaryWriter();
+
+writer.writeUnsignedShort(1337);
+```
diff --git a/docs/Component.md b/docs/Component.md
new file mode 100644
index 0000000..3e32fbe
--- /dev/null
+++ b/docs/Component.md
@@ -0,0 +1,161 @@
+# Class: `Component`
+
+- [Types](#types)
+ - [``](#basecomponentprops)
+ - [``](#componentprops)
+- [Constructors](#constructors)
+ - [`new Component(props)`](#new-componentprops)
+ - [`Component.fromBinary(reader, version)`](#componentfrombinaryreader-version)
+- [Properties](#properties)
+ - [`hash`](#hash)
+ - [`name`](#name)
+ - [`version`](#version)
+- [Methods](#methods)
+ - [`toBinary(version?)`](#tobinaryversion)
+ - [`write(writer, version?)`](#writewriter-version)
+
+## Types
+
+### ``
+
+A portion of the configuration object to pass to the `Component` constructor. These properties are only present on the base `Component` class constructor and are not used in derived classes.
+
+```ts
+type BaseComponentProps = {
+ hash: number;
+ name: string;
+};
+```
+
+- `hash` `` The hash of the component.
+- `name` `` The name of the component.
+
+---
+
+### ``
+
+A portion of the configuration object to pass to the `Component` constructor. These properties are also used in all derived class constructors.
+
+```ts
+type ComponentProps = {
+ version: number;
+};
+```
+
+- `version` `` The version of the component, which controls its data shape and (de)serialisation sequence.
+
+## Constructors
+
+### `new Component(props)`
+
+Creates a versioned component. This constructor is used internally. You shouldn't create any instances of this base class.
+
+- `props` [``](#basecomponentprops) Configuration of the component to create.
+- Returns: ``
+
+:warning: You shouldn't create any instances of this base class. Use any of its [derived classes](./README.md) instead.
+
+---
+
+### `Component.fromBinary(reader, version)`
+
+Reads the binary string data and returns an instantiated component.
+
+- `reader` [`BinaryReader`](./BinaryReader.md) The `BinaryReader` instance containing the entity binary data.
+- `version` `` The version of the component for interpreting the binary data.
+
+:warning: You shouldn't create any instances of this base class. Use any of its [derived classes](./README.md) instead.
+
+## Properties
+
+Note that the following properties are sorted in order of appearance when decoding component binary data.
+
+### `hash`
+
+The hash of the component.
+
+- `` The hash of the component.
+
+```ts
+import { DerivedComponent } from 'att-string-transcoder';
+
+const componentVersion = 1;
+const component = new DerivedComponent({ version: componentVersion });
+
+const hash = component.hash;
+```
+
+---
+
+### `name`
+
+The name of the component.
+
+- `` The name of the component.
+
+```ts
+import { DerivedComponent } from 'att-string-transcoder';
+
+const componentVersion = 1;
+const component = new DerivedComponent({ version: componentVersion });
+
+const name = component.name;
+```
+
+---
+
+### `version`
+
+The version of the component. This controls the shape of the component data and its (de)serialisation sequence when reading or writing binary data.
+
+- `` The version of the component.
+
+```ts
+import { DerivedComponent } from 'att-string-transcoder';
+
+const componentVersion = 1;
+const component = new DerivedComponent({ version: componentVersion });
+
+const version = component.version;
+// `version` is `1`
+```
+
+## Methods
+
+### `toBinary(version?)`
+
+Returns a `BinaryString` representation of the component.
+
+- `version` (optional, default `this.version`) `` The version of the component, which controls its serialisation sequence.
+- Returns: [``](./BinaryString.md)
+
+```ts
+import { DerivedComponent } from 'att-string-transcoder';
+
+const componentVersion = 1;
+
+const component = new DerivedComponent({ version: componentVersion });
+
+const binaryString = component.toBinary(componentVersion);
+```
+
+---
+
+### `write(writer, version?)`
+
+Writes a `BinaryString` representation of the component to the given `BinaryWriter`, including the component hash and data length.
+
+- `writer` [``](./BinaryWriter.md) The `BinaryWriter` instance in which to store the binary data.
+- `version` (optional, default `this.version`) `` The version of the component, which controls its serialisation sequence.
+- Returns: ``
+
+```ts
+import { BinaryWriter, DerivedComponent } from 'att-string-transcoder';
+
+const writer = new BinaryWriter();
+const componentVersion = 1;
+
+const component = new DerivedComponent({ version: componentVersion });
+
+component.write(writer, componentVersion);
+```
diff --git a/docs/DoorComponent.md b/docs/DoorComponent.md
new file mode 100644
index 0000000..5d51347
--- /dev/null
+++ b/docs/DoorComponent.md
@@ -0,0 +1,113 @@
+# Class: `DoorComponent`
+
+- [Types](#types)
+ - [``](#componentprops)
+ - [``](#doorcomponentprops)
+- [Constructors](#constructors)
+ - [`new DoorComponent(props)`](#new-doorcomponentprops)
+ - [`DoorComponent.fromBinary(reader, version)`](#doorcomponentfrombinaryreader-version)
+- [Properties](#properties)
+ - [`hash`](#hash)
+ - [`name`](#name)
+ - [`version`](#version)
+ - [`isOpen`](#isopen)
+- [Methods](#methods)
+ - [`toBinary(version?)`](#tobinaryversion)
+ - [`write(writer, version?)`](#writewriter-version)
+
+## Types
+
+### ``
+
+See [``](./Component.md#componentprops)
+
+---
+
+### ``
+
+A portion of the configuration object to pass to the `DoorComponent` constructor.
+
+```ts
+type DoorComponentPropsV1 = {
+ isOpen?: number | undefined;
+};
+
+type DoorComponentProps = DoorComponentPropsV1;
+```
+
+#### Since v1
+
+- `isOpen` (optional, default `false`) ``
+
+## Constructors
+
+### `new DoorComponent(props)`
+
+Creates a versioned `Door` component.
+
+- `props` [``](#types) Configuration of the component to create.
+- Returns: ``
+
+```ts
+import { DoorComponent } from 'att-string-transcoder';
+
+const componentVersion = 1;
+const component = new DoorComponent({ version: componentVersion });
+```
+
+---
+
+### `DoorComponent.fromBinary(reader, version)`
+
+See [`Component.fromBinary(reader, version)`](./Component.md#componentfrombinaryreader-version)
+
+## Properties
+
+Note that the following properties are sorted in order of appearance when decoding component binary data.
+
+### `hash`
+
+See [`Component.hash`](./Component.md#hash)
+
+---
+
+### `name`
+
+See [`Component.name`](./Component.md#name)
+
+---
+
+### `version`
+
+See [`Component.version`](./Component.md#version)
+
+---
+
+### `isOpen`
+
+Reveals the open state of this component's prefab
+
+- Since: `v1`
+- ``
+
+```ts
+import { DoorComponent } from 'att-string-transcoder';
+
+const componentVersion = 1;
+const component = new DoorComponent({ version: componentVersion });
+
+const isOpen = component.isOpen;
+// `isOpen` is `false`
+```
+
+## Methods
+
+### `toBinary(version?)`
+
+See [`Component.toBinary(version?)`](./Component.md#tobinaryversion)
+
+---
+
+### `write(writer, version?)`
+
+See [`Component.write(writer, version?)`](./Component.md#writewriter-version)
diff --git a/docs/DurabilityModuleComponent.md b/docs/DurabilityModuleComponent.md
new file mode 100644
index 0000000..4cdbd1c
--- /dev/null
+++ b/docs/DurabilityModuleComponent.md
@@ -0,0 +1,113 @@
+# Class: `DurabilityModuleComponent`
+
+- [Types](#types)
+ - [``](#componentprops)
+ - [``](#durabilitymodulecomponentprops)
+- [Constructors](#constructors)
+ - [`new DurabilityModuleComponent(props)`](#new-durabilitymodulecomponentprops)
+ - [`DurabilityModuleComponent.fromBinary(reader, version)`](#durabilitymodulecomponentfrombinaryreader-version)
+- [Properties](#properties)
+ - [`hash`](#hash)
+ - [`name`](#name)
+ - [`version`](#version)
+ - [`integrity`](#integrity)
+- [Methods](#methods)
+ - [`toBinary(version?)`](#tobinaryversion)
+ - [`write(writer, version?)`](#writewriter-version)
+
+## Types
+
+### ``
+
+See [``](./Component.md#componentprops)
+
+---
+
+### ``
+
+A portion of the configuration object to pass to the `DurabilityModuleComponent` constructor.
+
+```ts
+type DurabilityModuleComponentPropsV1 = {
+ integrity?: number | undefined;
+};
+
+type DurabilityModuleComponentProps = DurabilityModuleComponentPropsV1;
+```
+
+#### Since v1
+
+- `integrity` (optional, default `1`) ``
+
+## Constructors
+
+### `new DurabilityModuleComponent(props)`
+
+Creates a versioned `DurabilityModule` component.
+
+- `props` [``](#types) Configuration of the component to create.
+- Returns: ``
+
+```ts
+import { DurabilityModuleComponent } from 'att-string-transcoder';
+
+const componentVersion = 1;
+const component = new DurabilityModuleComponent({ version: componentVersion });
+```
+
+---
+
+### `DurabilityModuleComponent.fromBinary(reader, version)`
+
+See [`Component.fromBinary(reader, version)`](./Component.md#componentfrombinaryreader-version)
+
+## Properties
+
+Note that the following properties are sorted in order of appearance when decoding component binary data.
+
+### `hash`
+
+See [`Component.hash`](./Component.md#hash)
+
+---
+
+### `name`
+
+See [`Component.name`](./Component.md#name)
+
+---
+
+### `version`
+
+See [`Component.version`](./Component.md#version)
+
+---
+
+### `integrity`
+
+The integrity of the prefab this component is attached to.
+
+- Since: `v1`
+- `` A number between `0` and `1` (inclusive).
+
+```ts
+import { DurabilityModuleComponent } from 'att-string-transcoder';
+
+const componentVersion = 1;
+const component = new DurabilityModuleComponent({ version: componentVersion });
+
+const integrity = component.integrity;
+// `integrity` is `1`
+```
+
+## Methods
+
+### `toBinary(version?)`
+
+See [`Component.toBinary(version?)`](./Component.md#tobinaryversion)
+
+---
+
+### `write(writer, version?)`
+
+See [`Component.write(writer, version?)`](./Component.md#writewriter-version)
diff --git a/docs/Entity.md b/docs/Entity.md
new file mode 100644
index 0000000..941ed79
--- /dev/null
+++ b/docs/Entity.md
@@ -0,0 +1,216 @@
+# Class: `Entity`
+
+- [Types](#types)
+ - [``](#entityfrombinaryprops)
+ - [``](#entityprops)
+- [Constructors](#constructors)
+ - [`new Entity(key, props?)`](#new-entitykey-props)
+ - [`Entity.fromBinary(reader, props)`](#entityfrombinaryreader-props)
+- [Properties](#properties)
+ - [`hash`](#hash)
+ - [`name`](#name)
+ - [`isAlive`](#isalive)
+ - [`components`](#components)
+- [Methods](#methods)
+ - [`toBinary(componentVersions)`](#tobinarycomponentversions)
+ - [`write(writer, componentVersions)`](#writewriter-componentversions)
+
+## Types
+
+### ``
+
+A configuration object to pass to the `fromBinary` constructor. Lets you instantiate an `Entity` from reading its binary data.
+
+```ts
+type EntityFromBinaryProps = {
+ key: string;
+ hash: number;
+ componentVersions?: Map | undefined;
+};
+```
+
+- `key` [`EntityKey`](../src/types/EntityKey.ts) The key (`${name}_${hash}`) of the entity.
+- `hash` `` The hash of the entity.
+- `componentVersions` (optional) `