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 +

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: [] - } -}; -``` +

+ build status + npm version + node version + typescript version + license + contributor covenant v2.0 adopted +

-
+--- -### 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: +Chat with the ATT String Transcoder community on Discord -```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) `>` A map of component versions to assume are encoded in the binary data. + +--- + +### `` + +A configuration object to optionally pass to the `Entity` constructor. Lets you instantiate an `Entity` with predefined data. Any properties that you do not pass will be created with a default value. + +```ts +type EntityProps = { + hash?: number | undefined; + isAlive?: boolean | undefined; + components?: (SupportedPrefabComponents & UnsupportedPrefabComponents & Partial) | undefined; +}; +``` + +- `hash` (optional) `` The hash of the entity. +- `isAlive` (optional, default `true`) `` Whether ATT considers this entity "alive". +- `components` (optional) [``](../src/types/PrefabComponents.ts) A mapped object of components on the entity. + +## Constructors + +### `new Entity(key, props?)` + +Creates a new `Entity` object configured with the passed in configuration. + +- `key` [`EntityKey`](../src/types/EntityKey.ts) The key (`${name}_${hash}`) of the entity. +- `props` (optional) [``](#entityprops) Additional configuration of the entity to create. +- Returns: `` + +```ts +import { Entity } from 'att-string-transcoder'; + +const torchFireEntity = new Entity<'Torch'>('Fire_30100', { + hash: 30100, + isAlive: true, + components: {} +}); +``` + +:warning: This argument **must** be passed with at least the `hash` property when manually creating an unrecognised entity. + +```ts +import { Entity } from 'att-string-transcoder'; + +const torchUnknownEntity = new Entity<'Torch'>('Unknown', { hash: 1337 }); +``` + +--- + +### `Entity.fromBinary(reader, props)` + +Reads the binary string data and returns an instantiated entity. + +- `reader` [`BinaryReader`](./BinaryReader.md) The `BinaryReader` instance containing the entity binary data. +- `props` [``](#entityfrombinaryprops) The configuration for interpreting the binary data. + +```ts +import { Entity } from 'att-string-transcoder'; + +const torchFireEntity = Entity.fromBinary<'Torch'>(myBinaryString); +``` + +## Properties + +Note that the following properties are sorted in order of appearance when decoding entity binary data. + +### `hash` + +The hash of the entity. + +- `` The hash of the entity. + +```ts +import { Entity } from 'att-string-transcoder'; + +const entity = new Entity<'Torch'>('Fire_30100'); + +const hash = entity.hash; +// `hash` is `30100` +``` + +--- + +### `name` + +The name of the entity. + +- `` The name of the entity. + +```ts +import { Entity } from 'att-string-transcoder'; + +const entity = new Entity<'Torch'>('Fire_30100'); + +const name = entity.name; +// `name` is `'Fire'` +``` + +--- + +### `isAlive` + +The alive state of the entity. + +- `` The alive state of the entity. + +```ts +import { Entity } from 'att-string-transcoder'; + +const entity = new Entity<'Torch'>('Fire_30100'); + +const isAlive = entity.isAlive; +// `isAlive` is `true` +``` + +--- + +### `components` + +Provides access to the components stored in this entity. Components are keyed to their respective names, unless its data contained an unrecognised hash. In that case, the component will be stored in an array under the `Unknown` key. + +- [``](../src/types/PrefabComponents.ts) A map of the stored components. + +```ts +import { Entity } from 'att-string-transcoder'; + +const entity = new Entity<'Torch'>('Fire_30100'); + +const components = entity.components; +// `components` is `{ Unknown: [] }` +``` + +## Methods + +### `toBinary(componentVersions)` + +Returns a `BinaryString` representation of the entity. + +- `componentVersions` `>` A map of component versions to ensure are encoded in the binary data. +- Returns: [``](./BinaryString.md) + +```ts +import { ComponentHash, Entity } from 'att-string-transcoder'; + +const torchFireEntity = new Entity<'Torch'>('Fire_30100'); + +const componentVersions = new Map([ + [ComponentHash.NetworkRigidbody, 1], + [ComponentHash.PhysicalMaterialPart, 1], + [ComponentHash.Pickup, 2] + // etc... +]); + +const binaryString = torchFireEntity.toBinary(componentVersions); +``` + +--- + +### `write(writer, componentVersions)` + +Writes a `BinaryString` representation of the entity to the given `BinaryWriter`, including the entity hash and data length. + +- `writer` [``](./BinaryWriter.md) The `BinaryWriter` instance in which to store the binary data. +- `componentVersions` `>` A map of component versions to ensure are encoded in the binary data. +- Returns: `` + +```ts +import { BinaryWriter, ComponentHash, Entity } from 'att-string-transcoder'; + +const torchFireEntity = new Entity<'Torch'>('Fire_30100'); + +const componentVersions = new Map([ + [ComponentHash.NetworkRigidbody, 1], + [ComponentHash.PhysicalMaterialPart, 1], + [ComponentHash.Pickup, 2] + // etc... +]); + +const writer = new BinaryWriter(); + +torchFireEntity.write(writer, componentVersions); +``` diff --git a/docs/FireComponent.md b/docs/FireComponent.md new file mode 100644 index 0000000..2fa3064 --- /dev/null +++ b/docs/FireComponent.md @@ -0,0 +1,113 @@ +# Class: `FireComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#firecomponentprops) +- [Constructors](#constructors) + - [`new FireComponent(props)`](#new-firecomponentprops) + - [`FireComponent.fromBinary(reader, version)`](#firecomponentfrombinaryreader-version) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`fuelConsumptionProgress`](#fuelconsumptionprogress) +- [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 `FireComponent` constructor. + +```ts +type FireComponentPropsV1 = { + fuelConsumptionProgress?: number | undefined; +}; + +type FireComponentProps = FireComponentPropsV1; +``` + +#### Since v1 + +- `fuelConsumptionProgress` (optional, default `1`) `` + +## Constructors + +### `new FireComponent(props)` + +Creates a versioned `Fire` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { FireComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new FireComponent({ version: componentVersion }); +``` + +--- + +### `FireComponent.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) + +--- + +### `fuelConsumptionProgress` + +The progress of the consumption of fuel attached to this component's prefab. + +- Since: `v1` +- `` A number between `0` and `1` (inclusive). + +```ts +import { FireComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new FireComponent({ version: componentVersion }); + +const fuelConsumptionProgress = component.fuelConsumptionProgress; +// `fuelConsumptionProgress` 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/FuseComponent.md b/docs/FuseComponent.md new file mode 100644 index 0000000..e76f63b --- /dev/null +++ b/docs/FuseComponent.md @@ -0,0 +1,157 @@ +# Class: `FuseComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#fusecomponentprops) +- [Constructors](#constructors) + - [`new FuseComponent(props)`](#new-fusecomponentprops) + - [`FuseComponent.fromBinary(reader, version)`](#fusecomponentfrombinaryreader-version) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`isFinished`](#isfinished) + - [`isLit`](#islit) + - [`currentFuseAmount`](#currentfuseamount) +- [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 `FuseComponent` constructor. + +```ts +type FuseComponentPropsV1 = { + isFinished?: boolean | undefined; + isLit?: boolean | undefined; + currentFuseAmount?: number | undefined; +}; + +type FuseComponentProps = FuseComponentPropsV1; +``` + +#### Since v1 + +- `isFinished` (optional, default `false`) `` +- `isLit` (optional, default `false`) `` +- `currentFuseAmount` (optional, default `1`) `` + +## Constructors + +### `new FuseComponent(props)` + +Creates a versioned `Fuse` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { FuseComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new FuseComponent({ version: componentVersion }); +``` + +--- + +### `FuseComponent.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) + +--- + +### `isFinished` + +Whether the fuse is finished or not. + +- Since: `v1` +- `` + +```ts +import { FuseComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new FuseComponent({ version: componentVersion }); + +const isFinished = component.isFinished; +// `isFinished` is `false` +``` + +--- + +### `isLit` + +Whether the fuse is lit or not. + +- Since: `v1` +- `` + +```ts +import { FuseComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new FuseComponent({ version: componentVersion }); + +const isLit = component.isLit; +// `isLit` is `false` +``` + +--- + +### `currentFuseAmount` + +How much of the fuse is left. + +- Since: `v1` +- `` A number between `0` and `1` (inclusive). + +```ts +import { FuseComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new FuseComponent({ version: componentVersion }); + +const currentFuseAmount = component.currentFuseAmount; +// `currentFuseAmount` 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/HeatSourceBaseComponent.md b/docs/HeatSourceBaseComponent.md new file mode 100644 index 0000000..60236cc --- /dev/null +++ b/docs/HeatSourceBaseComponent.md @@ -0,0 +1,155 @@ +# Class: `HeatSourceBaseComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#heatsourcebasecomponentprops) +- [Constructors](#constructors) + - [`new HeatSourceBaseComponent(props)`](#new-heatsourcebasecomponentprops) + - [`HeatSourceBaseComponent.fromBinary(reader, version)`](#heatsourcebasecomponentfrombinaryreader-version) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`isLit`](#islit) + - [`progress`](#progress) + - [`time`](#time) +- [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 `HeatSourceBaseComponent` constructor. + +```ts +type HeatSourceBaseComponentPropsV1 = { + isLit?: boolean | undefined; + progress?: number | undefined; + time?: number | undefined; +}; + +export type HeatSourceBaseComponentProps = HeatSourceBaseComponentPropsV1; +``` + +#### Since v1 + +- `isLit` (optional, default `true`) `` +- `progress` (optional, default `0`) `` +- `time` (optional, default `31557600000000000`) `` + +## Constructors + +### `new HeatSourceBaseComponent(props)` + +Creates a versioned `HeatSourceBase` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { HeatSourceBaseComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new HeatSourceBaseComponent({ version: componentVersion }); +``` + +--- + +### `HeatSourceBaseComponent.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) + +--- + +### `isLit` + +Whether this heat source is lit and active or not. + +- Since: `v1` +- `` + +```ts +import { HeatSourceBaseComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new HeatSourceBaseComponent({ version: componentVersion }); + +const isLit = component.isLit; +// `isLit` is `true` +``` + +--- + +### `progress` + +Progress of the heat source until extinguishing. + +- Since: `v1` +- `` A number between `0` and `1` (inclusive). + +```ts +import { HeatSourceBaseComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new HeatSourceBaseComponent({ version: componentVersion }); + +const progress = component.progress; +// `progress` is `0` +``` + +--- + +### `time` + +- Since: `v1` +- `` + +```ts +import { HeatSourceBaseComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new HeatSourceBaseComponent({ version: componentVersion }); + +const time = component.time; +// `time` 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/LiquidContainerComponent.md b/docs/LiquidContainerComponent.md new file mode 100644 index 0000000..7e6605c --- /dev/null +++ b/docs/LiquidContainerComponent.md @@ -0,0 +1,267 @@ +# Class: `LiquidContainerComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#liquidcontainercomponentprops) +- [Constructors](#constructors) + - [`new LiquidContainerComponent(props)`](#new-liquidcontainercomponentprops) + - [`LiquidContainerComponent.fromBinary(reader, version)`](#liquidcontainercomponentfrombinaryreader-version) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`canAddTo`](#canaddto) + - [`canRemoveFrom`](#canremovefrom) + - [`contentLevel`](#contentlevel) + - [`hasContent`](#hascontent) + - [`isCustom`](#iscustom) + - [`presetHash`](#presethash) + - [`customData`](#customdata) +- [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 `LiquidContainerComponent` constructor. + +```ts +type Color = { + r: number; + g: number; + b: number; + a: number; +}; + +type Effect = null | { + hash: number; + strengthMultiplier: number; +}; + +type FoodChunk = number; + +type CustomData = null | { + color: Color; + isConsumableThroughSkin: boolean; + visualDataHash: number; + effects: Effect[]; + foodChunks: FoodChunk[]; +}; + +type LiquidContainerComponentPropsV1 = { + canAddTo?: boolean | undefined; + canRemoveFrom?: boolean | undefined; + contentLevel?: number | undefined; + hasContent?: boolean | undefined; + isCustom?: boolean | undefined; + presetHash?: number | undefined; + customData?: CustomData | undefined; +}; + +export type LiquidContainerComponentProps = LiquidContainerComponentPropsV1; +``` + +#### Since v1 + +- `canAddTo` (optional, default `false`) `` +- `canRemoveFrom` (optional, default `false`) `` +- `contentLevel` (optional, default `0`) `` +- `hasContent` (optional, default `false`) `` +- `isCustom` (optional, default `false`) `` +- `presetHash` (optional, default `0`) [``](../src/types/PresetHash.ts) +- `customData` (optional, default `null`) `` + +## Constructors + +### `new LiquidContainerComponent(props)` + +Creates a versioned `LiquidContainer` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { LiquidContainerComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LiquidContainerComponent({ version: componentVersion }); +``` + +--- + +### `LiquidContainerComponent.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) + +--- + +### `canAddTo` + +Whether any content can be added to the liquid container or not. + +- Since: `v1` +- `` + +```ts +import { LiquidContainerComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LiquidContainerComponent({ version: componentVersion }); + +const canAddTo = component.canAddTo; +// `canAddTo` is `false` +``` + +--- + +### `canRemoveFrom` + +Whether any content can be removed from the liquid container or not. + +- Since: `v1` +- `` + +```ts +import { LiquidContainerComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LiquidContainerComponent({ version: componentVersion }); + +const canRemoveFrom = component.canRemoveFrom; +// `canRemoveFrom` is `false` +``` + +--- + +### `contentLevel` + +The amount of content stored inside the liquid container. + +- Since: `v1` +- `` Any integer greater than or equal to `0`. + +```ts +import { LiquidContainerComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LiquidContainerComponent({ version: componentVersion }); + +const contentLevel = component.contentLevel; +// `contentLevel` is `0` +``` + +--- + +### `hasContent` + +Whether any content is stored in the liquid container or not. + +- Since: `v1` +- `` + +```ts +import { LiquidContainerComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LiquidContainerComponent({ version: componentVersion }); + +const hasContent = component.hasContent; +// `hasContent` is `false` +``` + +--- + +### `isCustom` + +Whether the content stored in the liquid container is custom or a preset. + +- Since: `v1` +- `` + +```ts +import { LiquidContainerComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LiquidContainerComponent({ version: componentVersion }); + +const isCustom = component.isCustom; +// `isCustom` is `false` +``` + +--- + +### `presetHash` + +The hash of the preset of the contents stored in the liquid container. Is `0` when no preset is used (uses `CustomData` instead). + +- Since: `v1` +- [``](../src/types/PresetHash.ts) + +```ts +import { LiquidContainerComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LiquidContainerComponent({ version: componentVersion }); + +const presetHash = component.presetHash; +// `presetHash` is `0` +``` + +--- + +### `customData` + +The data to use as the customised contents of the liquid container. + +- Since: `v1` +- `` + +```ts +import { LiquidContainerComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LiquidContainerComponent({ version: componentVersion }); + +const customData = component.customData; +// `customData` is `null` +``` + +## 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/LogicBoolReceiverComponent.md b/docs/LogicBoolReceiverComponent.md new file mode 100644 index 0000000..f19e484 --- /dev/null +++ b/docs/LogicBoolReceiverComponent.md @@ -0,0 +1,113 @@ +# Class: `LogicBoolReceiverComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#logicboolreceivercomponentprops) +- [Constructors](#constructors) + - [`new LogicBoolReceiverComponent(props)`](#new-logicboolreceivercomponentprops) + - [`LogicBoolReceiverComponent.fromBinary(reader, version)`](#logicboolreceivercomponentfrombinaryreader-version) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`sender`](#sender) +- [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 `LogicBoolReceiverComponent` constructor. + +```ts +type LogicBoolReceiverComponentPropsV1 = { + sender?: number | undefined; +}; + +type LogicBoolReceiverComponentProps = LogicBoolReceiverComponentPropsV1; +``` + +#### Since v1 + +- `sender` (optional, default `0`) `` + +## Constructors + +### `new LogicBoolReceiverComponent(props)` + +Creates a versioned `LogicBoolReceiver` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { LogicBoolReceiverComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicBoolReceiverComponent({ version: componentVersion }); +``` + +--- + +### `LogicBoolReceiverComponent.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) + +--- + +### `sender` + +The identifier of the `LogicBoolSender` that is connected to this `LogicBoolReceiver`. + +- Since: `v1` +- `` + +```ts +import { LogicBoolReceiverComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicBoolReceiverComponent({ version: componentVersion }); + +const sender = component.sender; +// `sender` is `0` +``` + +## 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/LogicBoolSenderComponent.md b/docs/LogicBoolSenderComponent.md new file mode 100644 index 0000000..84ef9af --- /dev/null +++ b/docs/LogicBoolSenderComponent.md @@ -0,0 +1,179 @@ +# Class: `LogicBoolSenderComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#logicboolsendercomponentprops) +- [Constructors](#constructors) + - [`new LogicBoolSenderComponent(props)`](#new-logicboolsendercomponentprops) + - [`LogicBoolSenderComponent.fromBinary(reader, version)`](#logicboolsendercomponentfrombinaryreader-version) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`updatedValue`](#updatedvalue) + - [`changedExternally`](#changedexternally) + - [`identifier`](#identifier) + - [`value`](#value) +- [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 `LogicBoolSenderComponent` constructor. + +```ts +type LogicBoolSenderComponentPropsV2 = { + updatedValue?: number | undefined; + changedExternally?: number | undefined; + identifier?: number | undefined; + value?: boolean | undefined; +}; + +type LogicBoolSenderComponentProps = LogicBoolSenderComponentPropsV2; +``` + +#### Since v2 + +- `updatedValue` (optional, default `3171294583`) `` +- `changedExternally` (optional, default `32`) `` +- `identifier` (optional, default `0`) `` +- `value` (optional, default `false`) `` + +## Constructors + +### `new LogicBoolSenderComponent(props)` + +Creates a versioned `LogicBoolSender` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { LogicBoolSenderComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new LogicBoolSenderComponent({ version: componentVersion }); +``` + +--- + +### `LogicBoolSenderComponent.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) + +--- + +### `updatedValue` + +We're not quite sure what this property does. + +- Since: `v2` +- `` + +```ts +import { LogicBoolSenderComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new LogicBoolSenderComponent({ version: componentVersion }); + +const updatedValue = component.updatedValue; +// `updatedValue` is `3171294583` +``` + +--- + +### `changedExternally` + +We're not quite sure what this property does. + +- Since: `v2` +- `` + +```ts +import { LogicBoolSenderComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new LogicBoolSenderComponent({ version: componentVersion }); + +const changedExternally = component.changedExternally; +// `changedExternally` is `32` +``` + +--- + +### `identifier` + +The identifier of this `LogicBoolSender` that a `LogicBoolReceiver` connects to. + +- Since: `v2` +- `` + +```ts +import { LogicBoolSenderComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new LogicBoolSenderComponent({ version: componentVersion }); + +const identifier = component.identifier; +// `identifier` is `0` +``` + +--- + +### `value` + +The output value of this `LogicBoolSender` that a `LogicBoolReceiver` reads as its input. + +- Since: `v2` +- `` + +```ts +import { LogicBoolSenderComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new LogicBoolSenderComponent({ version: componentVersion }); + +const value = component.value; +// `value` 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/LogicFloatReceiverComponent.md b/docs/LogicFloatReceiverComponent.md new file mode 100644 index 0000000..bb0e615 --- /dev/null +++ b/docs/LogicFloatReceiverComponent.md @@ -0,0 +1,113 @@ +# Class: `LogicFloatReceiverComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#logicfloatreceivercomponentprops) +- [Constructors](#constructors) + - [`new LogicFloatReceiverComponent(props)`](#new-logicfloatreceivercomponentprops) + - [`LogicFloatReceiverComponent.fromBinary(reader, version)`](#logicfloatreceivercomponentfrombinaryreader-version) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`sender`](#sender) +- [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 `LogicFloatReceiverComponent` constructor. + +```ts +type LogicFloatReceiverComponentPropsV1 = { + sender?: number | undefined; +}; + +type LogicFloatReceiverComponentProps = LogicFloatReceiverComponentPropsV1; +``` + +#### Since v1 + +- `sender` (optional, default `0`) `` + +## Constructors + +### `new LogicFloatReceiverComponent(props)` + +Creates a versioned `LogicFloatReceiver` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { LogicFloatReceiverComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicFloatReceiverComponent({ version: componentVersion }); +``` + +--- + +### `LogicFloatReceiverComponent.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) + +--- + +### `sender` + +The identifier of the `LogicFloatSender` that is connected to this `LogicFloatReceiver`. + +- Since: `v1` +- `` + +```ts +import { LogicFloatReceiverComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicFloatReceiverComponent({ version: componentVersion }); + +const sender = component.sender; +// `sender` is `0` +``` + +## 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/LogicFloatSenderComponent.md b/docs/LogicFloatSenderComponent.md new file mode 100644 index 0000000..4130d42 --- /dev/null +++ b/docs/LogicFloatSenderComponent.md @@ -0,0 +1,179 @@ +# Class: `LogicFloatSenderComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#logicfloatsendercomponentprops) +- [Constructors](#constructors) + - [`new LogicFloatSenderComponent(props)`](#new-logicfloatsendercomponentprops) + - [`LogicFloatSenderComponent.fromBinary(reader, version)`](#logicfloatsendercomponentfrombinaryreader-version) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`updatedValue`](#updatedvalue) + - [`changedExternally`](#changedexternally) + - [`identifier`](#identifier) + - [`value`](#value) +- [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 `LogicFloatSenderComponent` constructor. + +```ts +type LogicFloatSenderComponentPropsV1 = { + updatedValue?: number | undefined; + changedExternally?: number | undefined; + identifier?: number | undefined; + value?: float | undefined; +}; + +type LogicFloatSenderComponentProps = LogicFloatSenderComponentPropsV1; +``` + +#### Since v1 + +- `updatedValue` (optional, default `3171294583`) `` +- `changedExternally` (optional, default `32`) `` +- `identifier` (optional, default `0`) `` +- `value` (optional, default `0`) `` + +## Constructors + +### `new LogicFloatSenderComponent(props)` + +Creates a versioned `LogicFloatSender` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { LogicFloatSenderComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicFloatSenderComponent({ version: componentVersion }); +``` + +--- + +### `LogicFloatSenderComponent.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) + +--- + +### `updatedValue` + +We're not quite sure what this property does. + +- Since: `v1` +- `` + +```ts +import { LogicFloatSenderComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicFloatSenderComponent({ version: componentVersion }); + +const updatedValue = component.updatedValue; +// `updatedValue` is `3171294583` +``` + +--- + +### `changedExternally` + +We're not quite sure what this property does. + +- Since: `v1` +- `` + +```ts +import { LogicFloatSenderComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicFloatSenderComponent({ version: componentVersion }); + +const changedExternally = component.changedExternally; +// `changedExternally` is `32` +``` + +--- + +### `identifier` + +The identifier of this `LogicFloatSender` that a `LogicFloatReceiver` connects to. + +- Since: `v1` +- `` + +```ts +import { LogicFloatSenderComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicFloatSenderComponent({ version: componentVersion }); + +const identifier = component.identifier; +// `identifier` is `0` +``` + +--- + +### `value` + +The output value of this `LogicFloatSender` that a `LogicFloatReceiver` reads as its input. + +- Since: `v1` +- `` + +```ts +import { LogicFloatSenderComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicFloatSenderComponent({ version: componentVersion }); + +const value = component.value; +// `value` is `0` +``` + +## 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/LogicGateReceiverComponent.md b/docs/LogicGateReceiverComponent.md new file mode 100644 index 0000000..a256f7b --- /dev/null +++ b/docs/LogicGateReceiverComponent.md @@ -0,0 +1,157 @@ +# Class: `LogicGateReceiverComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#logicgatereceivercomponentprops) +- [Constructors](#constructors) + - [`new LogicGateReceiverComponent(props)`](#new-logicgatereceivercomponentprops) + - [`LogicGateReceiverComponent.fromBinary(reader, version)`](#logicgatereceivercomponentfrombinaryreader-version) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`senders`](#senders) + - [`operationType`](#operationtype) + - [`isInversedOutputSaved`](#isinversedoutputsaved) +- [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 `LogicGateReceiverComponent` constructor. + +```ts +type LogicGateReceiverComponentPropsV2 = { + senders?: number[] | undefined; + operationType?: LogicOperator | undefined; + isInversedOutputSaved?: boolean | undefined; +}; + +type LogicGateReceiverComponentProps = LogicGateReceiverComponentPropsV2; +``` + +#### Since v2 + +- `senders` (optional, default `[]`) `>` +- `operationType` (optional, default `0`) [``](../src/types/LogicOperator.ts) +- `isInversedOutputSaved` (optional, default `false`) `` + +## Constructors + +### `new LogicGateReceiverComponent(props)` + +Creates a versioned `LogicGateReceiver` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { LogicGateReceiverComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new LogicGateReceiverComponent({ version: componentVersion }); +``` + +--- + +### `LogicGateReceiverComponent.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) + +--- + +### `senders` + +The identifiers of the `Logic*Sender` components that are connected to this `LogicGateReceiver`. + +- Since: `v2` +- `>` + +```ts +import { LogicGateReceiverComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new LogicGateReceiverComponent({ version: componentVersion }); + +const senders = component.senders; +// `senders` is `[]` +``` + +--- + +### `operationType` + +The type of operation to perform on the received inputs. + +- Since: `v2` +- [``](../src/types/LogicOperator.ts) + +```ts +import { LogicGateReceiverComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new LogicGateReceiverComponent({ version: componentVersion }); + +const operationType = component.operationType; +// `operationType` is `0` (AND) +``` + +--- + +### `isInversedOutputSaved` + +Whether to inverse the output of this gate. + +- Since: `v2` +- `` + +```ts +import { LogicGateReceiverComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new LogicGateReceiverComponent({ version: componentVersion }); + +const isInversedOutputSaved = component.isInversedOutputSaved; +// `isInversedOutputSaved` 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/LogicIntReceiverComponent.md b/docs/LogicIntReceiverComponent.md new file mode 100644 index 0000000..a8ba0e7 --- /dev/null +++ b/docs/LogicIntReceiverComponent.md @@ -0,0 +1,113 @@ +# Class: `LogicIntReceiverComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#logicintreceivercomponentprops) +- [Constructors](#constructors) + - [`new LogicIntReceiverComponent(props)`](#new-logicintreceivercomponentprops) + - [`LogicIntReceiverComponent.fromBinary(reader, version)`](#logicintreceivercomponentfrombinaryreader-version) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`sender`](#sender) +- [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 `LogicIntReceiverComponent` constructor. + +```ts +type LogicIntReceiverComponentPropsV1 = { + sender?: number | undefined; +}; + +type LogicIntReceiverComponentProps = LogicIntReceiverComponentPropsV1; +``` + +#### Since v1 + +- `sender` (optional, default `0`) `` + +## Constructors + +### `new LogicIntReceiverComponent(props)` + +Creates a versioned `LogicIntReceiver` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { LogicIntReceiverComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicIntReceiverComponent({ version: componentVersion }); +``` + +--- + +### `LogicIntReceiverComponent.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) + +--- + +### `sender` + +The identifier of the `LogicIntSender` that is connected to this `LogicIntReceiver`. + +- Since: `v1` +- `` + +```ts +import { LogicIntReceiverComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicIntReceiverComponent({ version: componentVersion }); + +const sender = component.sender; +// `sender` is `0` +``` + +## 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/LogicIntSenderComponent.md b/docs/LogicIntSenderComponent.md new file mode 100644 index 0000000..bac00c6 --- /dev/null +++ b/docs/LogicIntSenderComponent.md @@ -0,0 +1,179 @@ +# Class: `LogicIntSenderComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#logicintsendercomponentprops) +- [Constructors](#constructors) + - [`new LogicIntSenderComponent(props)`](#new-logicintsendercomponentprops) + - [`LogicIntSenderComponent.fromBinary(reader, version)`](#logicintsendercomponentfrombinaryreader-version) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`updatedValue`](#updatedvalue) + - [`changedExternally`](#changedexternally) + - [`identifier`](#identifier) + - [`value`](#value) +- [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 `LogicIntSenderComponent` constructor. + +```ts +type LogicIntSenderComponentPropsV1 = { + updatedValue?: number | undefined; + changedExternally?: number | undefined; + identifier?: number | undefined; + value?: number | undefined; +}; + +type LogicIntSenderComponentProps = LogicIntSenderComponentPropsV1; +``` + +#### Since v1 + +- `updatedValue` (optional, default `3171294583`) `` +- `changedExternally` (optional, default `32`) `` +- `identifier` (optional, default `0`) `` +- `value` (optional, default `false`) `` + +## Constructors + +### `new LogicIntSenderComponent(props)` + +Creates a versioned `LogicIntSender` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { LogicIntSenderComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicIntSenderComponent({ version: componentVersion }); +``` + +--- + +### `LogicIntSenderComponent.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) + +--- + +### `updatedValue` + +We're not quite sure what this property does. + +- Since: `v1` +- `` + +```ts +import { LogicIntSenderComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicIntSenderComponent({ version: componentVersion }); + +const updatedValue = component.updatedValue; +// `updatedValue` is `3171294583` +``` + +--- + +### `changedExternally` + +We're not quite sure what this property does. + +- Since: `v1` +- `` + +```ts +import { LogicIntSenderComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicIntSenderComponent({ version: componentVersion }); + +const changedExternally = component.changedExternally; +// `changedExternally` is `32` +``` + +--- + +### `identifier` + +The identifier of this `LogicIntSender` that a `LogicIntReceiver` connects to. + +- Since: `v1` +- `` + +```ts +import { LogicIntSenderComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicIntSenderComponent({ version: componentVersion }); + +const identifier = component.identifier; +// `identifier` is `0` +``` + +--- + +### `value` + +The output value of this `LogicIntSender` that a `LogicIntReceiver` reads as its input. + +- Since: `v1` +- `` + +```ts +import { LogicIntSenderComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicIntSenderComponent({ version: componentVersion }); + +const value = component.value; +// `value` is `0` +``` + +## 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/LogicVector3ReceiverComponent.md b/docs/LogicVector3ReceiverComponent.md new file mode 100644 index 0000000..0708e88 --- /dev/null +++ b/docs/LogicVector3ReceiverComponent.md @@ -0,0 +1,113 @@ +# Class: `LogicVector3ReceiverComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#logicvector3receivercomponentprops) +- [Constructors](#constructors) + - [`new LogicVector3ReceiverComponent(props)`](#new-logicvector3receivercomponentprops) + - [`LogicVector3ReceiverComponent.fromBinary(reader, version)`](#logicvector3receivercomponentfrombinaryreader-version) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`sender`](#sender) +- [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 `LogicVector3ReceiverComponent` constructor. + +```ts +type LogicVector3ReceiverComponentPropsV1 = { + sender?: number | undefined; +}; + +type LogicVector3ReceiverComponentProps = LogicVector3ReceiverComponentPropsV1; +``` + +#### Since v1 + +- `sender` (optional, default `0`) `` + +## Constructors + +### `new LogicVector3ReceiverComponent(props)` + +Creates a versioned `LogicVector3Receiver` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { LogicVector3ReceiverComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicVector3ReceiverComponent({ version: componentVersion }); +``` + +--- + +### `LogicVector3ReceiverComponent.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) + +--- + +### `sender` + +The identifier of the `LogicVector3Sender` that is connected to this `LogicVector3Receiver`. + +- Since: `v1` +- `` + +```ts +import { LogicVector3ReceiverComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicVector3ReceiverComponent({ version: componentVersion }); + +const sender = component.sender; +// `sender` is `0` +``` + +## 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/LogicVector3SenderComponent.md b/docs/LogicVector3SenderComponent.md new file mode 100644 index 0000000..7903e68 --- /dev/null +++ b/docs/LogicVector3SenderComponent.md @@ -0,0 +1,179 @@ +# Class: `LogicVector3SenderComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#logicvector3sendercomponentprops) +- [Constructors](#constructors) + - [`new LogicVector3SenderComponent(props)`](#new-logicvector3sendercomponentprops) + - [`LogicVector3SenderComponent.fromBinary(reader, version)`](#logicvector3sendercomponentfrombinaryreader-version) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`updatedValue`](#updatedvalue) + - [`changedExternally`](#changedexternally) + - [`identifier`](#identifier) + - [`value`](#value) +- [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 `LogicVector3SenderComponent` constructor. + +```ts +type LogicVector3SenderComponentPropsV1 = { + updatedValue?: number | undefined; + changedExternally?: number | undefined; + identifier?: number | undefined; + value?: vector3ean | undefined; +}; + +type LogicVector3SenderComponentProps = LogicVector3SenderComponentPropsV1; +``` + +#### Since v1 + +- `updatedValue` (optional, default `3171294583`) `` +- `changedExternally` (optional, default `32`) `` +- `identifier` (optional, default `0`) `` +- `value` (optional, default `{ x: 0, y: 0, z: 0 }`) `` + +## Constructors + +### `new LogicVector3SenderComponent(props)` + +Creates a versioned `LogicVector3Sender` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { LogicVector3SenderComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicVector3SenderComponent({ version: componentVersion }); +``` + +--- + +### `LogicVector3SenderComponent.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) + +--- + +### `updatedValue` + +We're not quite sure what this property does. + +- Since: `v1` +- `` + +```ts +import { LogicVector3SenderComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicVector3SenderComponent({ version: componentVersion }); + +const updatedValue = component.updatedValue; +// `updatedValue` is `3171294583` +``` + +--- + +### `changedExternally` + +We're not quite sure what this property does. + +- Since: `v1` +- `` + +```ts +import { LogicVector3SenderComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicVector3SenderComponent({ version: componentVersion }); + +const changedExternally = component.changedExternally; +// `changedExternally` is `32` +``` + +--- + +### `identifier` + +The identifier of this `LogicVector3Sender` that a `LogicVector3Receiver` connects to. + +- Since: `v1` +- `` + +```ts +import { LogicVector3SenderComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicVector3SenderComponent({ version: componentVersion }); + +const identifier = component.identifier; +// `identifier` is `0` +``` + +--- + +### `value` + +The output value of this `LogicVector3Sender` that a `LogicVector3Receiver` reads as its input. + +- Since: `v1` +- `` + +```ts +import { LogicVector3SenderComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new LogicVector3SenderComponent({ version: componentVersion }); + +const value = component.value; +// `value` is `{ x: 0, y: 0, z: 0 }` +``` + +## 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/NetworkRigidbodyComponent.md b/docs/NetworkRigidbodyComponent.md new file mode 100644 index 0000000..eb44a70 --- /dev/null +++ b/docs/NetworkRigidbodyComponent.md @@ -0,0 +1,219 @@ +# Class: `NetworkRigidbodyComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#networkrigidbodycomponentprops) +- [Constructors](#constructors) + - [`new NetworkRigidbodyComponent(props)`](#new-networkrigidbodycomponentprops) + - [`NetworkRigidbodyComponent.fromBinary(reader, version)`](#networkrigidbodycomponentfrombinaryreader-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 `NetworkRigidbodyComponent` constructor. + +```ts +type NetworkRigidbodyComponentPropsV1 = { + position?: Position | undefined; + rotation?: Rotation | undefined; + isKinematic?: boolean | undefined; + isServerSleeping?: boolean | undefined; + velocity?: Velocity | undefined; + angularVelocity?: AngularVelocity | undefined; +}; + +type NetworkRigidbodyComponentProps = NetworkRigidbodyComponentPropsV1; +``` + +#### Since v1 + +- `position` (optional, default `{ x: 0, y: 0, z: 0 }`) [``](../src/types/Position.ts) +- `rotation` (optional, default `{ x: 0, y: 0, z: 0, w: 1 }`) [``](../src/types/Rotation.ts) +- `isKinematic` (optional, default `false`) `` +- `isServerSleeping` (optional, default `false`) `` +- `velocity` (optional, default `{ x: 0, y: 0, z: 0 }`) [``](../src/types/Velocity.ts) +- `angularVelocity` (optional, default `{ x: 0, y: 0, z: 0 }`) [``](../src/types/AngularVelocity.ts) + +## Constructors + +### `new NetworkRigidbodyComponent(props)` + +Creates a versioned `NetworkRigidbody` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { NetworkRigidbodyComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new NetworkRigidbodyComponent({ version: componentVersion }); +``` + +--- + +### `NetworkRigidbodyComponent.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) + +--- + +### `position` + +Position of the prefab this component is attached to. + +- Since: `v1` +- [``](../src/types/Position.ts) + +```ts +import { NetworkRigidbodyComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new NetworkRigidbodyComponent({ version: componentVersion }); + +const position = component.position; +// `position` is `{ x: 0, y: 0, z: 0 }` +``` + +--- + +### `rotation` + +Rotation of the prefab this component is attached to. + +- Since: `v1` +- [``](../src/types/Rotation.ts) + +```ts +import { NetworkRigidbodyComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new NetworkRigidbodyComponent({ version: componentVersion }); + +const rotation = component.rotation; +// `rotation` is `{ x: 0, y: 0, z: 0, w: 1 }` +``` + +--- + +### `isKinematic` + +Whether the prefab this component is attached to is [kinematic](https://docs.unity3d.com/ScriptReference/Rigidbody-isKinematic.html) or not. + +- Since: `v1` +- `` + +```ts +import { NetworkRigidbodyComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new NetworkRigidbodyComponent({ version: componentVersion }); + +const isKinematic = component.isKinematic; +// `isKinematic` is `false` +``` + +--- + +### `isServerSleeping` + +Whether the prefab this component is attached to is [sleeping](https://docs.unity3d.com/Manual/RigidbodiesOverview.html) or not. + +- Since: `v1` +- `` + +```ts +import { NetworkRigidbodyComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new NetworkRigidbodyComponent({ version: componentVersion }); + +const isServerSleeping = component.isServerSleeping; +// `isServerSleeping` is `false` +``` + +--- + +### `velocity` + +Velocity of the prefab this component is attached to. + +- Since: `v1` +- [``](../src/types/Velocity.ts) + +```ts +import { NetworkRigidbodyComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new NetworkRigidbodyComponent({ version: componentVersion }); + +const velocity = component.velocity; +// `velocity` is `{ x: 0, y: 0, z: 0 }` +``` + +--- + +### `angularVelocity` + +Angular velocity of the prefab this component is attached to. + +- Since: `v1` +- [``](../src/types/AngularVelocity.ts) + +```ts +import { NetworkRigidbodyComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new NetworkRigidbodyComponent({ version: componentVersion }); + +const angularVelocity = component.angularVelocity; +// `angularVelocity` is `{ x: 0, y: 0, z: 0 }` +``` + +## 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/PhysicalMaterialPartComponent.md b/docs/PhysicalMaterialPartComponent.md new file mode 100644 index 0000000..0f04e15 --- /dev/null +++ b/docs/PhysicalMaterialPartComponent.md @@ -0,0 +1,113 @@ +# Class: `PhysicalMaterialPartComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#physicalmaterialpartcomponentprops) +- [Constructors](#constructors) + - [`new PhysicalMaterialPartComponent(props)`](#new-physicalmaterialpartcomponentprops) + - [`PhysicalMaterialPartComponent.fromBinary(reader, version)`](#physicalmaterialpartcomponentfrombinaryreader-version) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`materialHash`](#materialhash) +- [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 `PhysicalMaterialPartComponent` constructor. + +```ts +type PhysicalMaterialPartComponentPropsV1 = { + materialHash?: number | undefined; +}; + +type PhysicalMaterialPartComponentProps = PhysicalMaterialPartComponentPropsV1; +``` + +#### Since v1 + +- `materialHash` (optional, default `1`) [``](../src/types/PhysicalMaterialPartHash.ts) + +## Constructors + +### `new PhysicalMaterialPartComponent(props)` + +Creates a versioned `PhysicalMaterialPart` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { PhysicalMaterialPartComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new PhysicalMaterialPartComponent({ version: componentVersion }); +``` + +--- + +### `PhysicalMaterialPartComponent.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) + +--- + +### `materialHash` + +The hash of the physical material of the prefab this component is attached to. + +- Since: `v1` +- [``](../src/types/PhysicalMaterialPartHash.ts) + +```ts +import { PhysicalMaterialPartComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new PhysicalMaterialPartComponent({ version: componentVersion }); + +const materialHash = component.materialHash; +// `materialHash` 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/PickupComponent.md b/docs/PickupComponent.md new file mode 100644 index 0000000..84e7ecc --- /dev/null +++ b/docs/PickupComponent.md @@ -0,0 +1,151 @@ +# Class: `PickupComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#pickupcomponentprops) +- [Constructors](#constructors) + - [`new PickupComponent(props)`](#new-pickupcomponentprops) + - [`PickupComponent.fromBinary(reader, version)`](#pickupcomponentfrombinaryreader-version) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`lastInteractorPlayerId`](#lastinteractorplayerid) + - [`dockedMemory`](#dockedmemory) +- [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 `PickupComponent` constructor. + +```ts +type GrabPointParameters = null | { + grabPointIndex: number; + lastLinearPosition: number; + lastPosition: Position; + lastRotation: Rotation; +}; + +type PickupComponentPropsV1 = { + lastInteractorPlayerId?: number | undefined; + dockedMemory?: never; +}; + +type PickupComponentPropsV2 = { + lastInteractorPlayerId?: number | undefined; + dockedMemory?: GrabPointParameters[] | undefined; +}; + +type PickupComponentProps = PickupComponentPropsV1 | PickupComponentPropsV2; +``` + +#### Since v1 + +- `lastInteractorPlayerId` (optional, default `0`) `` + +#### Since v2 + +- `lastInteractorPlayerId` (optional, default `0`) `` +- `dockedMemory` (optional, default `[]`) `>` + +## Constructors + +### `new PickupComponent(props)` + +Creates a versioned `Pickup` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { PickupComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new PickupComponent({ version: componentVersion }); +``` + +--- + +### `PickupComponent.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) + +--- + +### `lastInteractorPlayerId` + +The ID of the player that last interacted with the prefab that this component is attached to. + +- Since: `v1` +- `` + +```ts +import { PickupComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new PickupComponent({ version: componentVersion }); + +const lastInteractorPlayerId = component.lastInteractorPlayerId; +// `lastInteractorPlayerId` is `0` +``` + +--- + +### `dockedMemory` + +An array of `` that describes the orientation of prefabs when they were docked. Used to control in which orientation pickups should be held when grabbed from the dock attached to the same prefab this component is attached to. + +- Since: `v2` +- `` + +```ts +import { PickupComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new PickupComponent({ version: componentVersion }); + +const dockedMemory = component.dockedMemory; +// `dockedMemory` is `[]` +``` + +## 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/PickupDockComponent.md b/docs/PickupDockComponent.md new file mode 100644 index 0000000..a47bb73 --- /dev/null +++ b/docs/PickupDockComponent.md @@ -0,0 +1,151 @@ +# Class: `PickupDockComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#pickupdockcomponentprops) +- [Constructors](#constructors) + - [`new PickupDockComponent(props)`](#new-pickupdockcomponentprops) + - [`PickupDockComponent.fromBinary(reader, version)`](#pickupdockcomponentfrombinaryreader-version) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`dockedTypeHash`](#dockedtypehash) + - [`quantity`](#quantity) + - [`childIndex`](#childindex) +- [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 `PickupDockComponent` constructor. + +```ts +type PickupDockComponentPropsV2 = { + dockedTypeHash?: number | undefined; + quantity?: number | undefined; + childIndex?: number | undefined; +}; + +type PickupDockComponentProps = PickupDockComponentPropsV2; +``` + +#### Since v2 + +- `dockedTypeHash` (optional, default `0`) `` +- `quantity` (optional, default `1`) `` +- `childIndex` (optional, default `0`) `` + +## Constructors + +### `new PickupDockComponent(props)` + +Creates a versioned `PickupDock` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { PickupDockComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new PickupDockComponent({ version: componentVersion }); +``` + +--- + +### `PickupDockComponent.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) + +--- + +### `dockedTypeHash` + +- Since: `v2` +- `` + +```ts +import { PickupDockComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new PickupDockComponent({ version: componentVersion }); + +const dockedTypeHash = component.dockedTypeHash; +// `dockedTypeHash` is `0` +``` + +--- + +### `quantity` + +- Since: `v2` +- `` + +```ts +import { PickupDockComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new PickupDockComponent({ version: componentVersion }); + +const quantity = component.quantity; +// `quantity` is `1` +``` + +--- + +### `childIndex` + +- Since: `v2` +- `` + +```ts +import { PickupDockComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new PickupDockComponent({ version: componentVersion }); + +const childIndex = component.childIndex; +// `childIndex` is `0` +``` + +## 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/PopulationSpawnAreaComponent.md b/docs/PopulationSpawnAreaComponent.md new file mode 100644 index 0000000..439fe0c --- /dev/null +++ b/docs/PopulationSpawnAreaComponent.md @@ -0,0 +1,288 @@ +# Class: `PopulationSpawnAreaComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#populationspawnareacomponentprops) +- [Constructors](#constructors) + - [`new PopulationSpawnAreaComponent(props)`](#new-populationspawnareacomponentprops) + - [`PopulationSpawnAreaComponent.fromBinary(reader, version)`](#populationspawnareacomponentfrombinaryreader-version) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`definition`](#definition) + - [`isPopulationStarted`](#ispopulationstarted) + - [`children`](#children) + - [`maxPopulation`](#maxpopulation) + - [`currentPopulation`](#currentpopulation) + - [`checkPopulationTime`](#checkpopulationtime) + - [`numberOfSpawnPoints`](#numberofspawnpoints) + - [`startingPopulation`](#startingpopulation) + - [`isOneOff`](#isoneoff) +- [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 `PopulationSpawnAreaComponent` constructor. + +```ts +type PopulationSaveDataChild = null | { + index: number; + pointIndex: number; +}; + +type PopulationSpawnAreaComponentPropsV2 = { + definition?: number | undefined; + isPopulationStarted?: boolean | undefined; + children?: PopulationSaveDataChild[] | undefined; + maxPopulation?: number | undefined; + currentPopulation?: number | undefined; + checkPopulationTime?: number | undefined; + numberOfSpawnPoints?: number | undefined; + startingPopulation?: number | undefined; + isOneOff?: boolean | undefined; +}; + +type PopulationSpawnAreaComponentProps = PopulationSpawnAreaComponentPropsV2; +``` + +#### Since v2 + +- `definition` (optional, default `30040`) [``](../src/types/PopulationDefinitionHash.ts) +- `isPopulationStarted` (optional, default `true`) `` +- `children` (optional, default `[]`) `>` +- `maxPopulation` (optional, default `20`) `` +- `currentPopulation` (optional, default `5`) `` +- `checkPopulationTime` (optional, default `852974979330`) `` +- `numberOfSpawnPoints` (optional, default `40`) `` +- `startingPopulation` (optional, default `5`) `` +- `isOneOff` (optional, default `false`) `` + +## Constructors + +### `new PopulationSpawnAreaComponent(props)` + +Creates a versioned `PopulationSpawnArea` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { PopulationSpawnAreaComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new PopulationSpawnAreaComponent({ version: componentVersion }); +``` + +--- + +### `PopulationSpawnAreaComponent.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) + +--- + +### `definition` + +The hash of the population to spawn in the `SpawnArea` component that is attached to the same prefab this component is attached to. + +- Since: `v2` +- [``](../src/types/PopulationDefinitionHash.ts) + +```ts +import { PopulationSpawnAreaComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new PopulationSpawnAreaComponent({ version: componentVersion }); + +const definition = component.definition; +// `definition` is `30040` +``` + +--- + +### `isPopulationStarted` + +- Since: `v2` +- `` + +```ts +import { PopulationSpawnAreaComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new PopulationSpawnAreaComponent({ version: componentVersion }); + +const isPopulationStarted = component.isPopulationStarted; +// `isPopulationStarted` is `true` +``` + +--- + +### `children` + +- Since: `v2` +- `>` + +```ts +import { PopulationSpawnAreaComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new PopulationSpawnAreaComponent({ version: componentVersion }); + +const children = component.children; +// `children` is `[]` +``` + +--- + +### `maxPopulation` + +The maximum amount of spawned prefabs in this population. + +- Since: `v2` +- `` + +```ts +import { PopulationSpawnAreaComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new PopulationSpawnAreaComponent({ version: componentVersion }); + +const maxPopulation = component.maxPopulation; +// `maxPopulation` is `20` +``` + +--- + +### `currentPopulation` + +The current amount of spawned prefabs in this population. + +- Since: `v2` +- `` + +```ts +import { PopulationSpawnAreaComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new PopulationSpawnAreaComponent({ version: componentVersion }); + +const currentPopulation = component.currentPopulation; +// `currentPopulation` is `5` +``` + +--- + +### `checkPopulationTime` + +- Since: `v2` +- `` + +```ts +import { PopulationSpawnAreaComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new PopulationSpawnAreaComponent({ version: componentVersion }); + +const checkPopulationTime = component.checkPopulationTime; +// `checkPopulationTime` is `852974979330` +``` + +--- + +### `numberOfSpawnPoints` + +The amount of spawn locations inside the `SpawnArea` component that is attached to the same prefab this component is attached to. + +- Since: `v2` +- `` + +```ts +import { PopulationSpawnAreaComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new PopulationSpawnAreaComponent({ version: componentVersion }); + +const numberOfSpawnPoints = component.numberOfSpawnPoints; +// `numberOfSpawnPoints` is `40` +``` + +--- + +### `startingPopulation` + +The amount of spawned prefabs that this population begins with. + +- Since: `v2` +- `` + +```ts +import { PopulationSpawnAreaComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new PopulationSpawnAreaComponent({ version: componentVersion }); + +const startingPopulation = component.startingPopulation; +// `startingPopulation` is `5` +``` + +--- + +### `isOneOff` + +Whether any removed prefabs from this population shouldn't be replaced after the server's respawn timer has elapsed. + +- Since: `v2` +- `` + +```ts +import { PopulationSpawnAreaComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new PopulationSpawnAreaComponent({ version: componentVersion }); + +const isOneOff = component.isOneOff; +// `isOneOff` 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/Prefab.md b/docs/Prefab.md new file mode 100644 index 0000000..6a170f3 --- /dev/null +++ b/docs/Prefab.md @@ -0,0 +1,1211 @@ +# Class: `Prefab` + +- [Types](#types) + - [``](#prefabprops) +- [Constructors](#constructors) + - [`new Prefab(prefabName, props?)`](#new-prefabprefabname-props) + - [`Prefab.fromBinary(reader, componentVersions?)`](#prefabfrombinaryreader-componentversions) + - [`Prefab.fromSaveString(saveString)`](#prefabfromsavestringsavestring) +- [Properties](#properties) + - [`name`](#name) + - [`hash`](#hash) + - [`position`](#position) + - [`rotation`](#rotation) + - [`scale`](#scale) + - [`components`](#components) + - [`entities`](#entities) + - [`children`](#children) +- [Methods](#methods) + - [`addChildPrefab(parentKey, childPrefab)`](#addchildprefabparentkey-childprefab) + - [`addComponent(component)`](#addcomponentcomponent) + - [`addEntity(entity)`](#addentityentity) + - [`addGift(giftPrefab)`](#addgiftgiftprefab) + - [`clone(options?)`](#cloneoptions) + - [`getAngularVelocity()`](#getangularvelocity) + - [`getChildPrefab(prefabName, parentHash?)`](#getchildprefabprefabname-parenthash) + - [`getComponentVersions()`](#getcomponentversions) + - [`getGiftBoxLabel()`](#getgiftboxlabel) + - [`getIntegrity()`](#getintegrity) + - [`getKinematic()`](#getkinematic) + - [`getMaterial()`](#getmaterial) + - [`getOnFire()`](#getonfire) + - [`getPosition()`](#getposition) + - [`getRotation()`](#getrotation) + - [`getScale()`](#getscale) + - [`getServerSleeping()`](#getserversleeping) + - [`getServings()`](#getservings) + - [`getSpawnAreaPopulationName()`](#getspawnareapopulationname) + - [`getVelocity()`](#getvelocity) + - [`inspect()`](#inspect) + - [`print()`](#print) + - [`removeAllChildPrefabs()`](#removeallchildprefabs) + - [`removeAllComponents()`](#removeallcomponents) + - [`removeAllEntities()`](#removeallentities) + - [`removeAllGifts()`](#removeallgifts) + - [`removeChildPrefab(prefabArg)`](#removechildprefabprefabarg) + - [`removeComponent(componentArg)`](#removecomponentcomponentarg) + - [`removeEntity(entityKey)`](#removeentityentitykey) + - [`removeGift(prefabHash)`](#removegiftprefabhash) + - [`removeSpawnArea()`](#removespawnarea) + - [`setAngularVelocity(angularVelocity)`](#setangularvelocityangularvelocity) + - [`setGiftBoxLabel(label)`](#setgiftboxlabellabel) + - [`setIntegrity(integrity)`](#setintegrityintegrity) + - [`setKinematic(isKinematic?)`](#setkinematiciskinematic) + - [`setMaterial(materialArg)`](#setmaterialmaterialarg) + - [`setOnFire(isLit?)`](#setonfireislit) + - [`setPosition(position)`](#setpositionposition) + - [`setRotation(rotation)`](#setrotationrotation) + - [`setScale(scale)`](#setscalescale) + - [`setServerSleeping(isServerSleeping?)`](#setserversleepingisserversleeping) + - [`setServings(servings)`](#setservingsservings) + - [`setSpawnArea(populationDefinitionArg, props?)`](#setspawnareapopulationarg-props) + - [`setVelocity(velocity)`](#setvelocityvelocity) + - [`toBinary(componentVersions)`](#tobinarycomponentversions) + - [`toSaveString(options?)`](#tosavestringoptions) + +## Types + +### `` + +A configuration object to optionally pass to the `Prefab` constructor. Lets you instantiate a `Prefab` with predefined data. Any properties that you do not pass will be created with a default value. + +```ts +type PrefabProps = { + position?: Position | undefined; + rotation?: Rotation | undefined; + scale?: number | undefined; + components?: Partial | undefined; + entities?: Partial> | undefined; + children?: PrefabChild[] | undefined; +}; +``` + +- `position` (optional) [``](../src/types/Position.ts) The world position 3D vector coordinates of the prefab. +- `rotation` (optional) [``](../src/types/Rotation.ts) The world rotation quaternion of the prefab. +- `scale` (optional) `` The scale of the prefab. +- `components` (optional) `>` A mapped object of components on the prefab. +- `entities` (optional) `>>` A mapped object of entities on the prefab. +- `children` (optional) `>` An array of objects connecting child prefabs with parent entities. + +## Constructors + +### `new Prefab(prefabName, props?)` + +Creates a new `Prefab` object configured with the passed in configuration. + +- `prefabName` [``](./ATTPrefabName.md) The name of the prefab to create. +- `props` (optional) [``](#prefabprops) Additional configuration of the prefab to create. +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Wooden_Stake', { + position: { x: 133.7, y: 420, z: 69 }, + rotation: { x: 0.3, y: 0.4, z: 0.1, w: 0.8 }, + scale: 1.5, + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ + version: 1, + position: { x: 133.7, y: 420, z: 69 }, + rotation: { x: 0.3, y: 0.4, z: 0.1, w: 0.8 }, + isKinematic: false, + isServerSleeping: false, + velocity: { x: 0, y: 1, z: 0 }, + angularVelocity: { x: 0, y: 1, z: 0 } + }) + }, + entities: { + Slot_Multi_11474: new Entity('Slot_Multi_11474') + }, + children: [ + { + parentHash: 11474, + prefab: new Prefab('Grass_Clump', { + entities: { + Fire_30100: new Entity('Fire_30100', { + components: { + HeatSourceBase: new HeatSourceBaseComponent({ + version: 2, + isLit: true, + progress: 0.8 + }) + } + }) + } + }) + } + ] +}); +``` + +--- + +### `Prefab.fromBinary(reader, componentVersions?)` + +Creates a `Prefab` from reading the prefab's binary data stored in a [``](./SaveString.md). + +- `reader` [``](./BinaryReader.md) The binary reader that contains the data stored inside an ATT save string. +- `componentVersions` (optional) `>` A map of component versions to assume are encoded in the binary data. +- Returns: `` + +```ts +import { BinaryReader, ComponentHash, Prefab, type BinaryString } from 'att-string-transcoder'; + +const binaryString = `0000000000000000101001001111011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111100000000000000000000000001111111000000000000000000000000101011010110001000000111011011000000000000000000000000001000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000`; + +const reader = new BinaryReader(binaryString as BinaryString); + +const componentVersions = new Map([ + [ComponentHash.NetworkRigidbody, 1], + [ComponentHash.PhysicalMaterialPart, 1], + [ComponentHash.Pickup, 1] + // etc... +]); + +const prefab = Prefab.fromBinary<'Handle_Short'>(reader, componentVersions); +``` + +--- + +### `Prefab.fromSaveString(saveString)` + +Creates a `Prefab` from reading an ATT save string. + +- `saveString` `` The ATT save string to decode into a `Prefab`. +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const saveString = `43430,230,43430,3290698471,1125743666,1132721897,1050703933,3208373430,1039090831,1058493384,1043542835,2290978823,418,3290698471,1125743666,1132721897,1050703933,3208373430,1039090831,1058493384,3221225472,0,0,0,0,0,363610349,2147483736,3005828291,3221225472,2415919104,0,395228240,397619388,393508864,400941080,2546407302,4157020038,3890602430,1579755829,536870916,374086096,2147483844,1610612736,765,2684354569,338752663,2281701377,0,0,19021736,1744830465,67108864,75722752,0,303,67108864,1124073472,0,0,`; + +const prefab = Prefab.fromSaveString<'SpriggullDrumstick_Full_Ripe'>(saveString); +``` + +## Properties + +Note that the following properties are sorted in order of appearance when decoding an ATT prefab save string. + +### `name` + +:warning: This property does not occur when decoding an ATT prefab save string but is added by _ATT String Transcoder_ for your convenience when inspecting prefab structures. + +- [``](./ATTPrefabName.md) The name of the prefab. + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Handle_Short'); + +const name = prefab.name; +// `name` is `'Handle_Short'` +``` + +### `hash` + +The prefab's hash is a unique numeric identifier for the _type_ of prefab. Every `Handle_Short` in the game will have the same prefab ID. This is not to be confused with a "network ID", which is a unique identifier the game server assigns to each individual object in the game. + +- [``](./ATTPrefabHash.md) The hash of the prefab. + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Handle_Short'); + +const hash = prefab.hash; +// `hash` is `42230` +``` + +### `position` + +:warning: Note that although you can safely read from this public property, you should not modify this property directly. This is because some prefabs also use a [`NetworkRigidbodyComponent`](./NetworkRigidbodyComponent.md) to control their position. You can safely set the position of a prefab using the [`setPosition(position)`](#setpositionposition) method. + +- [``](../src/types/Position.ts) The position of the prefab. + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Handle_Short', { + position: { x: 420, y: 69, z: 1337 } +}); + +const position = prefab.position; +// `position` is `{ x: 420, y: 69, z: 1337 }` +``` + +--- + +### `rotation` + +:warning: Note that although you can safely read from this public property, you should not modify this property directly. This is because some prefabs also use a [`NetworkRigidbodyComponent`](./NetworkRigidbodyComponent.md) to control their rotation. You can safely set the rotation of a prefab using the [`setRotation(rotation)`](#setrotationrotation) method. + +- [``](../src/types/Rotation.ts) The rotation of the prefab. + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Handle_Short', { + rotation: { x: 0.42, y: -0.69, z: -0.1337, w: 0.88 } +}); + +const rotation = prefab.rotation; +// `rotation` is `{ x: 0.42, y: -0.69, z: -0.1337, w: 0.88 }` +``` + +--- + +### `scale` + +Contains the scale of the prefab. You can also set the scale of a prefab using the [`setScale(scale)`](#setscalescale) method. + +- `` The scale of the prefab. + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Handle_Short', { + scale: 0.69 +}); + +const scale = prefab.scale; +// `scale` is approx. `0.69` (within JavaScript floating point precision) +``` + +--- + +### `components` + +Provides access to the components stored in this prefab. Components are keyed to their respective names, unless its data contained an unrecognised hash. In that case, the component will be stored in an array under the `Unknown` key. + +:bulb: It might be easier to add components using the [`addComponent(component)`](#addcomponentcomponent) method. + +- [``](../src/types/PrefabComponents.ts) A map of the stored components. + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Handle_Short', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ version: 1 }) + } +}); + +const components = prefab.components; +// `components` is `{ +// NetworkRigidbody: NetworkRigidbodyComponent { +// hash: 2290978823, +// name: 'NetworkRigidbody', +// position: { x: 0, y: 0, z: 0 }, +// rotation: { x: 0, y: 0, z: 0, w: 1 }, +// isKinematic: false, +// isServerSleeping: false, +// velocity: { x: 0, y: 0, z: 0 }, +// angularVelocity: { x: 0, y: 0, z: 0 } +// }, +// Unknown: [] +// }` +``` + +--- + +### `entities` + +Provides access to the entities stored in this prefab. Entities are keyed to a combination of their respective names and hashes, unless its data contained an unrecognised hash. In that case, the entity will be keyed as `Unknown_` followed by its hash. The reason that entities cannot be keyed without their hashes (like [components](#components)) is because some prefabs have multiple entities with the same name. For example, the `Handle_Fist` prefab has several `Slot_Deco` entities that are only differentiated by their hash. Conversely, it's also possible that an entity exists on different prefabs with the same name but different hashes. For example, the `Fire` entity exists on the `Infinite_Fire` prefab with hash `8488`, but exists on the `Grass_Clump` prefab with hash `30100`. For this reason, _ATT String Transcoder_ uses spawn infodumps from the game to figure out which entities belong to which prefabs and uses this data to provide you with auto-complete options. + +:warning: Unfortunately this means that it's not easy to tell upfront which hash a `Fire` entity has on a prefab that you're building. Please ensure that you assign a key that is identical to the entity key (which is name, underscore, and hash). + +:bulb: It might be easier to add entities using the [`addEntity(entity)`](#addentityentity) method. + +- [`>`](../src/types/PrefabEntities.ts) A map of the stored entities. + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Handle_Short', { + entities: { + // Please note the keys include the hash, not just the name. + Slot_Multi_6136: new Entity('Slot_Multi_6136'), + Slot_Multi_6138: new Entity('Slot_Multi_6138'), + Unknown_1337: new Entity('Unknown', { hash: 1337 }) + } +}); + +const entities = prefab.entities; +// `entities` is `{ +// Slot_Multi_6136: Entity { +// hash: 6136, +// name: 'Slot_Multi', +// isAlive: true, +// components: { Unknown: [] } +// }, +// Slot_Multi_6138: Entity { +// hash: 6138, +// name: 'Slot_Multi', +// isAlive: true, +// components: { Unknown: [] } +// }, +// Unknown_1337: Entity { +// hash: 1337, +// name: 'Unknown', +// isAlive: true, +// components: { Unknown: [] } +// }, +// }` +``` + +--- + +### `children` + +Contains an array of objects that map nested prefabs to entities on the current prefab. + +:warning: Note that the entity _does not need to exist_ in the prefab in your program! The ATT game server will fill in the blanks. For example, if you create a save string for a `Handle_Short` prefab with several children and no entities on it, and spawn it in-game, it will in fact have all its usual entities to which child prefabs can attach. + +:bulb: It might be easier to add child prefabs using the [`addChildPrefab(parentKey, childPrefab)`](#addchildprefabparentkey-childprefab) method. + +- [``](../src/types/PrefabChild.ts) An array of the stored child prefabs. + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Handle_Short', { + children: [ + { + // Please note the entity hash below wasn't defined elsewhere in this prefab, yet this will work when spawned in-game. + parentHash: 6136, // The hash for `Slot_Multi_6136` on `Handle_Short` prefab. + prefab: new Prefab('Guard') + } + ] +}); + +const children = prefab.children; +// `children` is `[ +// { +// parentHash: 6136, +// prefab: Prefab { +// name: 'Guard', +// hash: 51672, +// position: { x: 0, y: 0, z: 0 }, +// rotation: { x: 0, y: 0, z: 0, w: 1 } +// scale: 1, +// components: { Unknown: [] }, +// entities: {}, +// children: [] +// } +// } +// ]` +``` + +## Methods + +### `addChildPrefab(parentKey, childPrefab)` + +Attaches a `Prefab` to this prefab as a child. It can optionally be attached onto one of this prefab's embedded entities, which is required for most child prefabs under normal circumstances. If you do not specify a `parentKey`, you may pass `null` to create a "floating" child. It will be part of this prefab's hierarchy but will most likely behave unexpectedly in the game. + +- `parentKey` ``](../src/types/EntityKey.ts)`, 'Unknown'> | null>` The key of the prefab's entity to which you want to attach the `childPrefab`. +- `childPrefab` `` The prefab you want to attach as a child. +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const parent = new Prefab('Handle_Short'); +const child = new Prefab('Guard'); + +parent.addChildPrefab('Slot_Large_SwordType_Craft_54356', child); +``` + +--- + +### `addComponent(component)` + +Adds a `Component` to the prefab. Will override any existing component with that name. + +- `component` [``](./Component.md) The component to set on the prefab. +- Returns: `` + +```ts +import { NetworkRigidbodyComponent, Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Handle_Short'); +const component = new NetworkRigidbodyComponent({ version: 1 }); + +prefab.addComponent(component); +``` + +--- + +### `addEntity(entity)` + +Adds an `Entity` to the prefab. Will override any existing entity with that key. + +- `entity` [``](./Entity.md) The entity to set on the prefab. +- Returns: `` + +```ts +import { Entity, Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Handle_Short'); +const entity = new Entity<'Handle_Short'>('Slot_Multi_6136'); + +prefab.addEntity(entity); +``` + +--- + +### `addGift(giftPrefab)` + +Adds a `Prefab` gift to this prefab's [`SentGift`](./SentGiftComponent.md) component. You may call this method more than once to add additional gifts. + +- `giftPrefab` `` The prefab you want to store inside the gift box. +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const box = new Prefab('Gift_Mail_Box'); +const gift = new Prefab('Dynamite'); + +box.addGift(gift); +``` + +--- + +### `clone(options?)` + +Returns a deep clone of the prefab. + +- `options` (optional, default `{}`) See [`toSaveString(options?)`](#tosavestringoptions). +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const original = new Prefab('Guard').setMaterial('Mythril'); +const clone = original.clone(); + +clone.setMaterial('Gold'); + +const originalMaterial = original.getMaterial(); +// `originalMaterial` is still `31174` (Mythril) + +const cloneMaterial = clone.getMaterial(); +// `cloneMaterial` is `56394` (Gold) +``` + +--- + +### `getAngularVelocity()` + +Gets the spin (vector) on the prefab. + +- Returns: [``](../src/types/AngularVelocity.ts) + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Stone'>.fromSaveString('...'); + +const angularVelocity = prefab.getAngularVelocity(); +const { x, y, z } = angularVelocity; +``` + +--- + +### `getChildPrefab(prefabName, parentHash?)` + +Finds the first child prefab matching the given name. If there are multiple child prefabs with the same name, you can use the second argument to provide a parent hash to match against. + +- `prefabName` [``](./ATTPrefabName.md) The name of the child prefab to get. +- `parentHash` (optional) `` The entity hash of the child prefab. Useful when differentiating between multiple children with the same name. +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Handle_Short'); + +prefab.addChildPrefab('Slot_Large_SwordType_Craft_6134', new Prefab('Guard')); + +const childGuard = prefab.getChildPrefab('Guard'); +// `childGuard` is an instance of `Prefab<'Guard'>` + +const childPommel = prefab.getChildPrefab('Pommel'); +// `childPommel` is `undefined` +``` + +--- + +### `getComponentVersions()` + +Gets a map of component hashes and the versions used on this prefab. Will throw an error if the prefab uses mixed versions of a particular component. + +- Returns: `Map` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + +const componentVersions = prefab.getComponentVersions(); +``` + +--- + +### `getGiftBoxLabel()` + +Gets the gift sender's name, which is labeled on the gift. + +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Gift_Mail_Box'>.fromSaveString('...'); + +const giftBoxLabel = prefab.getGiftBoxLabel(); +``` + +--- + +### `getIntegrity()` + +Gets the prefab's physical integrity. + +- Returns: `` between `0` and `1`. + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + +const integrity = prefab.getIntegrity(); +``` + +--- + +### `getKinematic()` + +Gets the [kinematic](https://docs.unity3d.com/ScriptReference/Rigidbody-isKinematic.html) state of the prefab. + +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + +const isKinematic = prefab.getKinematic(); +``` + +--- + +### `getMaterial()` + +Gets the prefab's physical material. + +- Returns: [``](../src/types/PhysicalMaterialPartHash.ts) + +```ts +import { PhysicalMaterialPartHash, Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Guard'>.fromSaveString('...'); + +const materialHash = prefab.getMaterial(); +const materialName = PhysicalMaterialPartHash[materialHash]; +``` + +--- + +### `getOnFire()` + +Gets the burning state of the prefab. + +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Grass_Clump'>.fromSaveString('...'); + +const isOnFire = prefab.getOnFire(); +``` + +--- + +### `getPosition()` + +Gets the position of the prefab. If the prefab is a child of another prefab, then this position is local to that parent. Otherwise, this position is in world space. + +- Returns: [``](../src/types/Position.ts) + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + +const position = prefab.getPosition(); +const { x, y, z } = position; +``` + +--- + +### `getRotation()` + +Gets the rotation of the prefab. If the prefab is a child of another prefab, then this rotation is local to that parent. Otherwise, this rotation is in world space. + +- Returns: [``](../src/types/Rotation.ts) + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + +const rotation = prefab.getRotation(); +const { x, y, z, w } = rotation; +``` + +--- + +### `getScale()` + +Gets the scale of the prefab. + +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + +const scale = prefab.getScale(); +``` + +--- + +### `getServerSleeping()` + +Gets the [sleeping](https://docs.unity3d.com/Manual/RigidbodiesOverview.html) state of the prefab. + +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + +const isServerSleeping = prefab.getServerSleeping(); +``` + +--- + +### `getServings()` + +Gets the number of servings on a liquid container prefab. + +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Potion_Medium'>.fromSaveString('...'); + +const servings = prefab.getServings(); +``` + +--- + +### `getSpawnAreaPopulationName()` + +Gets the name of the spawn area population, if there is one. Returns `undefined` otherwise. + +- Returns: `<'Unknown' | `[`PopulationDefinitionName`](../src/types/PopulationDefinitionName.ts)` | undefined>` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Disk_Encounter'>.fromSaveString('...'); + +const populationName = prefab.getSpawnAreaPopulationName(); +``` + +--- + +### `getVelocity()` + +Gets the direction (vector) on the prefab. Units are in metres per second. + +- Returns: [``](../src/types/Velocity.ts) + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Stone'>.fromSaveString('...'); + +const velocity = prefab.getVelocity(); +const { x, y, z } = velocity; +``` + +--- + +### `inspect()` + +Prints this prefab's data structure to the console. + +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + +prefab.inspect(); +``` + +--- + +### `print()` + +Prints this prefab's save string to the console. + +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + +prefab.print(); +``` + +--- + +### `removeAllChildPrefabs()` + +Removes all child `Prefab` from this prefab. + +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + +prefab.removeAllChildPrefabs(); +``` + +--- + +### `removeAllComponents()` + +Removes all components on this prefab. + +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + +prefab.removeAllComponents(); +``` + +--- + +### `removeAllEntities()` + +Removes all entities on this prefab. + +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + +prefab.removeAllEntities(); +``` + +--- + +### `removeAllGifts()` + +Removes all gift `Prefab` from this prefab. + +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Gift_Mail_Box'>.fromSaveString('...'); + +prefab.removeAllGifts(); +``` + +--- + +### `removeChildPrefab(prefabArg)` + +Removes the specified child `Prefab` from this prefab. + +- `prefabArg` `<`[`ATTPrefabHash`](./ATTPrefabHash.md)`|`[`ATTPrefabName`](./ATTPrefabName.md)`>` The child prefab's hash or name to remove from this prefab. +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + +prefab.removeChildPrefab(51672); +// or +prefab.removeChildPrefab('Guard'); +``` + +--- + +### `removeComponent(componentArg)` + +Removes the specified component from this prefab. + +- `componentArg` `<`[`ComponentHash`](../src/types/ComponentHash.ts)` | keyof Omit<`[`PrefabComponents`](../src/types/PrefabComponents.ts)`, 'Unknown'>>` The component's hash or name to remove from this prefab. +- Returns: `` + +```ts +import { ComponentHash, Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + +prefab.removeComponent(ComponentHash.NetworkRigidbody); +// or +prefab.removeComponent('NetworkRigidbody'); +``` + +--- + +### `removeEntity(entityKey)` + +Removes the specified entity from this prefab. + +- `entityKey` `>>` The entity's key to remove from this prefab. +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + +prefab.removeEntity('Slot_Multi_6136'); +``` + +--- + +### `removeGift(prefabArg)` + +Removes the specified gift `Prefab` from this prefab. + +- `prefabArg` `<`[`ATTPrefabHash`](./ATTPrefabHash.md)`|`[`ATTPrefabName`](./ATTPrefabName.md)>` The gift prefab's hash or name to remove from this prefab. +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Gift_Mail_Box'>.fromSaveString('...'); + +prefab.removeGift(31326); +// or +prefab.removeGift('Dynamite'); +``` + +--- + +### `removeSpawnArea()` + +Removes the spawn area components from this prefab. + +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = Prefab<'Disk_Encounter'>.fromSaveString('...'); + +prefab.removeSpawnArea(); +``` + +--- + +### `setAngularVelocity(angularVelocity)` + +Sets a spin (vector) on the prefab, causing the physics engine to apply a force to it when spawning. Units are in metres per second. Only works reliably on the parent prefab. Does not work on kinematic prefabs. Does not work on static prefabs. + +- `angularVelocity` [``](../src/types/AngularVelocity.ts) The angular velocity to set on this prefab. +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Stone'); + +prefab.setAngularVelocity({ x: 420, y: 69, z: 1337 }); +``` + +--- + +### `setGiftBoxLabel(label)` + +Sets the gift sender's name, which is labeled on the gift. + +- `label` `` The label to set on the gift box. +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Gift_Mail_Box'); + +prefab.setGiftBoxLabel('topkek'); +``` + +--- + +### `setIntegrity(integrity)` + +Sets the prefab's integrity. This can change both its appearance and other qualities such as durability and the amount of materials recovered from recycling. + +- `integrity` `` The integrity of the physical material of the prefab. +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Handle_Short'); + +prefab.setIntegrity(0.69); +``` + +--- + +### `setKinematic(isKinematic?)` + +Makes the prefab [kinematic](https://docs.unity3d.com/ScriptReference/Rigidbody-isKinematic.html). By default, a `new Prefab()` is not kinematic, but some prefabs require to be kinematic to work properly. You can optionally pass a boolean, for example `setKinematic(false)`. + +- `isKinematic` (optional, default `true`) `` Whether the prefab must be kinematic or not. +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Handle_Short'); + +prefab.setKinematic(true); +``` + +--- + +### `setMaterial(materialArg)` + +Sets the prefab's physical material. This can change both its appearance and other qualities such as durability, damage, heat retention and weight. + +- `materialArg` [``](../src/types/PhysicalMaterialPartHash.ts) The physical material's hash or name to set on the prefab. +- Returns: `` + +```ts +import { PhysicalMaterialPartHash, Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Handle_Short'); + +prefab.setMaterial(PhysicalMaterialPartHash.Mythril); +// or +prefab.setMaterial('Mythril'); +``` + +--- + +### `setOnFire(isLit?)` + +Sets the prefab on fire, if it is capable of catching fire. + +- `isLit` (optional, default `true`) `` Whether or not to set the prefab alight. +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Grass_Clump'); + +prefab.setOnFire(true); +``` + +--- + +### `setPosition(position)` + +Sets the position of the prefab. If the prefab is a child of another prefab, then this position is local to that parent. Otherwise, this position is in world space. + +- `position` [``](../src/types/Position.ts) The position to set on the prefab. +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Stone'); + +prefab.setPosition({ x: 420, y: 69, z: 1337 }); +``` + +--- + +### `setRotation(rotation)` + +Sets the rotation of the prefab. If the prefab is a child of another prefab, then this rotation is local to that parent. Otherwise, this rotation is in world space. + +- `rotation` [``](../src/types/Rotation.ts) The rotation to set on the prefab. +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Stone'); + +prefab.setRotation({ x: 0.42, y: -0.69, z: 0.1337, w: -0.88 }); +``` + +--- + +### `setScale(scale)` + +Sets the scale of the prefab. + +- `scale` `` The scale to set on the prefab. +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Stone'); + +prefab.setScale(0.69); +``` + +--- + +### `setServerSleeping(isServerSleeping?)` + +Makes the prefab [sleep](https://docs.unity3d.com/Manual/RigidbodiesOverview.html). By default, a `new Prefab()` is not sleeping. A sleeping prefab does not have its physics simulated until it receives a collision or force, such as touching it. You can optionally pass a boolean, for example `setServerSleeping(false)`. + +- `isServerSleeping` (optional, default `true`) `` Whether the prefab must be sleeping or not. +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Handle_Short'); + +prefab.setServerSleeping(true); +``` + +--- + +### `setServings(servings)` + +Sets the number of servings on a liquid container prefab. + +- `servings` `` The amount of servings to set on the prefab. +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Potion_Medium'); + +prefab.setServings(69); +``` + +--- + +### `setSpawnArea(populationArg, props?)` + +Sets a spawn area on the prefab with the given population and any additional configuration. + +- `populationArg` `<`[`PopulationDefinitionHash`](../src/types/PopulationDefinitionHash.ts)`|`[`PopulationDefinitionName`](../src/types/PopulationDefinitionName.ts)`>` The spawn area population hash or name to set on the prefab. +- `props` (optional, default `{}`) [``](../src/types/SetSpawnAreaProps.ts) Additional properties for configuring the spawn area. +- Returns: `` + +```ts +import { PopulationDefinitionHash, Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Disk_Encounter'); + +prefab.setSpawnArea(PopulationDefinitionHash.WyrmPopulation, { + currentPopulation: 5, + isOneOff: false, + isPopulationStarted: true, + maxPopulation: 20, + numberOfSpawnPoints: 40, + size: 5, + startingPopulation: 5 +}); +``` + +--- + +### `setVelocity(velocity)` + +Sets a direction (vector) on the prefab, causing the physics engine to apply a force to it when spawning. Units are in metres per second. Only works reliably on the parent prefab. Does not work on kinematic prefabs. Does not work on static prefabs. + +- `velocity` [``](../src/types/Velocity.ts) The velocity to set on this prefab. +- Returns: `` + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Stone'); + +prefab.setVelocity({ x: 420, y: 69, z: 1337 }); +``` + +--- + +### `toBinary(componentVersions)` + +Returns a `BinaryString` representation of the prefab. + +- `componentVersions` `>` A map of component versions to ensure are encoded in the binary data. +- Returns: [``](./BinaryString.md) + +```ts +import { ComponentHash, Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Stone'); + +const componentVersions = prefab.getComponentVersions(); +// or +const componentVersions = new Map([ + [ComponentHash.NetworkRigidbody, 1], + [ComponentHash.PhysicalMaterialPart, 1], + [ComponentHash.Pickup, 2] + // etc... +]); + +const binaryString = prefab.toBinary(componentVersions); +``` + +--- + +### `toSaveString(options?)` + +Returns the `SaveString` to spawn this prefab in the game. You may pass additional options to change the output behaviour. + +- `options` (optional, default `{}`) `` +- `options.excludeComponentVersions` (optional, default `false`) Set to true to force a save string without component versions. +- `options.ignoreIndeterminateComponentVersions` (optional, default `false`) Same as `excludeComponentVersions` but only when encountering indeterminate component versions. +- Returns: [``](./SaveString.md) + +```ts +import { Prefab } from 'att-string-transcoder'; + +const prefab = new Prefab('Stone'); + +const saveString = prefab.toSaveString(); +``` diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..efb569e --- /dev/null +++ b/docs/README.md @@ -0,0 +1,58 @@ +# API Reference Documentation + +- Types + - [``](./ATTPrefabHash.md) + - [``](./ATTPrefabName.md) + - [``](./BinaryString.md) + - [``](./SaveString.md) +- Classes + - [`BasicDecayComponent`](./BasicDecayComponent.md) + - [`BinaryData`](./BinaryData.md) + - [`BinaryReader`](./BinaryReader.md) + - [`BinaryWriter`](./BinaryWriter.md) + - [`Component`](./Component.md) + - [`DoorComponent`](./DoorComponent.md) + - [`DurabilityModuleComponent`](./DurabilityModuleComponent.md) + - [`Entity`](./Entity.md) + - [`FireComponent`](./FireComponent.md) + - [`FuseComponent`](./FuseComponent.md) + - [`HeatSourceBaseComponent`](./HeatSourceBaseComponent.md) + - [`LiquidContainerComponent`](./LiquidContainerComponent.md) + - [`LogicBoolReceiverComponent`](./LogicBoolReceiverComponent.md) + - [`LogicBoolSenderComponent`](./LogicBoolSenderComponent.md) + - [`LogicFloatReceiverComponent`](./LogicFloatReceiverComponent.md) + - [`LogicFloatSenderComponent`](./LogicFloatSenderComponent.md) + - [`LogicGateReceiverComponent`](./LogicGateReceiverComponent.md) + - [`LogicIntReceiverComponent`](./LogicIntReceiverComponent.md) + - [`LogicIntSenderComponent`](./LogicIntSenderComponent.md) + - [`LogicVector3ReceiverComponent`](./LogicVector3ReceiverComponent.md) + - [`LogicVector3SenderComponent`](./LogicVector3SenderComponent.md) + - [`NetworkRigidbodyComponent`](./NetworkRigidbodyComponent.md) + - [`PhysicalMaterialPartComponent`](./PhysicalMaterialPartComponent.md) + - [`PickupComponent`](./PickupComponent.md) + - [`PickupDockComponent`](./PickupDockComponent.md) + - [`PopulationSpawnAreaComponent`](./PopulationSpawnAreaComponent.md) + - [`Prefab`](./Prefab.md) + - [`SentGiftComponent`](./SentGiftComponent.md) + - [`SlidingDoorComponent`](./SlidingDoorComponent.md) + - [`SpawnAreaComponent`](./SpawnAreaComponent.md) + - [`StatManagerComponent`](./StatManagerComponent.md) + - [`UnsupportedComponent`](./UnsupportedComponent.md) + - [`WoodcutTreeComponent`](./WoodcutTreeComponent.md) +- Functions + - [`isATTPrefabHash(hash)`](./isATTPrefabHash.md) + - [`isATTPrefabName(name)`](./isATTPrefabName.md) + - [`isSavableComponent(componentName, prefabArg)`](./isSavableComponent.md) + - [`isUnknownComponent(component)`](./isUnknownComponent.md) + - [`readChildren(reader, componentVersions?)`](./readChildren.md) + - [`readComponent(reader, hash, name, version)`](./readComponent.md) + - [`readComponents(reader, versions?)`](./readComponents.md) + - [`readEntities(reader, prefabName, componentVersions?)`](./readEntities.md) + - [`writeChildren(writer, children, componentVersions)`](./writeChildren.md) + - [`writeComponents(writer, components, versions)`](./writeComponents.md) + - [`writeEntities(writer, entities, componentVersions)`](./writeEntities.md) +- Examples + - [Alter a sword's material](./examples/Alter-a-swords-material.md) + - [Flask of infinite teleportation](./examples/Flask-of-infinite-teleportation.md) + - [Integrate with a bot](./examples/Flask-of-infinite-teleportation.md) + - [Launch a wyrm spit](./examples/Flask-of-infinite-teleportation.md) diff --git a/docs/SaveString.md b/docs/SaveString.md new file mode 100644 index 0000000..2a050b1 --- /dev/null +++ b/docs/SaveString.md @@ -0,0 +1,5 @@ +# `` + +The `` type is used to narrow `` types to recognised ATT save strings. + +You can use the [`BinaryData.isSaveString`](./BinaryData.md#binarydataissavestring) type assertion function to narrow down your `` types. diff --git a/docs/SentGiftComponent.md b/docs/SentGiftComponent.md new file mode 100644 index 0000000..955287d --- /dev/null +++ b/docs/SentGiftComponent.md @@ -0,0 +1,189 @@ +# Class: `SentGiftComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#sentgiftcomponentprops) +- [Constructors](#constructors) + - [`new SentGiftComponent(props)`](#new-sentgiftcomponentprops) + - [`SentGiftComponent.fromBinary(reader, version)`](#sentgiftcomponentfrombinaryreader-version) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`receiverName`](#receivername) + - [`senderName`](#sendername) + - [`gifts`](#gifts) + - [`senderTag`](#sendertag) +- [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 `SentGiftComponent` constructor. + +```ts +type Gift = null | { + data: number[]; + messageSizeInBytes: number; + hash: number; + chunkVersioning: number[]; +}; + +type SentGiftTag = null | { + from: number; + to: number; +}; + +type SentGiftComponentPropsV1 = { + receiverName?: string | undefined; + senderName?: string | undefined; + gifts?: Gift[] | undefined; + senderTag?: SentGiftTag | undefined; +}; + +type SentGiftComponentProps = SentGiftComponentPropsV1; +``` + +#### Since v1 + +- `receiverName` (optional, default `''`) `` +- `senderName` (optional, default `''`) `` +- `gifts` (optional, default `[]`) `>` +- `senderTag` (optional, default `null`) `` + +## Constructors + +### `new SentGiftComponent(props)` + +Creates a versioned `SentGift` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { SentGiftComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new SentGiftComponent({ version: componentVersion }); +``` + +--- + +### `SentGiftComponent.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) + +--- + +### `receiverName` + +Name of the player intended as the receiver of the prefab this component is attached to. + +- Since: `v1` +- `` + +```ts +import { SentGiftComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new SentGiftComponent({ version: componentVersion }); + +const receiverName = component.receiverName; +// `receiverName` is `''` +``` + +--- + +### `senderName` + +Name of the player intended as the sender of the prefab this component is attached to. This name will be displayed as a label on a gift box prefab. + +- Since: `v1` +- `` + +```ts +import { SentGiftComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new SentGiftComponent({ version: componentVersion }); + +const senderName = component.senderName; +// `senderName` is `''` +``` + +--- + +### `gifts` + +Array of gifts, which are prefab save strings. + +- Since: `v1` +- `>` + +```ts +import { SentGiftComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new SentGiftComponent({ version: componentVersion }); + +const gifts = component.gifts; +// `gifts` is `[]` +``` + +--- + +### `senderTag` + +- Since: `v3` +- `` + +```ts +import { SentGiftComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new SentGiftComponent({ version: componentVersion }); + +const senderTag = component.senderTag; +// `senderTag` is `null` +``` + +## 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/SlidingDoorComponent.md b/docs/SlidingDoorComponent.md new file mode 100644 index 0000000..8d27a9d --- /dev/null +++ b/docs/SlidingDoorComponent.md @@ -0,0 +1,113 @@ +# Class: `SlidingDoorComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#slidingdoorcomponentprops) +- [Constructors](#constructors) + - [`new SlidingDoorComponent(props)`](#new-slidingdoorcomponentprops) + - [`SlidingDoorComponent.fromBinary(reader, version)`](#slidingdoorcomponentfrombinaryreader-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 `SlidingDoorComponent` constructor. + +```ts +type SlidingDoorComponentPropsV1 = { + isOpen?: number | undefined; +}; + +type SlidingDoorComponentProps = SlidingDoorComponentPropsV1; +``` + +#### Since v1 + +- `isOpen` (optional, default `false`) `` + +## Constructors + +### `new SlidingDoorComponent(props)` + +Creates a versioned `SlidingDoor` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { SlidingDoorComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new SlidingDoorComponent({ version: componentVersion }); +``` + +--- + +### `SlidingDoorComponent.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 { SlidingDoorComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new SlidingDoorComponent({ 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/SpawnAreaComponent.md b/docs/SpawnAreaComponent.md new file mode 100644 index 0000000..fc1e0ff --- /dev/null +++ b/docs/SpawnAreaComponent.md @@ -0,0 +1,193 @@ +# Class: `SpawnAreaComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#spawnareacomponentprops) +- [Constructors](#constructors) + - [`new SpawnAreaComponent(props)`](#new-spawnareacomponentprops) + - [`SpawnAreaComponent.fromBinary(reader, version)`](#spawnareacomponentfrombinaryreader-version) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`size`](#size) + - [`groundLayers`](#groundlayers) + - [`avoidLayers`](#avoidlayers) + - [`isAligningNormal`](#isaligningnormal) + - [`maxAcceptableAngleDot`](#maxacceptableangledot) +- [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 `SpawnAreaComponent` constructor. + +```ts +type SpawnAreaComponentPropsV1 = { + size?: number | undefined; + groundLayers?: number | undefined; + avoidLayers?: number | undefined; + isAligningNormal?: boolean | undefined; + maxAcceptableAngleDot?: number | undefined; +}; + +type SpawnAreaComponentProps = SpawnAreaComponentPropsV1; +``` + +#### Since v1 + +- `size` (optional, default `5`) `` +- `groundLayers` (optional, default `1280`) `` +- `avoidLayers` (optional, default `8721`) `` +- `isAligningNormal` (optional, default `false`) `` +- `maxAcceptableAngleDot` (optional, default `-1`) `` + +## Constructors + +### `new SpawnAreaComponent(props)` + +Creates a versioned `SpawnArea` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { SpawnAreaComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new SpawnAreaComponent({ version: componentVersion }); +``` + +--- + +### `SpawnAreaComponent.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) + +--- + +### `size` + +The size (in metres) of the spawn area of the prefab this component is attached to. + +- Since: `v1` +- `` + +```ts +import { SpawnAreaComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new SpawnAreaComponent({ version: componentVersion }); + +const size = component.size; +// `size` is `5` +``` + +--- + +### `groundLayers` + +- Since: `v1` +- `` + +```ts +import { SpawnAreaComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new SpawnAreaComponent({ version: componentVersion }); + +const groundLayers = component.groundLayers; +// `groundLayers` is `1280` +``` + +--- + +### `avoidLayers` + +- Since: `v1` +- `` + +```ts +import { SpawnAreaComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new SpawnAreaComponent({ version: componentVersion }); + +const avoidLayers = component.avoidLayers; +// `avoidLayers` is `8721` +``` + +--- + +### `isAligningNormal` + +- Since: `v1` +- `` + +```ts +import { SpawnAreaComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new SpawnAreaComponent({ version: componentVersion }); + +const isAligningNormal = component.isAligningNormal; +// `isAligningNormal` is `false` +``` + +--- + +### `maxAcceptableAngleDot` + +- Since: `v1` +- `` + +```ts +import { SpawnAreaComponent } from 'att-string-transcoder'; + +const componentVersion = 1; +const component = new SpawnAreaComponent({ version: componentVersion }); + +const maxAcceptableAngleDot = component.maxAcceptableAngleDot; +// `maxAcceptableAngleDot` 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/StatManagerComponent.md b/docs/StatManagerComponent.md new file mode 100644 index 0000000..53ca317 --- /dev/null +++ b/docs/StatManagerComponent.md @@ -0,0 +1,176 @@ +# Class: `StatManagerComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#statmanagercomponentprops) +- [Constructors](#constructors) + - [`new StatManagerComponent(props)`](#new-statmanagercomponentprops) + - [`StatManagerComponent.fromBinary(reader, version)`](#statmanagercomponentfrombinaryreader-version) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`stats`](#stats) + - [`modifiers`](#modifiers) + - [`indirectStatModifiers`](#indirectstatmodifiers) +- [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 `StatManagerComponent` constructor. + +```ts +type Stat = null | { + hash: number; + baseFlat: number; +}; + +type TimedModifier = null | { + hash: number; + value: number; + isMultiplier: boolean; + time: number; +}; + +type IndirectModifierSaveData = { + valueOverDurationHash: number; + baseValue: number; + duration: number; + tick: number; +}; + +type IndirectStatModifier = null | { + hash: number; + time: number; + modifiers: IndirectModifierSaveData[]; +}; + +type StatManagerComponentPropsV2 = { + stats?: Stat[] | undefined; + modifiers?: TimedModifier[] | undefined; + indirectStatModifiers?: IndirectStatModifier[] | undefined; +}; + +type StatManagerComponentProps = StatManagerComponentPropsV2; +``` + +#### Since v2 + +- `stats` (optional, default `[]`) `>` +- `modifiers` (optional, default `[]`) `>` +- `indirectStatModifiers` (optional, default `[]`) `>` + +## Constructors + +### `new StatManagerComponent(props)` + +Creates a versioned `StatManager` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { StatManagerComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new StatManagerComponent({ version: componentVersion }); +``` + +--- + +### `StatManagerComponent.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) + +--- + +### `stats` + +- Since: `v2` +- `>` + +```ts +import { StatManagerComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new StatManagerComponent({ version: componentVersion }); + +const stats = component.stats; +// `stats` is `[]` +``` + +--- + +### `modifiers` + +- Since: `v2` +- `>` + +```ts +import { StatManagerComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new StatManagerComponent({ version: componentVersion }); + +const modifiers = component.modifiers; +// `modifiers` is `[]` +``` + +--- + +### `indirectStatModifiers` + +- Since: `v2` +- `>` + +```ts +import { StatManagerComponent } from 'att-string-transcoder'; + +const componentVersion = 2; +const component = new StatManagerComponent({ version: componentVersion }); + +const indirectStatModifiers = component.indirectStatModifiers; +// `indirectStatModifiers` is `[]` +``` + +## 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/UnsupportedComponent.md b/docs/UnsupportedComponent.md new file mode 100644 index 0000000..fadafb4 --- /dev/null +++ b/docs/UnsupportedComponent.md @@ -0,0 +1,144 @@ +# Class: `UnsupportedComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#unsupportedcomponentprops) +- [Constructors](#constructors) + - [`new UnsupportedComponent(props)`](#new-unsupportedcomponentprops) + - [`UnsupportedComponent.fromBinary(reader, version, hash, name, dataLength)`](#unsupportedcomponentfrombinaryreader-version-hash-name-datalength) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`rawData`](#rawdata) +- [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 `UnsupportedComponent` constructor. + +```ts +type UnsupportedComponentProps = { + hash: number; + name: string; + rawData: BinaryString; +}; +``` + +- `hash` `` The hash of the component. +- `name` `` The name of the component. +- `rawData` [``](./BinaryString.md) The serialised data of the component. + +## Constructors + +### `new UnsupportedComponent(props)` + +Creates a versioned component without deserialising its data. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { UnsupportedComponent } from 'att-string-transcoder'; + +const hash = 1337; +const name = 'SomeUnrecognisedComponentName'; +const rawData = '11110111001100010000'; +const version = 1; + +const component = new UnsupportedComponent({ hash, name, rawData, version }); +``` + +--- + +### `UnsupportedComponent.fromBinary(reader, version, hash, name, dataLength)` + +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. +- `hash` `` The hash of the component. +- `name` `` The name of the component. +- `dataLength` `` The length of the component's binary data. + +```ts +import { BinaryReader, UnsupportedComponent } from 'att-string-transcoder'; + +const reader = new BinaryReader('...'); +const componentVersion = 1; +const componentHash = 1337; +const componentName = 'SomeUnrecognisedComponentName'; +const componentDataLength = 20; + +const component = UnsupportedComponent.fromBinary( + reader, + componentVersion, + componentHash, + componentName, + componentDataLength +); +``` + +## 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) + +--- + +### `rawData` + +The component's serialised data. + +- [``](./BinaryString.md) The component's serialised data. + +```ts +import { UnsupportedComponent } from 'att-string-transcoder'; + +const hash = 1337; +const name = 'SomeUnrecognisedComponentName'; +const rawData = '11110111001100010000'; +const version = 1; + +const component = new UnsupportedComponent({ hash, name, rawData, version }); + +const rawData = component.rawData; +// `rawData` is `'11110111001100010000'` +``` + +## 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/WoodcutTreeComponent.md b/docs/WoodcutTreeComponent.md new file mode 100644 index 0000000..f847347 --- /dev/null +++ b/docs/WoodcutTreeComponent.md @@ -0,0 +1,133 @@ +# Class: `WoodcutTreeComponent` + +- [Types](#types) + - [``](#componentprops) + - [``](#basicdecaycomponentprops) +- [Constructors](#constructors) + - [`new WoodcutTreeComponent(props)`](#new-basicdecaycomponentprops) + - [`WoodcutTreeComponent.fromBinary(reader, version)`](#basicdecaycomponentfrombinaryreader-version) +- [Properties](#properties) + - [`hash`](#hash) + - [`name`](#name) + - [`version`](#version) + - [`presetHash`](#presethash) + - [`speciesHash`](#specieshash) +- [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 `WoodcutTreeComponent` constructor. + +```ts +type WoodcutTreeComponentPropsV3 = { + presetHash?: 0 | PresetHash | undefined; + speciesHash?: SpeciesHash | undefined; +}; + +type WoodcutTreeComponentProps = WoodcutTreeComponentPropsV3; +``` + +#### Since v3 + +- `presetHash` (optional, default `0`) `` +- `speciesHash` (optional, default `11232`) [``](../src/types/SpeciesHash.ts) + +## Constructors + +### `new WoodcutTreeComponent(props)` + +Creates a versioned `WoodcutTree` component. + +- `props` [``](#types) Configuration of the component to create. +- Returns: `` + +```ts +import { WoodcutTreeComponent } from 'att-string-transcoder'; + +const componentVersion = 3; +const component = new WoodcutTreeComponent({ version: componentVersion }); +``` + +--- + +### `WoodcutTreeComponent.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) + +--- + +### `presetHash` + +- Since: `v3` +- `` + +```ts +import { WoodcutTreeComponent } from 'att-string-transcoder'; + +const componentVersion = 3; +const component = new WoodcutTreeComponent({ version: componentVersion }); + +const presetHash = component.presetHash; +// `presetHash` is `0` +``` + +--- + +### `speciesHash` + +The hash of the species of the tree prefab this component is attached to. + +- Since: `v3` +- [``](../src/types/SpeciesHash.ts) + +```ts +import { WoodcutTreeComponent } from 'att-string-transcoder'; + +const componentVersion = 3; +const component = new WoodcutTreeComponent({ version: componentVersion }); + +const speciesHash = component.speciesHash; +// `speciesHash` is `11232` +``` + +## 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/examples/Alter-a-swords-material.md b/docs/examples/Alter-a-swords-material.md new file mode 100644 index 0000000..bb849a9 --- /dev/null +++ b/docs/examples/Alter-a-swords-material.md @@ -0,0 +1,13 @@ +# Alter a sword's material + +```ts +import { Prefab } from 'att-string-transcoder'; + +const handle = Prefab.fromSaveString<'Handle_Short'>('...'); + +handle.children + .find(child => child.prefab.name === 'Guard') + ?.prefab.children.find(child => child.prefab.name === 'Short_Sword_Blade') + ?.prefab.setMaterial('EvinonSteelAlloy') + .print(); +``` diff --git a/docs/examples/Flask-of-infinite-teleportation.md b/docs/examples/Flask-of-infinite-teleportation.md new file mode 100644 index 0000000..869469d --- /dev/null +++ b/docs/examples/Flask-of-infinite-teleportation.md @@ -0,0 +1,9 @@ +# Flask of infinite teleportation + +```ts +import { Prefab } from 'att-string-transcoder'; + +const flask = new Prefab('Potion_Medium'); + +flask.setServings(999).print(); +``` diff --git a/docs/examples/Integrate-with-a-bot.md b/docs/examples/Integrate-with-a-bot.md new file mode 100644 index 0000000..39ae9c6 --- /dev/null +++ b/docs/examples/Integrate-with-a-bot.md @@ -0,0 +1,17 @@ +# Integrate with a bot + +```ts +import { Prefab } from 'att-string-transcoder'; + +// ... + +const commandResult = await botClient.send('...'); +const saveString = commandResult.data.ResultString; + +const prefab = Prefab.fromSaveString(saveString); +prefab.setOnFire(); + +const newSaveString = prefab.toSaveString(); + +await botClient.send(`spawn string-raw ${newSaveString}`); +``` diff --git a/docs/examples/Launch-a-wyrm-spit.md b/docs/examples/Launch-a-wyrm-spit.md new file mode 100644 index 0000000..d67bc0b --- /dev/null +++ b/docs/examples/Launch-a-wyrm-spit.md @@ -0,0 +1,12 @@ +# Launch a wym spit + +```ts +import { Prefab } from 'att-string-transcoder'; + +const spit = new Prefab('Wyrm_Spit'); + +spit.setPosition(playerRightHandPosition); +spit.setRotation(playerRightHandUpInverted); +spit.setVelocity(playerRightHandUpInvertedMultiplied); +spit.print(); +``` diff --git a/docs/isATTPrefabHash.md b/docs/isATTPrefabHash.md new file mode 100644 index 0000000..962ec8e --- /dev/null +++ b/docs/isATTPrefabHash.md @@ -0,0 +1,22 @@ +# Function: `isATTPrefabHash` + +Asserts if a `` is an [``](./ATTPrefabHash.md). + +## Signatures + +### `isATTPrefabHash(hash)` + +- `hash` `` The hash of the prefab. +- Returns: `` + +```ts +import { isATTPrefabHash } from 'att-string-transcoder'; + +let prefabHash: number; +prefabHash = 23182; +// `prefabHash` is of type `number`. + +if (isATTPrefabHash(prefabHash)) { + // `prefabHash` is of type `ATTPrefabHash`. +} +``` diff --git a/docs/isATTPrefabName.md b/docs/isATTPrefabName.md new file mode 100644 index 0000000..29c92f9 --- /dev/null +++ b/docs/isATTPrefabName.md @@ -0,0 +1,22 @@ +# Function: `isATTPrefabName` + +Asserts if a `` is an [``](./ATTPrefabName.md). + +## Signatures + +### `isATTPrefabName(name)` + +- `name` `` The name of the prefab. +- Returns: `` + +```ts +import { isATTPrefabName } from 'att-string-transcoder'; + +let prefabName: string; +prefabName = 'Anvil'; +// `prefabName` is of type `string`. + +if (isATTPrefabName(prefabName)) { + // `prefabName` is of type `ATTPrefabName`. +} +``` diff --git a/docs/isSavableComponent.md b/docs/isSavableComponent.md new file mode 100644 index 0000000..af7e4ea --- /dev/null +++ b/docs/isSavableComponent.md @@ -0,0 +1,33 @@ +# Function: `isSavablecomponent` + +Returns whether or not the given component name belongs to a component that is normally savable on the given prefab hash or name. + +## Signatures + +### `isSavablecomponent(componentName, prefabHash)` + +- `componentName` [``](../src/types/SupportedPrefabComponents.ts) The name of the component. +- `prefabHash` [``](./ATTPrefabHash.md) The hash of the parent prefab. +- Returns: `` + +```ts +import { isSavableComponent } from 'att-string-transcoder'; + +if (isSavableComponent('NetworkRigidbody', 42230)) { + // `Handle_Short` can save `NetworkRigidbody` component data. +} +``` + +### `isSavablecomponent(componentName, prefabName)` + +- `componentName` [``](../src/types/SupportedPrefabComponents.ts) The name of the component. +- `prefabName` [``](./ATTPrefabName.md) The name of the parent prefab. +- Returns: `` + +```ts +import { isSavablecomponent } from 'att-string-transcoder'; + +if (isSavableComponent('NetworkRigidbody', 'Handle_Short')) { + // `Handle_Short` can save `NetworkRigidbody` component data. +} +``` diff --git a/docs/isUnknownComponent.md b/docs/isUnknownComponent.md new file mode 100644 index 0000000..59cc8bc --- /dev/null +++ b/docs/isUnknownComponent.md @@ -0,0 +1,18 @@ +# Function: `isUnknownComponent` + +Asserts if a `component` is an [`UnsupportedComponent`](./UnsupportedComponent.md). + +## Signatures + +### `isUnknownComponent(component)` + +- `component` [`Component`](./Component.md) +- Returns: `` + +```ts +import { isUnknownComponent } from 'att-string-transcoder'; + +if (isUnknownComponent(component)) { + // `component` is of type `UnsupportedComponent`. +} +``` diff --git a/docs/readChildren.md b/docs/readChildren.md new file mode 100644 index 0000000..1ad7d8c --- /dev/null +++ b/docs/readChildren.md @@ -0,0 +1,26 @@ +# Function: `readChildren` + +Reads all child prefabs from the given `BinaryReader` and returns an array of `PrefabChild`. + +## Signatures + +### `readChildren(reader, componentVersions?)` + +- `reader` [`BinaryReader`](./BinaryReader.md) The `BinaryReader` containing the child prefab binary data. +- `componentVersions` (optional, default latest) `>` A map of component versions to ensure are encoded in the binary data. +- Returns: [`>`](../src/types/PrefabChild.ts) + +```ts +import { BinaryReader, readChildren } from 'att-string-transcoder'; + +const reader = new BinaryReader('...'); + +const componentVersions = new Map([ + [ComponentHash.NetworkRigidbody, 1], + [ComponentHash.PhysicalMaterialPart, 1], + [ComponentHash.Pickup, 2] + // etc... +]); + +const children = readChildren(reader, componentVersions); +``` diff --git a/docs/readComponent.md b/docs/readComponent.md new file mode 100644 index 0000000..e29831e --- /dev/null +++ b/docs/readComponent.md @@ -0,0 +1,24 @@ +# Function: `readComponent` + +Reads next component from the given `BinaryReader` and returns a `Component` instance. + +## Signatures + +### `readComponent(reader, hash, name, version)` + +- `reader` [`BinaryReader`](./BinaryReader.md) The `BinaryReader` containing the component binary data. +- `hash` `` The hash of the component. +- `name` `` The name of the component. +- `version` `` The version of the component. +- Returns: [``](./Component.md) + +```ts +import { BinaryReader, readComponent } from 'att-string-transcoder'; + +const reader = new BinaryReader('...'); +const hash = 2290978823; +const name = 'NetworkRigidbody'; +const version = 1; + +const component = readComponent(reader, hash, name, version); +``` diff --git a/docs/readComponents.md b/docs/readComponents.md new file mode 100644 index 0000000..11b643a --- /dev/null +++ b/docs/readComponents.md @@ -0,0 +1,26 @@ +# Function: `readComponents` + +Reads all components from the given `BinaryReader` and returns a `PrefabComponents` object. + +## Signatures + +### `readComponents(reader, versions?)` + +- `reader` [`BinaryReader`](./BinaryReader.md) The `BinaryReader` containing the components binary data. +- `versions` (optional, default latest) `>` A map of component versions to ensure are encoded in the binary data. +- Returns: [``](../src/types/PrefabComponents.ts) + +```ts +import { BinaryReader, readComponents } from 'att-string-transcoder'; + +const reader = new BinaryReader('...'); + +const versions = new Map([ + [ComponentHash.NetworkRigidbody, 1], + [ComponentHash.PhysicalMaterialPart, 1], + [ComponentHash.Pickup, 2] + // etc... +]); + +const component = readComponents(reader, versions); +``` diff --git a/docs/readEntities.md b/docs/readEntities.md new file mode 100644 index 0000000..fd6d1fb --- /dev/null +++ b/docs/readEntities.md @@ -0,0 +1,28 @@ +# Function: `readEntities` + +Reads all entities from the given `BinaryReader` and returns a `PrefabEntities` object. + +## Signatures + +### `readEntities(reader, prefabName, componentVersions?)` + +- `reader` [`BinaryReader`](./BinaryReader.md) The `BinaryReader` containing the entities binary data. +- `prefabName` [`ATTPrefabName`](./ATTPrefabName.md) The name of the parent prefab. +- `componentVersions` (optional, default latest) `>` A map of component versions to ensure are encoded in the binary data. +- Returns: [``](../src/types/PrefabEntities.ts) + +```ts +import { BinaryReader, readEntities, type ATTPrefabName } from 'att-string-transcoder'; + +const reader = new BinaryReader('...'); +const prefabName = 'Handle_Short' as ATTPrefabName; + +const componentVersions = new Map([ + [ComponentHash.NetworkRigidbody, 1], + [ComponentHash.PhysicalMaterialPart, 1], + [ComponentHash.Pickup, 2] + // etc... +]); + +const component = readEntities(reader, prefabName, componentVersions); +``` diff --git a/docs/writeChildren.md b/docs/writeChildren.md new file mode 100644 index 0000000..b7605c4 --- /dev/null +++ b/docs/writeChildren.md @@ -0,0 +1,34 @@ +# Function: `writeChildren` + +Writes given child prefabs to the given `BinaryWriter`. + +## Signatures + +### `writeChildren(writer, children, componentVersions)` + +- `writer` [`BinaryWriter`](./BinaryWriter.md) The `BinaryWriter` to store the binary data into. +- `children` [`>`](../src/types/PrefabChild.ts) The child prefabs to store. +- `componentVersions` `>` A map of component versions to ensure are encoded in the binary data. +- Returns: `` + +```ts +import { BinaryWriter, writeChildren } from 'att-string-transcoder'; + +const writer = new BinaryWriter(); + +const children = [ + { + parentHash: 0, + prefab: new Prefab('Guard') + } +]; + +const componentVersions = new Map([ + [ComponentHash.NetworkRigidbody, 1], + [ComponentHash.PhysicalMaterialPart, 1], + [ComponentHash.Pickup, 2] + // etc... +]); + +writeChildren(writer, children, componentVersions); +``` diff --git a/docs/writeComponents.md b/docs/writeComponents.md new file mode 100644 index 0000000..f856f09 --- /dev/null +++ b/docs/writeComponents.md @@ -0,0 +1,32 @@ +# Function: `writeComponents` + +Writes given components to the given `BinaryWriter`. + +## Signatures + +### `writeComponents(writer, components, versions)` + +- `writer` [`BinaryWriter`](./BinaryWriter.md) The `BinaryWriter` to store the binary data into. +- `components` [``](../src/types/PrefabComponents.ts) The components to store. +- `versions` `>` A map of component versions to ensure are encoded in the binary data. +- Returns: `` + +```ts +import { BinaryWriter, NetworkRigidbodyComponent, writeComponents } from 'att-string-transcoder'; + +const writer = new BinaryWriter(); + +const components = { + NetworkRigidbody: new NetworkRigidbodyComponent({ version: 1 }), + Unknown: [] +}; + +const versions = new Map([ + [ComponentHash.NetworkRigidbody, 1], + [ComponentHash.PhysicalMaterialPart, 1], + [ComponentHash.Pickup, 2] + // etc... +]); + +writeComponents(writer, components, versions); +``` diff --git a/docs/writeEntities.md b/docs/writeEntities.md new file mode 100644 index 0000000..7c52e6a --- /dev/null +++ b/docs/writeEntities.md @@ -0,0 +1,31 @@ +# Function: `writeEntities` + +Writes given entities to the given `BinaryWriter`. + +## Signatures + +### `writeEntities(writer, entities, componentVersions)` + +- `writer` [`BinaryWriter`](./BinaryWriter.md) The `BinaryWriter` to store the binary data into. +- `entities` [``](../src/types/PrefabEntities.ts) The entities to store. +- `componentVersions` `>` A map of component versions to ensure are encoded in the binary data. +- Returns: `` + +```ts +import { BinaryWriter, Entity, writeEntities } from 'att-string-transcoder'; + +const writer = new BinaryWriter(); + +const entities = { + Fire_30100: new Entity<'Torch'>('Fire_30100') +}; + +const componentVersions = new Map([ + [ComponentHash.NetworkRigidbody, 1], + [ComponentHash.PhysicalMaterialPart, 1], + [ComponentHash.Pickup, 2] + // etc... +]); + +writeEntities(writer, entities, componentVersions); +``` diff --git a/package.json b/package.json index 0599d35..900dae0 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,7 @@ { "name": "att-string-transcoder", - "version": "2.4.3", - "description": "Trancode integer strings for A Township Tale.", - "main": "dist/index.js", - "scripts": { - "prepare": "npm run build", - "prebuild": "rimraf dist/", - "build": "tsc", - "compile": "tsc --noEmit", - "test": "jest", - "infodump": "ts-node scripts/parseSpawnInfodump.ts" - }, + "version": "3.0.0", + "description": "Trancode save strings for A Township Tale.", "author": "Marc Dingena", "repository": { "type": "git", @@ -27,23 +18,60 @@ "transcoder" ], "license": "MIT", + "scripts": { + "prepare": "run-s prepare:*", + "prepare:husky": "husky install", + "prepare:build": "npm run build", + "lint": "eslint --fix \"src/**/*.{ts,js}\"", + "format": "prettier --write \"+(*.md|src/**/*.{js,ts,json,md})\"", + "compile": "tsc --noEmit", + "parse": "npm run parse --prefix scripts", + "prebuild": "rimraf dist/", + "build": "run-p build:*", + "build:cjs": "tsc -p tsconfig-cjs.json", + "build:esm": "tsc -p tsconfig-esm.json", + "postbuild:cjs": "node --loader ts-node/esm ./scripts/postbuild-cjs.ts", + "test": "vitest run" + }, + "engines": { + "node": ">=20.4.0" + }, + "type": "module", + "exports": { + ".": { + "import": "./dist/esm/index.js", + "require": "./dist/cjs/index.js", + "default": "./dist/esm/index.js", + "types": "./dist/types/index.d.ts" + } + }, + "module": "./dist/esm/index.js", + "main": "./dist/cjs/index.js", + "types": "./dist/types/index.d.ts", + "files": [ + "dist/" + ], "dependencies": { "bitwise": "^2.1.0", "ieee754": "^1.2.1" }, "devDependencies": { - "@types/jest": "^27.0.2", - "@types/node": "^16.9.1", - "husky": "^4.3.8", - "jest": "^27.0.6", - "lint-staged": "^11.1.1", - "prettier": "^2.3.0", - "rimraf": "^3.0.2", - "ts-jest": "^27.0.4", + "@types/jest": "^29.5.3", + "@types/node": "^20.4.2", + "@typescript-eslint/eslint-plugin": "^6.1.0", + "@typescript-eslint/parser": "^6.1.0", + "@vitest/coverage-v8": "^0.33.0", + "eslint": "^8.19.0", + "eslint-config-prettier": "^8.5.0", + "eslint-import-resolver-typescript": "^3.3.0", + "eslint-plugin-import": "^2.26.0", + "husky": "^8.0.1", + "lint-staged": "^13.0.3", + "npm-run-all": "^4.1.5", + "prettier": "^3.0.0", + "rimraf": "^5.0.0", "ts-node": "^10.9.1", - "typescript": "^4.4.4" - }, - "files": [ - "dist/" - ] + "typescript": "^5.2.0-beta", + "vitest": "^0.33.0" + } } diff --git a/scripts/package.json b/scripts/package.json new file mode 100644 index 0000000..5ddbace --- /dev/null +++ b/scripts/package.json @@ -0,0 +1,6 @@ +{ + "type": "module", + "scripts": { + "parse": "node --loader ts-node/esm ./parseSpawnInfodump.ts" + } +} diff --git a/scripts/parseSpawnInfodump.ts b/scripts/parseSpawnInfodump.ts index 51b67a7..c03ffee 100644 --- a/scripts/parseSpawnInfodump.ts +++ b/scripts/parseSpawnInfodump.ts @@ -1,75 +1,115 @@ import fs from 'fs'; -import { Prefab } from '../src/Prefab'; -import infodump from './spawnInfodump.json'; - -const snakeCase = (name: string) => name.replace(/[\s]/g, '_'); - -const alphabetically = (a: [string, unknown], b: [string, unknown]) => (a[0] < b[0] ? -1 : 1); - -const parsedPrefabs = Object.fromEntries( - Object.entries( - infodump.reduce( - (prefabs, data) => ({ - ...prefabs, - [snakeCase(data.name)]: { - hash: data.hash, - name: data.name, - embedded: Object.fromEntries( - Object.entries( - data.embedded.reduce( - (entities, entity) => ({ - ...entities, - [`${snakeCase(entity.name)}_${entity.hash}`]: { - hash: entity.hash, - name: entity.name, - savables: Object.fromEntries( - Object.entries( - entity.savables.reduce( - (savables, savable) => ({ - ...savables, - [snakeCase(savable.name)]: { - hash: savable.hash, - name: savable.name - } - }), - {} - ) - ).sort(alphabetically) - ) - } - }), - {} - ) - ).sort(alphabetically) - ) - } - }), - {} - ) - ).sort(alphabetically) -); + +import { ATTPrefabs } from '../src/types/ATTPrefabs.js'; + +import dumpedPrefabs from './spawnInfodump.json' assert { type: 'json' }; + +type Savable = { + hash: number; + name: string; +}; + +type Embed = { + hash: number; + name: string; + savables: Savable[]; +}; + +type Prefab = { + hash: number; + name: string; + embedded: Embed[]; +}; + +function snakeCase(name: string) { + return name.replace(/[\s]/g, '_'); +} + +function alphabetically(a: [string, unknown], b: [string, unknown]) { + return a[0] < b[0] ? -1 : 1; +} + +function parseSavables(savables: Savable[]) { + return Object.fromEntries( + Object.entries( + savables.reduce( + (savables, savable) => ({ + ...savables, + [snakeCase(savable.name)]: { + hash: savable.hash, + name: snakeCase(savable.name) + } + }), + {} + ) + ).sort(alphabetically) + ); +} + +function parseEmbeds(embeds: Embed[]) { + return Object.fromEntries( + Object.entries( + embeds.reduce( + (entities, entity) => ({ + ...entities, + [`${snakeCase(entity.name)}_${entity.hash}`]: { + hash: entity.hash, + name: snakeCase(entity.name), + savables: parseSavables(entity.savables) + } + }), + {} + ) + ).sort(alphabetically) + ); +} + +function parsePrefabs(dumpedPrefabs: Prefab[]) { + return Object.fromEntries( + Object.entries( + dumpedPrefabs.reduce( + (prefabs, prefab) => ({ + ...prefabs, + [snakeCase(prefab.name)]: { + hash: prefab.hash, + name: snakeCase(prefab.name), + embedded: parseEmbeds(prefab.embedded) + } + }), + {} + ) + ).sort(alphabetically) + ); +} + +const parsedPrefabs = parsePrefabs(dumpedPrefabs); const parsedPrefabKeys = Object.keys(parsedPrefabs); -const missingPrefabs = Object.entries(Prefab).reduce( +const missingPrefabs = Object.entries(ATTPrefabs).reduce( (missing, [key, prefab]) => (parsedPrefabKeys.includes(key) ? missing : { ...missing, [key]: prefab }), {} ); -const totalPrefabs = Object.entries({ - ...missingPrefabs, - ...parsedPrefabs -}) - .sort(alphabetically) - .reduce( - (prefabs, [key, prefab]) => ({ - ...prefabs, - [key]: prefab - }), - {} - ); +const totalPrefabs = Object.fromEntries( + Object.entries({ + ...missingPrefabs, + ...parsedPrefabs + }).sort(alphabetically) +); + +const date = new Date(); +const since = `${date.getFullYear()}-${date.getMonth().toString().padStart(2, '0')}-${date + .getDate() + .toString() + .padStart(2, '0')}`; fs.writeFileSync( - './src/Prefab.ts', - `export const Prefab = ${JSON.stringify(totalPrefabs, null, 2).replace(/"/g, "'")};\n` + '../src/types/ATTPrefabs.ts', + `/** + * Parsed spawn infodump. + * @since ${since} + * @version 3.0.0 + */ +export const ATTPrefabs = ${JSON.stringify(totalPrefabs, null, 2).replace(/"/g, "'")} as const;\n` ); diff --git a/scripts/postbuild-cjs.ts b/scripts/postbuild-cjs.ts new file mode 100644 index 0000000..0db648a --- /dev/null +++ b/scripts/postbuild-cjs.ts @@ -0,0 +1,5 @@ +import fs from 'fs'; + +const packageJson = JSON.stringify({ 'type': 'commonjs' }, null, 2); + +fs.writeFileSync('./dist/cjs/package.json', `${packageJson}\n`); diff --git a/scripts/tsconfig.json b/scripts/tsconfig.json index 70d472d..8d72cc4 100644 --- a/scripts/tsconfig.json +++ b/scripts/tsconfig.json @@ -2,7 +2,8 @@ "compilerOptions": { "esModuleInterop": true, "forceConsistentCasingInFileNames": true, - "module": "commonjs", + "module": "NodeNext", + "moduleResolution": "NodeNext", "declaration": true, "declarationMap": false, "sourceMap": false, diff --git a/src/BinaryData.test.ts b/src/BinaryData.test.ts new file mode 100644 index 0000000..a8b1c7f --- /dev/null +++ b/src/BinaryData.test.ts @@ -0,0 +1,416 @@ +import type { BinaryString } from './types/BinaryString.js'; + +import { BinaryData, type BinaryDataOptions, type UnpackFloatOptions } from './BinaryData.js'; + +const BUFFER_OFFSET = 0; +const BYTE_LENGTH = 4; +const IS_LITTLE_ENDIAN = true; +const MANTISSA_LENGTH = 23; +const SIGNED_INTEGER_OFFSET = 2147483648; + +describe('new BinaryData()', () => { + describe('when given non-binary data', () => { + it('throws an error', () => { + const expectedToThrow = () => new BinaryData('topkek'); + const expectedError = new Error('Binary data string contains invalid characters. Only "0" and "1" are allowed.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); +}); + +describe('BinaryData.fromBoolean()', () => { + it('creates a BinaryData instance from a boolean', () => { + const expectedBoolean = true; + const expectedBinary = '1' as BinaryString; // => expectedBoolean as a binary boolean + const data = BinaryData.fromBoolean(expectedBoolean); + + expect(data.toBinaryString()).toStrictEqual(expectedBinary); + expect(data.toBoolean()).toStrictEqual(expectedBoolean); + }); +}); + +describe('BinaryData.fromFloat()', () => { + it('creates a BinaryData instance from a floating point number', () => { + const expectedNumber = 1337.42069; + const expectedBinary = '01000100101001110010110101110110' as BinaryString; // => expectedNumber as a binary floating point number + const data = BinaryData.fromFloat(expectedNumber); + + expect(data.toBinaryString()).toStrictEqual(expectedBinary); + expect(data.toFloat()).toBeCloseTo(expectedNumber, 4); + }); +}); + +describe('BinaryData.fromNumber()', () => { + it('creates a BinaryData instance from a number', () => { + const expectedNumber = 1337; + const expectedBinary = '10100111001' as BinaryString; // => expectedNumber as a binary number + const data = BinaryData.fromNumber(expectedNumber); + + expect(data.toBinaryString()).toStrictEqual(expectedBinary); + expect(data.toNumber()).toStrictEqual(expectedNumber); + }); +}); + +describe('BinaryData.fromSignedInteger()', () => { + it('creates a BinaryData instance from a positive signed integer', () => { + const expectedNumber = 133742069; + const expectedBinary = '10000111111110001011110111110101' as BinaryString; // => expectedNumber as a binary signed integer + const data = BinaryData.fromSignedInteger(expectedNumber); + + expect(data.toBinaryString()).toStrictEqual(expectedBinary); + expect(data.toSignedInteger()).toStrictEqual(expectedNumber); + }); + + it('creates a BinaryData instance from a negative signed integer', () => { + const expectedNumber = -694201337; + const expectedBinary = '01010110100111110101010000000111' as BinaryString; // => expectedNumber as a binary signed integer + const data = BinaryData.fromSignedInteger(expectedNumber); + + expect(data.toBinaryString()).toStrictEqual(expectedBinary); + expect(data.toSignedInteger()).toStrictEqual(expectedNumber); + }); + + describe('when an options argument is passed', () => { + const options: BinaryDataOptions = {}; + + beforeEach(() => { + options.signedIntegerOffset = SIGNED_INTEGER_OFFSET; + }); + + it('creates a BinaryData instance from a positive signed integer', () => { + const expectedNumber = 133742069; + const expectedBinary = '10000111111110001011110111110101' as BinaryString; // => expectedNumber as a binary signed integer + const data = BinaryData.fromSignedInteger(expectedNumber, options); + + expect(data.toBinaryString()).toStrictEqual(expectedBinary); + expect(data.toSignedInteger()).toStrictEqual(expectedNumber); + }); + + it('creates a BinaryData instance from a negative signed integer', () => { + const expectedNumber = -694201337; + const expectedBinary = '01010110100111110101010000000111' as BinaryString; // => expectedNumber as a binary signed integer + const data = BinaryData.fromSignedInteger(expectedNumber, options); + + expect(data.toBinaryString()).toStrictEqual(expectedBinary); + expect(data.toSignedInteger()).toStrictEqual(expectedNumber); + }); + }); +}); + +describe('BinaryData.fromUnsignedInteger()', () => { + it('creates a BinaryData instance from an unsigned integer', () => { + const expectedNumber = 133742069; + const expectedBinary = '00000111111110001011110111110101' as BinaryString; // => expectedNumber as a binary unsigned integer + const data = BinaryData.fromUnsignedInteger(expectedNumber); + + expect(data.toBinaryString()).toStrictEqual(expectedBinary); + expect(data.toUnsignedInteger()).toStrictEqual(expectedNumber); + }); +}); + +describe('BinaryData.fromUnsignedIntegerArray()', () => { + it('creates a BinaryData instance from an array of unsigned integers', () => { + const expectedNumbers = [1337, 420, 69]; + const expectedBinary = + '000000000000000000000101001110010000000000000000000000011010010000000000000000000000000001000101' as BinaryString; // => expectedNumbers as binary data + const data = BinaryData.fromUnsignedIntegerArray(expectedNumbers); + + expect(data.toBinaryString()).toStrictEqual(expectedBinary); + expect(data.toUnsignedIntegerArray()).toStrictEqual(expectedNumbers); + }); +}); + +describe('BinaryData.fromUnsignedLong()', () => { + it('creates a BinaryData instance from an unsigned long integer', () => { + const expectedNumber = 133742069; + const expectedBinary = '0000011111111000101111011111010100000000000000000000000000000000' as BinaryString; // => expectedNumber as a binary unsigned long integer + const data = BinaryData.fromUnsignedLong(expectedNumber); + + expect(data.toBinaryString()).toStrictEqual(expectedBinary); + expect(data.toUnsignedLong()).toStrictEqual(expectedNumber); + }); +}); + +describe('BinaryData.fromUnsignedShort()', () => { + it('creates a BinaryData instance from an unsigned short integer', () => { + const expectedNumber = 1337; + const expectedBinary = '0000010100111001' as BinaryString; // => expectedNumber as a binary unsigned short integer + const data = BinaryData.fromUnsignedShort(expectedNumber); + + expect(data.toBinaryString()).toStrictEqual(expectedBinary); + expect(data.toUnsignedShort()).toStrictEqual(expectedNumber); + }); +}); + +describe('BinaryData.isBinaryString()', () => { + it('asserts that a string with valid binary is a BinaryString', () => { + const data = '01110110100110101'; + const result = BinaryData.isBinaryString(data); + + expect(result).toBe(true); + expect(data).toStrictEqual('01110110100110101' as BinaryString); + }); + + it('asserts that a string with invalid binary is not a BinaryString', () => { + const data = '011abc10110100110101'; + const result = BinaryData.isBinaryString(data); + + expect(result).toBe(false); + expect(data).toStrictEqual('011abc10110100110101'); + }); +}); + +describe('BinaryData.isSaveString()', () => { + it('asserts that a string with valid binary is a SaveString', () => { + const data = '1111,2222,3333,|4,5555,1,6666,2,7777,3,8888,4,'; + const result = BinaryData.isSaveString(data); + + expect(result).toBe(true); + expect(data).toStrictEqual('1111,2222,3333,|4,5555,1,6666,2,7777,3,8888,4,' as BinaryString); + }); + + it('asserts that a string with invalid binary is not a SaveString', () => { + const data = '1111,2222,3333,|4,5555,1,6666,2,7777,3,8888,4'; // missing trailing comma + const result = BinaryData.isBinaryString(data); + + expect(result).toBe(false); + expect(data).toStrictEqual('1111,2222,3333,|4,5555,1,6666,2,7777,3,8888,4'); + }); +}); + +describe('BinaryData.packFloat()', () => { + it('converts a JavaScript number into an IEEE754 integer', () => { + const packedFloat = BinaryData.packFloat(1337.42069); + + expect(packedFloat).toEqual(1151806838); + }); +}); + +describe('BinaryData.toBinaryString()', () => { + it('expresses binary verbatim', () => { + const binary = '11110111001100010000'; + const data = new BinaryData(binary); + + expect(data.toBinaryString()).toStrictEqual(binary); + }); +}); + +describe('BinaryData.toBoolean()', () => { + it('expresses binary as a boolean', () => { + const expectedBoolean = true; + const binary = '1'; // => expectedBoolean as a binary boolean + const data = new BinaryData(binary); + + expect(data.toBoolean()).toStrictEqual(expectedBoolean); + }); + + describe('when binary data is not exactly one bit', () => { + it('throws an error', () => { + const expectedToThrow = () => new BinaryData('01').toBoolean(); + const expectedError = new Error('Boolean binary string must be 1 bit.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); +}); + +describe('BinaryData.toChar()', () => { + it('expresses binary as a char', () => { + const expectedChar = 'A'; + const binary = '01000001'; // => expectedChar as a binary boolean + const data = new BinaryData(binary); + + expect(data.toChar()).toStrictEqual(expectedChar); + }); + + describe('when binary data is not exactly eight bits', () => { + it('throws an error', () => { + const expectedToThrow = () => new BinaryData('01').toChar(); + const expectedError = new Error('Char binary string must be 8 bits.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); +}); + +describe('BinaryData.toFloat()', () => { + describe('when the binary string is of incorrect length', () => { + it('throws an error', () => { + const expectedToThrow = () => new BinaryData('0').toFloat(); + const expectedError = new Error('Floating point number binary string must be 32 bits.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + it('expresses binary as a number', () => { + const expectedNumber = 1337.42069; + const binary = '01000100101001110010110101110110'; // => expectedNumber as a binary number + const data = new BinaryData(binary); + + expect(data.toFloat()).toBeCloseTo(expectedNumber, 4); + }); +}); + +describe('BinaryData.toNumber()', () => { + it('expresses binary as a number', () => { + const expectedNumber = 1337; + const binary = '10100111001'; // => expectedNumber as a binary number + const data = new BinaryData(binary); + + expect(data.toNumber()).toStrictEqual(expectedNumber); + }); +}); + +describe('BinaryData.toSignedInteger()', () => { + describe('when the binary string is of incorrect length', () => { + it('throws an error', () => { + const expectedToThrow = () => new BinaryData('0').toSignedInteger(); + const expectedError = new Error('Signed integer binary string must be 32 bits.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + it('expresses binary as a positive signed integer', () => { + const expectedNumber = 133742069; + const binary = '10000111111110001011110111110101'; // => expectedNumber as a binary signed integer + const data = new BinaryData(binary); + + expect(data.toSignedInteger()).toStrictEqual(expectedNumber); + }); + + it('expresses binary as a negative signed integer', () => { + const expectedNumber = -694201337; + const binary = '01010110100111110101010000000111'; // => expectedNumber as a binary signed integer + const data = new BinaryData(binary); + + expect(data.toSignedInteger()).toStrictEqual(expectedNumber); + }); + + describe('when the constructor options are configured', () => { + const options: BinaryDataOptions = {}; + + beforeEach(() => { + options.signedIntegerOffset = SIGNED_INTEGER_OFFSET; + }); + + it('expresses binary as a positive signed integer', () => { + const expectedNumber = 133742069; + const binary = '10000111111110001011110111110101'; // => expectedNumber as a binary signed integer + const data = new BinaryData(binary, options); + + expect(data.toSignedInteger()).toStrictEqual(expectedNumber); + }); + + it('expresses binary as a negative signed integer', () => { + const expectedNumber = -694201337; + const binary = '01010110100111110101010000000111'; // => expectedNumber as a binary signed integer + const data = new BinaryData(binary, options); + + expect(data.toSignedInteger()).toStrictEqual(expectedNumber); + }); + }); +}); + +describe('BinaryData.toUnsignedInteger()', () => { + describe('when the binary string is of incorrect length', () => { + it('throws an error', () => { + const expectedToThrow = () => new BinaryData('0').toUnsignedInteger(); + const expectedError = new Error('Unsigned integer binary string must be 32 bits.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + it('expresses binary as an unsigned integer', () => { + const expectedNumber = 133742069; + const binary = '00000111111110001011110111110101'; // => expectedNumber as an unsigned integer + const data = new BinaryData(binary); + + expect(data.toUnsignedInteger()).toStrictEqual(expectedNumber); + }); +}); + +describe('BinaryData.toUnsignedIntegerArray()', () => { + describe('when the binary string is of incorrect length', () => { + it('throws an error', () => { + const expectedToThrow = () => new BinaryData('0').toUnsignedIntegerArray(); + const expectedError = new Error('Bit count must be divisible by 32.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + it('expresses binary as an unsigned integer', () => { + const expectedNumbers = [1337, 420, 69]; + const binary = '000000000000000000000101001110010000000000000000000000011010010000000000000000000000000001000101'; // => expectedNumbers as binary data + const data = new BinaryData(binary); + + expect(data.toUnsignedIntegerArray()).toStrictEqual(expectedNumbers); + }); +}); + +describe('BinaryData.toUnsignedLong()', () => { + describe('when the binary string is of incorrect length', () => { + it('throws an error', () => { + const expectedToThrow = () => new BinaryData('0').toUnsignedLong(); + const expectedError = new Error('Unsigned long integer binary string must be 64 bits.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + it('expresses binary as an unsigned long integer', () => { + const expectedNumber = 133742069; + const binary = '0000011111111000101111011111010100000000000000000000000000000000'; // => expectedNumber as an unsigned long integer + const data = new BinaryData(binary); + + expect(data.toUnsignedLong()).toStrictEqual(expectedNumber); + }); +}); + +describe('BinaryData.toUnsignedShort()', () => { + describe('when the binary string is of incorrect length', () => { + it('throws an error', () => { + const expectedToThrow = () => new BinaryData('0').toUnsignedShort(); + const expectedError = new Error('Unsigned short integer binary string must be 16 bits.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + it('expresses binary as an unsigned short integer', () => { + const expectedNumber = 1337; + const binary = '0000010100111001'; // => expectedNumber as an unsigned short integer + const data = new BinaryData(binary); + + expect(data.toUnsignedShort()).toStrictEqual(expectedNumber); + }); +}); + +describe('BinaryData.unpackFloat()', () => { + it('converts an IEEE754 integer into a JavaScript number', () => { + const unpackedFloat = BinaryData.unpackFloat(1151806838); + + expect(unpackedFloat).toBeCloseTo(1337.42069, 4); + }); + + describe('when an options argument is passed', () => { + const options: UnpackFloatOptions = {}; + + beforeEach(() => { + options.bufferOffset = BUFFER_OFFSET; + options.byteLength = BYTE_LENGTH; + options.isLittleEndian = IS_LITTLE_ENDIAN; + options.mantissaLength = MANTISSA_LENGTH; + }); + + it('converts an IEEE754 integer into a JavaScript number', () => { + const unpackedFloat = BinaryData.unpackFloat(1151806838, options); + + expect(unpackedFloat).toBeCloseTo(1337.42069, 4); + }); + }); +}); diff --git a/src/BinaryData.ts b/src/BinaryData.ts new file mode 100644 index 0000000..6eb370e --- /dev/null +++ b/src/BinaryData.ts @@ -0,0 +1,481 @@ +import type { BinaryString } from './types/BinaryString.js'; +import type { SaveString } from './types/SaveString.js'; +import type { Bit } from 'bitwise/types.js'; + +import { integer as bitwiseInteger } from 'bitwise'; +import { read as ieee754Read, write as ieee754Write } from 'ieee754'; + +export type BinaryDataOptions = { + signedIntegerOffset?: number; +}; + +export type UnpackFloatOptions = { + bufferOffset?: number; + byteLength?: number; + isLittleEndian?: boolean; + mantissaLength?: number; +}; + +const BUFFER_OFFSET = 0; +const BYTE_LENGTH = 4; +const IS_LITTLE_ENDIAN = true; +const MANTISSA_LENGTH = 23; +const SIGNED_INTEGER_OFFSET = 2147483648; + +/** + * Deals with data types as understood by _A Township Tale_ game servers. + * + * @see [Class: `BinaryData`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/BinaryData.md) + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const data = new BinaryData('11110111001100010000'); + * // or + * const data = BinaryData.fromBoolean(true); + * // or + * const data = BinaryData.fromChar('x'); + * // or + * const data = BinaryData.fromFloat(0.69); + * // or + * const data = BinaryData.fromNumber(1337); + * // or + * const data = BinaryData.fromSignedInteger(-420); + * // or + * const data = BinaryData.fromUnsignedInteger(69420); + * // or + * const data = BinaryData.fromUnsignedIntegerArray([69420, 133769]); + * // or + * const data = BinaryData.fromUnsignedLong(133742069); + * // or + * const data = BinaryData.fromUnsignedShort(420); + */ +export class BinaryData { + private readonly binary: BinaryString; + private readonly signedIntegerOffset: number; + + /** + * 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. + * + * @see [Class: `BinaryData`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/BinaryData.md) + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const data = new BinaryData('11110111001100010000', { + * signedIntegerOffset: 2147483648 + * }); + */ + constructor(binary: string, options?: BinaryDataOptions) { + if (!BinaryData.isBinaryString(binary)) { + throw new Error('Binary data string contains invalid characters. Only "0" and "1" are allowed.'); + } + + this.binary = binary; + this.signedIntegerOffset = options?.signedIntegerOffset ?? SIGNED_INTEGER_OFFSET; + } + + /** + * Creates a BinaryData instance from the given boolean. + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const data = BinaryData.fromBoolean(true); + */ + static fromBoolean(boolean: boolean, options?: BinaryDataOptions): BinaryData { + const data = Number(boolean).toString(); + + return new BinaryData(data, options); + } + + /** + * Creates a BinaryData instance from the given character. + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const data = BinaryData.fromChar('x'); + */ + static fromChar(char: string, options?: BinaryDataOptions): BinaryData { + const charCode = char.charCodeAt(0); + const data = BinaryData.fromNumber(charCode).toBinaryString().padStart(8, '0'); + + return new BinaryData(data, options); + } + + /** + * Creates a BinaryData instance from the given floating point number. + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const data = BinaryData.fromFloat(0.69); + */ + static fromFloat(float: number, options?: BinaryDataOptions): BinaryData { + const packedFloat = BinaryData.packFloat(float); + + return BinaryData.fromUnsignedInteger(packedFloat, options); + } + + /** + * Creates a BinaryData instance from the given number. + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const data = BinaryData.fromNumber(1337); + */ + static fromNumber(number: number, options?: BinaryDataOptions): BinaryData { + const data = number.toString(2) as BinaryString; + + return new BinaryData(data, options); + } + + /** + * Creates a BinaryData instance from the given signed integer. + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const data = BinaryData.fromSignedInteger(-420); + */ + static fromSignedInteger(signedInteger: number, options?: BinaryDataOptions): BinaryData { + const isPositive = signedInteger >= 0; + const integer = isPositive + ? signedInteger + : signedInteger + (options?.signedIntegerOffset ?? SIGNED_INTEGER_OFFSET); + + const isPositiveBit = Number(isPositive).toString(); + const integerBits = BinaryData.fromNumber(integer).toBinaryString().padStart(32, '0'); + + const data = `${isPositiveBit}${integerBits.slice(1)}`; + + return new BinaryData(data, options); + } + + /** + * Creates a BinaryData instance from the given unsigned integer. + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const data = BinaryData.fromUnsignedInteger(69420); + */ + static fromUnsignedInteger(unsignedInteger: number, options?: BinaryDataOptions): BinaryData { + const binary = BinaryData.fromNumber(unsignedInteger).toBinaryString().padStart(32, '0'); + + return new BinaryData(binary, options); + } + + /** + * Creates a BinaryData instance from the given comma-separated array of unsigned integers. + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const data = BinaryData.fromUnsignedIntegerArray([69420, 133769]); + */ + static fromUnsignedIntegerArray(unsignedIntegerArray: number[], options?: BinaryDataOptions): BinaryData { + const binary = unsignedIntegerArray + .map(unsignedInteger => BinaryData.fromUnsignedInteger(unsignedInteger, options).toBinaryString()) + .join(''); + + return new BinaryData(binary, options); + } + + /** + * Creates a BinaryData instance from the given unsigned long integer. + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const data = BinaryData.fromUnsignedLong(133742069); + */ + static fromUnsignedLong(unsignedLong: number, options?: BinaryDataOptions): BinaryData { + const binary = BinaryData.fromNumber(unsignedLong).toBinaryString().padStart(64, '0'); + const reorderedBinary = `${binary.slice(32)}${binary.slice(0, 32)}`; + + return new BinaryData(reorderedBinary, options); + } + + /** + * Creates a BinaryData instance from the given unsigned short integer. + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const data = BinaryData.fromUnsignedShort(420); + */ + static fromUnsignedShort(unsignedShort: number, options?: BinaryDataOptions): BinaryData { + const binary = BinaryData.fromNumber(unsignedShort).toBinaryString().padStart(16, '0'); + + return new BinaryData(binary, options); + } + + /** + * Confirms whether `data` is a string of binary data, i.e. a string of zeroes and ones. + * + * @example + * 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 + * } + */ + static isBinaryString(data: string): data is BinaryString { + const binaryStringPattern = /^[01]+$/; + + return binaryStringPattern.test(data); + } + + /** + * Confirms whether `data` is a string of unsigned integers and chunk versioning pairs. + * + * This is also a type assertion function, so if the passed `string` is asserted as a + * `BinaryString`, it will be considered as such after calling this function. + * + * @example + * 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 + * } + */ + static isSaveString(data: string): data is SaveString { + const saveStringPattern = /^[0-9,|]+$/; + + const isValidCharacters = saveStringPattern.test(data); + const isValidLastCharacter = data.slice(-1) === ','; + + return isValidCharacters && isValidLastCharacter; + } + + /** + * Converts a JavaScript floating point number into an IEEE754 integer. + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const packedFloat = BinaryData.packFloat(1337.42069); + * // `packedFloat` is `1151806838` + */ + static packFloat(number: number): number { + const buffer = Buffer.from(new Uint8Array(4)); + let bits = 0; + + ieee754Write(buffer, number, 0, true, 23, 4); + + const integer = buffer.readUInt32LE(0); + + for (let i = 0; i < 32; i++) { + const bit: Bit = bitwiseInteger.getBit(integer, 31 - i); + + bits = bitwiseInteger.setBit(bits, 31 - i, bit); + } + + return bits >>> 0; + } + + /** + * Returns the binary data as a `BinaryString`. + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const data = new BinaryData('1111011100110001000'); + * + * const binary = data.toBinaryString(); + * // `binary` is `'1111011100110001000'` + */ + toBinaryString(): BinaryString { + return this.binary; + } + + /** + * Returns the boolean represenation of the binary data. + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const data = new BinaryData('1'); + * + * const boolean = data.toBoolean(); + * // `boolean` is `true` + */ + toBoolean(): boolean { + if (this.binary.length !== 1) throw new Error('Boolean binary string must be 1 bit.'); + + return Boolean(Number(this.binary)); + } + + /** + * Returns the character represenation of the binary data. + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const data = new BinaryData('01000001'); + * + * const char = data.toChar(); + * // `char` is `'A'` + */ + toChar(): string { + if (this.binary.length !== 8) throw new Error('Char binary string must be 8 bits.'); + + return String.fromCharCode(this.toNumber()); + } + + /** + * Returns the floating point number represenation of the binary data. + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const data = new BinaryData('01000100101001110010110101110110'); + * + * const float = data.toFloat(); + * // `float` is approximately `1337.42069` + */ + toFloat(): number { + if (this.binary.length !== 32) throw new Error('Floating point number binary string must be 32 bits.'); + + const unsignedInteger = this.toUnsignedInteger(); + + return BinaryData.unpackFloat(unsignedInteger); + } + + /** + * Returns the numeric represenation of the binary data. + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const data = new BinaryData('10100111001'); + * + * const number = data.toNumber(); + * // `number` is `1337` + */ + toNumber(): number { + return Number(`0b${this.binary}`); + } + + /** + * Returns the signed integer representation of the binary data. + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const data = new BinaryData('01010110100111110101010000000111'); + * + * const signedInteger = data.toSignedInteger(); + * // `signedInteger` is `-694201337` + */ + toSignedInteger(): number { + if (this.binary.length !== 32) throw new Error('Signed integer binary string must be 32 bits.'); + + const isPositive = Boolean(Number(this.binary.slice(0, 1))); + const integer = Number(`0b0${this.binary.slice(1)}`); + + return isPositive ? integer : integer - this.signedIntegerOffset; + } + + /** + * Returns the unsigned integer representation of the binary data. + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const data = new BinaryData('00000111111110001011110111110101'); + * + * const unsignedInteger = data.toUnsignedInteger(); + * // `unsignedInteger` is `133742069` + */ + toUnsignedInteger(): number { + if (this.binary.length !== 32) throw new Error('Unsigned integer binary string must be 32 bits.'); + + return this.toNumber(); + } + + /** + * Returns the binary data as a comma-separated array of unsigned integers. + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const data = new BinaryData('000000000000000000000101001110010000000000000000000000011010010000000000000000000000000001000101'); + * + * const unsignedIntegers = data.toUnsignedIntegerArray(); + * // `unsignedIntegers` is `[1337, 420, 69]` + */ + toUnsignedIntegerArray(): number[] { + if (this.binary.length % 32 !== 0) throw Error('Bit count must be divisible by 32.'); + + const chunks = this.binary.match(/.{32}/g) as RegExpMatchArray; + + return chunks.map(bits => new BinaryData(bits).toUnsignedInteger()); + } + + /** + * Returns the unsigned long integer representation of the binary data. + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const data = new BinaryData('0000011111111000101111011111010100000000000000000000000000000000'); + * + * const unsignedLongInteger = data.toUnsignedLong(); + * // `unsignedLongInteger` is `133742069` + */ + toUnsignedLong(): number { + if (this.binary.length !== 64) throw new Error('Unsigned long integer binary string must be 64 bits.'); + + return Number(`0b${this.binary.slice(32)}${this.binary.slice(0, 32)}`); + } + + /** + * Returns the unsigned short integer representation of the binary data. + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const data = new BinaryData('0000010100111001'); + * + * const unsignedShortInteger = data.toUnsignedShort(); + * // `unsignedShortInteger` is `1337` + */ + toUnsignedShort(): number { + if (this.binary.length !== 16) throw new Error('Unsigned short integer binary string must be 16 bits.'); + + return this.toNumber(); + } + + /** + * Converts an IEEE754 integer into a JavaScript floating point number. + * + * @example + * import { BinaryData } from 'att-string-transcoder'; + * + * const unpackedFloat = BinaryData.unpackFloat(1151806838); + * // `unpackedFloat` is approximately `1337.42069` + */ + static unpackFloat(unsignedInteger: number, options?: UnpackFloatOptions): number { + const bufferOffset = options?.bufferOffset ?? BUFFER_OFFSET; + const byteLength = options?.byteLength ?? BYTE_LENGTH; + const isLittleEndian = options?.isLittleEndian ?? IS_LITTLE_ENDIAN; + const mantissaLength = options?.mantissaLength ?? MANTISSA_LENGTH; + + const buffer = Buffer.from(new Uint8Array(4)); + + buffer.writeUInt32LE(unsignedInteger); + + return ieee754Read(buffer, bufferOffset, isLittleEndian, mantissaLength, byteLength); + } +} diff --git a/src/BinaryReader.test.ts b/src/BinaryReader.test.ts new file mode 100644 index 0000000..a839d3b --- /dev/null +++ b/src/BinaryReader.test.ts @@ -0,0 +1,155 @@ +import type { BinaryString } from './types/BinaryString.js'; + +import { BinaryReader } from './BinaryReader.js'; + +describe('new BinaryReader()', () => { + describe('when given non-binary data', () => { + it('throws an error', () => { + const data = 'topkek'; + const expectedToThrow = () => new BinaryReader(data); + const expectedError = new Error('Binary data string contains invalid characters. Only "0" and "1" are allowed.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); +}); + +describe('BinaryReader.readBits()', () => { + it('returns the amount of given bits', () => { + const data = '0001001101111111' as BinaryString; + const reader = new BinaryReader(data); + const read = reader.readBits(8); + + expect(read).toStrictEqual('00010011'); + }); + + it('continues to read on subsequent reads', () => { + const data = '0001001101111111' as BinaryString; + const reader = new BinaryReader(data); + const read1 = reader.readBits(8); + const read2 = reader.readBits(4); + const read3 = reader.readBits(4); + + expect(read1).toStrictEqual('00010011'); + expect(read2).toStrictEqual('0111'); + expect(read3).toStrictEqual('1111'); + }); + + describe('when reading more bits than are stored in the binary string data', () => { + it('throws an error', () => { + const data = '0001001101111111' as BinaryString; + const reader = new BinaryReader(data); + const expectedToThrow = () => reader.readBits(data.length + 1); + const expectedError = new Error( + `Cannot read ${data.length + 1} bits from binary at index 0. Binary is only ${data.length} bits.` + ); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); +}); + +describe('BinaryReader.readBoolean()', () => { + it('returns a Boolean', () => { + const data = '10' as BinaryString; + const reader = new BinaryReader(data); + + expect(reader.readBoolean()).toStrictEqual(true); + expect(reader.readBoolean()).toStrictEqual(false); + }); +}); + +describe('BinaryReader.readChar()', () => { + it('returns a single character string', () => { + const data = '01000001011000100110001101000100' as BinaryString; // "AbcD" + const reader = new BinaryReader(data); + + expect(reader.readChar()).toStrictEqual('A'); + expect(reader.readChar()).toStrictEqual('b'); + expect(reader.readChar()).toStrictEqual('c'); + expect(reader.readChar()).toStrictEqual('D'); + }); +}); + +describe('BinaryReader.readFloat()', () => { + it('returns a floating point number', () => { + const expectedNumber = 1337.42069; + const data = '01000100101001110010110101110110' as BinaryString; // ~1337.42069 + const reader = new BinaryReader(data); + + expect(reader.readFloat()).toBeCloseTo(expectedNumber, 4); + }); +}); + +describe('BinaryReader.readSignedInteger()', () => { + it('returns a signed integer', () => { + const expectedNumber = -694201337; + const data = '01010110100111110101010000000111' as BinaryString; // -694201337 + const reader = new BinaryReader(data); + + expect(reader.readSignedInteger()).toStrictEqual(expectedNumber); + }); +}); + +describe('BinaryReader.readString()', () => { + it('returns a string', () => { + const expectedString = 'Hello, world!'; + const data = + '000000000000110101001000011001010010110001101111011011000110110001110010011011110111011100100000011011000110010000100001' as BinaryString; + const reader = new BinaryReader(data); + + expect(reader.readString()).toStrictEqual(expectedString); + }); + + describe('when the string has length of zero', () => { + it('returns an empty string', () => { + const expectedString = ''; + const data = '0000000000000000' as BinaryString; // length bits that are read before interpreting string data + const reader = new BinaryReader(data); + + expect(reader.readString()).toStrictEqual(expectedString); + }); + }); + + describe('when the binary string data is not aligned', () => { + it('aligns the bits and returns a string', () => { + const expectedString = 'Hello, world!'; + const data = + '11100000000000011010000001001000011011110110110001101100011001010110111101110111001000000010110000100001011001000110110001110010' as BinaryString; + const reader = new BinaryReader(data); + + expect(reader.readBits(3)).toStrictEqual('111'); + expect(reader.readString()).toStrictEqual(expectedString); + }); + }); +}); + +describe('BinaryReader.readUnsignedInteger()', () => { + it('returns an unsigned integer', () => { + const expectedNumber = 133742069; + const data = '00000111111110001011110111110101' as BinaryString; + const reader = new BinaryReader(data); + + expect(reader.readUnsignedInteger()).toStrictEqual(expectedNumber); + }); +}); + +describe('BinaryReader.readUnsignedLong()', () => { + it('returns an unsigned integer', () => { + const expectedNumber = 133742069; + const data = '0000011111111000101111011111010100000000000000000000000000000000' as BinaryString; + const reader = new BinaryReader(data); + + expect(reader.readUnsignedLong()).toStrictEqual(expectedNumber); + }); +}); + +describe('BinaryReader.readUnsignedShort()', () => { + it('returns an unsigned integer', () => { + const expectedNumber = 1337; + const data = '0000010100111001' as BinaryString; + const reader = new BinaryReader(data); + + expect(reader.readUnsignedShort()).toStrictEqual(expectedNumber); + }); +}); diff --git a/src/BinaryReader.ts b/src/BinaryReader.ts new file mode 100644 index 0000000..934de6d --- /dev/null +++ b/src/BinaryReader.ts @@ -0,0 +1,243 @@ +import type { BinaryString } from './types/BinaryString.js'; + +import { BinaryData, type BinaryDataOptions } from './BinaryData.js'; + +/** + * Handles the controlled consumption of binary data from ATT save strings. + * + * @see [Class: `BinaryReader`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/BinaryReader.md) + * + * @example + * import { BinaryReader } from 'att-string-transcoder'; + * + * const reader = new BinaryReader('11110111001100010000'); + * + * const firstByte = reader.readBits(8); + * // `firstByte` is `'11110111'` + */ +export class BinaryReader { + private data: BinaryString; + private index = { current: 0 }; + private length: number; + + /** + * Creates a reader to extract information from `data` using various read methods. + * + * @see [Class: `BinaryReader`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/BinaryReader.md) + * + * @example + * import { BinaryReader } from 'att-string-transcoder'; + * + * const reader = new BinaryReader('11110111001100010000'); + */ + constructor(data: string) { + if (!BinaryData.isBinaryString(data)) { + throw new Error('Binary data string contains invalid characters. Only "0" and "1" are allowed.'); + } + + this.data = data; + this.length = data.length; + } + + /** + * Reads the next `bitCount` bits from the binary string. + * + * @example + * import { BinaryReader } from 'att-string-transcoder'; + * + * const reader = new BinaryReader('11110111001100010000'); + * + * const firstByte = reader.readBits(8); + * // `firstByte` is `'11110111'` + */ + readBits(bitCount: number): BinaryString { + if (this.index.current + bitCount > this.length) { + throw Error( + `Cannot read ${bitCount} bits from binary at index ${this.index.current}. Binary is only ${this.length} bits.` + ); + } + + return this.data.slice(this.index.current, (this.index.current += bitCount)) as BinaryString; + } + + /** + * Reads the next bit from the binary string and returns `true` for `"1"` and `false` for `"0"`. + * + * @example + * 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` + */ + readBoolean(options?: BinaryDataOptions): boolean { + const bit = this.readBits(1); + + return new BinaryData(bit, options).toBoolean(); + } + + /** + * Reads the next 8 bits from the binary string and returns the reconstructed string character. + * + * @example + * 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'` + */ + readChar(options?: BinaryDataOptions): string { + const bits = this.readBits(8); + + return new BinaryData(bits, options).toChar(); + } + + /** + * Reads the next 32 bits from the binary string and returns the reconstructed floating point number. + * + * @example + * import { BinaryReader } from 'att-string-transcoder'; + * + * const reader = new BinaryReader('01000100101001110010110101110110'); + * + * const float = reader.readFloat(); + * // `float` is approximately `1337.42069` + */ + readFloat(options?: BinaryDataOptions): number { + const bits = this.readBits(32); + + return new BinaryData(bits, options).toFloat(); + } + + /** + * Reads the next 32 bits from the binary string and returns the reconstructed signed integer. + * + * @example + * import { BinaryReader } from 'att-string-transcoder'; + * + * const reader = new BinaryReader('01010110100111110101010000000111'); + * + * const signedInteger = reader.readSignedInteger(); + * // `signedInteger` is `-694201337` + */ + readSignedInteger(options?: BinaryDataOptions): number { + const bits = this.readBits(32); + + return new BinaryData(bits, options).toSignedInteger(); + } + + /** + * Reads the next 16 bits from the binary string, then reads the number of bits as instructed and + * returns the reconstructed string text. + * + * @example + * import { BinaryReader } from 'att-string-transcoder'; + * + * const reader = new BinaryReader('000000000000110101001000011001010010110001101111011011000110110001110010011011110111011100100000011011000110010000100001'); + * + * const string = reader.readString(); + * // `string` is `'Hello, world!'` + */ + readString(): string { + const length = this.readUnsignedShort(); + + if (length === 0) return ''; + + /* Align bits. */ + const offset = this.index.current % 8 === 0 ? 0 : 8 - (this.index.current % 8); + + if (offset > 0) this.readBits(offset); + + let currentByte = (this.index.current % 32) / 8; + + /* Read garbled text from binary. */ + let textBuffer = ''; + + while (textBuffer.length < length) { + textBuffer += this.readChar(); + } + + /* Untangle garbled text. */ + let text = ''; + let bufferIndex = 0; + + while (currentByte < 4 && bufferIndex < length) { + text += textBuffer[bufferIndex++]; + currentByte++; + } + + while (bufferIndex + 4 <= length) { + const chars = textBuffer.substr(bufferIndex, 4); + + text += chars.split('').reverse().join(''); + bufferIndex += 4; + } + + while (bufferIndex < length) { + text += textBuffer[bufferIndex++]; + } + + return text; + } + + /** + * Reads the next 32 bits from the binary string and returns the reconstructed unsigned integer. + * + * @example + * import { BinaryReader } from 'att-string-transcoder'; + * + * const reader = new BinaryReader('00000111111110001011110111110101'); + * + * const unsignedInteger = reader.readUnsignedInteger(); + * // `unsignedInteger` is `133742069` + */ + readUnsignedInteger(options?: BinaryDataOptions): number { + const bits = this.readBits(32); + + return new BinaryData(bits, options).toUnsignedInteger(); + } + + /** + * Reads the next 64 bits from the binary string and returns the reconstructed unsigned long integer. + * + * @example + * import { BinaryReader } from 'att-string-transcoder'; + * + * const reader = new BinaryReader('0000011111111000101111011111010100000000000000000000000000000000'); + * + * const unsignedLongInteger = reader.readUnsignedLong(); + * // `unsignedLongInteger` is `133742069` + */ + readUnsignedLong(options?: BinaryDataOptions): number { + const bits = this.readBits(64); + + return new BinaryData(bits, options).toUnsignedLong(); + } + + /** + * Reads the next 16 bits from the binary string and returns the reconstructed unsigned short integer. + * + * @example + * import { BinaryReader } from 'att-string-transcoder'; + * + * const reader = new BinaryReader('0000010100111001'); + * + * const unsignedShortInteger = reader.readUnsignedShort(); + * // `unsignedShortInteger` is `1337` + */ + readUnsignedShort(options?: BinaryDataOptions): number { + const bits = this.readBits(16); + + return new BinaryData(bits, options).toUnsignedShort(); + } +} diff --git a/src/BinaryWriter.test.ts b/src/BinaryWriter.test.ts new file mode 100644 index 0000000..882557b --- /dev/null +++ b/src/BinaryWriter.test.ts @@ -0,0 +1,146 @@ +import { BinaryWriter } from './BinaryWriter.js'; + +let writer: BinaryWriter; + +beforeEach(() => { + writer = new BinaryWriter(); +}); + +describe('BinaryWriter.flush()', () => { + it('returns the accumulated data inside BinaryWriter', () => { + const flush1 = writer.flush(); + writer.writeBits('0001'); + const flush2 = writer.flush(); + writer.writeBits('01'); + writer.writeBits('01'); + const flush3 = writer.flush(); + + expect(flush1).toStrictEqual(''); + expect(flush2).toStrictEqual('0001'); + expect(flush3).toStrictEqual('0101'); + }); +}); + +describe('BinaryWriter.writeBits()', () => { + it('stores the bits verbatim as a binary string', () => { + const bits = '0001001101111111'; + const expectedBinary = bits; + writer.writeBits(bits); + + expect(writer.flush()).toStrictEqual(expectedBinary); + }); + + describe('when given non-binary data', () => { + it('throws an error', () => { + const expectedToThrow = () => new BinaryWriter().writeBits('topkek'); + const expectedError = new Error('Binary data string contains invalid characters. Only "0" and "1" are allowed.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); +}); + +describe('BinaryWriter.writeBoolean()', () => { + it('stores the boolean as a binary string', () => { + const boolean = true; + const expectedBinary = '1'; + writer.writeBoolean(boolean); + + expect(writer.flush()).toStrictEqual(expectedBinary); + }); +}); + +describe('BinaryWriter.writeChar()', () => { + it('stores the character as a binary string', () => { + const char = 'A'; + const expectedBinary = '01000001'; + writer.writeChar(char); + + expect(writer.flush()).toStrictEqual(expectedBinary); + }); +}); + +describe('BinaryWriter.writeFloat()', () => { + it('stores the floating point number as a binary string', () => { + const float = 1337.42069; + const expectedBinary = '01000100101001110010110101110110'; + writer.writeFloat(float); + + expect(writer.flush()).toStrictEqual(expectedBinary); + }); +}); + +describe('BinaryWriter.writeSignedInteger()', () => { + it('stores the signed integer as a binary string', () => { + const signedInteger = -694201337; + const expectedBinary = '01010110100111110101010000000111'; + writer.writeSignedInteger(signedInteger); + + expect(writer.flush()).toStrictEqual(expectedBinary); + }); +}); + +describe('BinaryWriter.writeString()', () => { + it('stores the string as a binary string', () => { + const string = 'Hello, world!'; + const expectedBinary = + '000000000000110101001000011001010010110001101111011011000110110001110010011011110111011100100000011011000110010000100001'; + writer.writeString(string); + + expect(writer.flush()).toStrictEqual(expectedBinary); + }); + + describe('when the string has length of zero', () => { + it('stores an empty string', () => { + const string = ''; + const expectedBinary = '0000000000000000'; + writer.writeString(string); + + expect(writer.flush()).toStrictEqual(expectedBinary); + }); + }); + + describe('when the binary string data is not aligned', () => { + it('aligns the bits and stores a string', () => { + const precedingData = '111'; + writer.writeBits(precedingData); + + const string = 'Hello, world!'; + const expectedBinary = + '11100000000000011010000001001000011011110110110001101100011001010110111101110111001000000010110000100001011001000110110001110010'; + writer.writeString(string); + + expect(writer.flush()).toStrictEqual(expectedBinary); + }); + }); +}); + +describe('BinaryWriter.writeUnsignedInteger()', () => { + it('stores the floating point number as a binary string', () => { + const unsignedInteger = 133742069; + const expectedBinary = '00000111111110001011110111110101'; + writer.writeUnsignedInteger(unsignedInteger); + + expect(writer.flush()).toStrictEqual(expectedBinary); + }); +}); + +describe('BinaryWriter.writeUnsignedLong()', () => { + it('stores the floating point number as a binary string', () => { + const unsignedLong = 133742069; + const expectedBinary = '0000011111111000101111011111010100000000000000000000000000000000'; + writer.writeUnsignedLong(unsignedLong); + + expect(writer.flush()).toStrictEqual(expectedBinary); + }); +}); + +describe('BinaryWriter.writeUnsignedShort()', () => { + it('stores the floating point number as a binary string', () => { + const unsignedShort = 1337; + const expectedBinary = '0000010100111001'; + writer.writeUnsignedShort(unsignedShort); + + expect(writer.flush()).toStrictEqual(expectedBinary); + }); +}); diff --git a/src/BinaryWriter.ts b/src/BinaryWriter.ts new file mode 100644 index 0000000..2643ce6 --- /dev/null +++ b/src/BinaryWriter.ts @@ -0,0 +1,225 @@ +import type { BinaryString } from './types/BinaryString.js'; + +import { BinaryData } from './BinaryData.js'; + +/** + * Handles the controlled storing of binary data for ATT save strings. + * + * @see [Class: `BinaryWriter`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/BinaryWriter.md) + * + * @example + * import { BinaryWriter } from 'att-string-transcoder'; + * + * const writer = new BinaryWriter(); + * + * writer.writeBoolean(true); + * + * const output = writer.flush(); + * // `output` is `'1'` + */ +export class BinaryWriter { + private data: string; + + /** + * Creates a writer to store information using various write methods. + * + * @see [Class: `BinaryWriter`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/BinaryWriter.md) + * + * @example + * import { BinaryWriter } from 'att-string-transcoder'; + * + * const writer = new BinaryWriter(); + */ + constructor() { + this.data = '' as BinaryString; + } + + /** + * Returns the stored binary string and resets the BinaryWriter's internal memory. + * + * @example + * 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'` + */ + flush(): BinaryString { + const data = this.data; + this.data = ''; + + return data as BinaryString; + } + + /** + * Writes raw binary data into BinaryWriter's internal memory. + * + * @example + * import { BinaryWriter } from 'att-string-transcoder'; + * + * const writer = new BinaryWriter(); + * + * writer.writeBits('11110111001100010000'); + */ + writeBits(data: string): void { + if (!BinaryData.isBinaryString(data)) { + throw new Error('Binary data string contains invalid characters. Only "0" and "1" are allowed.'); + } + + this.data += data; + } + + /** + * Writes a boolean into BinaryWriter's internal memory. + * + * @example + * import { BinaryWriter } from 'att-string-transcoder'; + * + * const writer = new BinaryWriter(); + * + * writer.writeBoolean(true); + */ + writeBoolean(boolean: boolean): void { + this.data += BinaryData.fromBoolean(boolean).toBinaryString(); + } + + /** + * Writes a character into BinaryWriter's internal memory. + * + * @example + * import { BinaryWriter } from 'att-string-transcoder'; + * + * const writer = new BinaryWriter(); + * + * writer.writeChar('x'); + */ + writeChar(char: string): void { + this.data += BinaryData.fromChar(char).toBinaryString(); + } + + /** + * Writes a floating point number into BinaryWriter's internal memory. + * + * @example + * import { BinaryWriter } from 'att-string-transcoder'; + * + * const writer = new BinaryWriter(); + * + * writer.writeFloat(0.69); + */ + writeFloat(float: number): void { + this.data += BinaryData.fromFloat(float).toBinaryString(); + } + + /** + * Writes a signed integer into BinaryWriter's internal memory. + * + * @example + * import { BinaryWriter } from 'att-string-transcoder'; + * + * const writer = new BinaryWriter(); + * + * writer.writeSignedInteger(-420); + */ + writeSignedInteger(signedInteger: number): void { + this.data += BinaryData.fromSignedInteger(signedInteger).toBinaryString(); + } + + /** + * Writes a string into BinaryWriter's internal memory. + * + * @example + * import { BinaryWriter } from 'att-string-transcoder'; + * + * const writer = new BinaryWriter(); + * + * writer.writeString('Hello, world!'); + */ + writeString(string: string): void { + this.writeUnsignedShort(string.length); + + if (string.length === 0) return; + + /* Align bits. */ + const index = this.data.length; + const offset = index % 8 === 0 ? 0 : 8 - (index % 8); + + if (offset > 0) { + const alignBits = '0'.repeat(offset); + + this.writeBits(alignBits); + } + + let currentByte = (this.data.length % 32) / 8; + + /* Garble text, ATT style. */ + let textBuffer = ''; + let bufferIndex = 0; + + while (currentByte++ < 4 && bufferIndex < string.length) { + textBuffer += string[bufferIndex++]; + } + + while (bufferIndex + 4 <= string.length) { + const chars = string.substr(bufferIndex, 4); + + textBuffer += chars.split('').reverse().join(''); + bufferIndex += 4; + } + + while (bufferIndex < string.length) { + textBuffer += string[bufferIndex++]; + } + + for (const character of textBuffer) { + this.writeChar(character); + } + } + + /** + * Writes an unsigned integer into BinaryWriter's internal memory. + * + * @example + * import { BinaryWriter } from 'att-string-transcoder'; + * + * const writer = new BinaryWriter(); + * + * writer.writeUnsignedInteger(69420); + */ + writeUnsignedInteger(unsignedInteger: number): void { + this.data += BinaryData.fromUnsignedInteger(unsignedInteger).toBinaryString(); + } + + /** + * Writes an unsigned long integer into BinaryWriter's internal memory. + * + * @example + * import { BinaryWriter } from 'att-string-transcoder'; + * + * const writer = new BinaryWriter(); + * + * writer.writeUnsignedLong(133742069); + */ + writeUnsignedLong(unsignedLong: number): void { + this.data += BinaryData.fromUnsignedLong(unsignedLong).toBinaryString(); + } + + /** + * Writes an unsigned short integer into BinaryWriter's internal memory. + * + * @example + * import { BinaryWriter } from 'att-string-transcoder'; + * + * const writer = new BinaryWriter(); + * + * writer.writeUnsignedShort(1337); + */ + writeUnsignedShort(unsignedShort: number): void { + this.data += BinaryData.fromUnsignedShort(unsignedShort).toBinaryString(); + } +} diff --git a/src/EmbeddedEntityHash.ts b/src/EmbeddedEntityHash.ts deleted file mode 100644 index 52589a8..0000000 --- a/src/EmbeddedEntityHash.ts +++ /dev/null @@ -1,3 +0,0 @@ -export enum EmbeddedEntityHash { - Fire = 30100 -} diff --git a/src/Entity.test.ts b/src/Entity.test.ts new file mode 100644 index 0000000..ae538e1 --- /dev/null +++ b/src/Entity.test.ts @@ -0,0 +1,215 @@ +import { BinaryData } from './BinaryData.js'; +import { BinaryReader } from './BinaryReader.js'; +import { BinaryWriter } from './BinaryWriter.js'; +import { Entity } from './Entity.js'; +import { Prefab } from './Prefab.js'; +import { HeatSourceBaseComponent } from './components/HeatSourceBaseComponent.js'; +import { ComponentHash } from './types/ComponentHash.js'; + +describe('new Entity()', () => { + describe('when given the required props', () => { + it('creates an instance of the Entity class', () => { + const prefabName = 'Torch'; + const entityHash = 30100; + const entityName = 'Fire'; + + const entity = new Entity(`${entityName}_${entityHash}`); + + expect(entity.hash).toStrictEqual(entityHash); + expect(entity.name).toStrictEqual(entityName); + expect(entity.isAlive).toStrictEqual(true); + expect(entity.components).toStrictEqual({ Unknown: [] }); + }); + }); + + describe('when given additional props', () => { + it('creates an instance of the Entity class', () => { + const prefabName = 'Torch'; + const entityHash = 30100; + const entityName = 'Fire'; + const entityIsAlive = true; + + const entity = new Entity(`${entityName}_${entityHash}`, { + hash: entityHash, + isAlive: entityIsAlive, + components: { + HeatSourceBase: new HeatSourceBaseComponent({ + version: 1, + isLit: true, + progress: 0.69 + }) + } + }); + + expect(entity.hash).toStrictEqual(entityHash); + expect(entity.name).toStrictEqual(entityName); + expect(entity.isAlive).toStrictEqual(entityIsAlive); + expect(entity.components).toStrictEqual({ + HeatSourceBase: new HeatSourceBaseComponent({ + version: 1, + isLit: true, + progress: 0.69 + }), + Unknown: [] + }); + }); + }); + + describe('when given an "Unknown" key and no additional hash property', () => { + it('throws an error', () => { + const expectedToThrow = () => new Entity('Unknown'); + const expectedError = new Error('You must manually pass an entity hash when instantiating an "Unknown" Entity.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); +}); + +describe('Entity.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + const prefabName = 'Torch'; + const entityHash = 30100; + const entityName = 'Fire'; + const prefab = new Prefab(prefabName, { + entities: { + Fire: new Entity(`${entityName}_${entityHash}`, { + hash: entityHash, + isAlive: false, + components: { + HeatSourceBase: new HeatSourceBaseComponent({ + version: 1, + isLit: true, + progress: 0.69 + }) + } + }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // Component hash === termination hash. + reader.readUnsignedInteger(); // Entity hash === entityHash. + reader.readUnsignedInteger(); // Entity data length. + + fastForwardedReader = reader; + }); + + describe('when given required EntityFromBinaryProps', () => { + it('creates an instance of the Entity class using the given BinaryReader', () => { + const props = { key: `${entityName}_${entityHash}`, hash: entityHash }; + const entity = Entity.fromBinary(fastForwardedReader, props); + + expect(entity).toBeInstanceOf(Entity); + expect(entity.hash).toStrictEqual(entityHash); + expect(entity.name).toStrictEqual(entityName); + expect(entity.isAlive).toStrictEqual(false); + }); + }); + + describe('when given additional EntityFromBinaryProps', () => { + it('creates an instance of the Entity class using the given BinaryReader', () => { + const componentVersions = new Map([[4109360768, 1]]); + const props = { key: `${entityName}_${entityHash}`, hash: entityHash, componentVersions }; + const entity = Entity.fromBinary(fastForwardedReader, props); + + expect(entity).toBeInstanceOf(Entity); + expect(entity.hash).toStrictEqual(entityHash); + expect(entity.name).toStrictEqual(entityName); + expect(entity.isAlive).toStrictEqual(false); + expect(entity.components).toStrictEqual({ + HeatSourceBase: new HeatSourceBaseComponent({ + version: 1, + isLit: true, + progress: 0.6899999976158142 + }), + Unknown: [] + }); + }); + }); +}); + +describe('Entity.toBinary()', () => { + it('returns a BinaryString representation of the entity', () => { + const prefabName = 'Torch'; + const entityHash = 30100; + const entityName = 'Fire'; + const entityIsAlive = true; + const componentHash = ComponentHash.HeatSourceBase; + const componentVersion = 1; + + const entity = new Entity(`${entityName}_${entityHash}`, { + hash: entityHash, + isAlive: entityIsAlive, + components: { + HeatSourceBase: new HeatSourceBaseComponent({ + version: componentVersion, + isLit: true, + progress: 0.69 + }) + } + }); + + const data = entity.toBinary(new Map([[componentHash, componentVersion]])); + + const expectedData = + '11111010011101111110111101000000000000000000000000000000001100001100111111001100001010001111010111010100011111011011000000000000000000000001110000000111010111100000000000000000000000000000000000'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('Entity.write()', () => { + it('writes a BinaryString representation of the entity to the given BinaryWriter, including entity hash and data length', () => { + const prefabName = 'Torch'; + const entityHash = 30100; + const entityName = 'Fire'; + const entityIsAlive = true; + + const entity = new Entity(`${entityName}_${entityHash}`, { + hash: entityHash, + isAlive: entityIsAlive + }); + + const writer = new BinaryWriter(); + entity.write(writer, new Map()); + + const data = writer.flush(); + + const expectedData = + '0000000000000000011101011001010000000000000000000000000000100001100000000000000000000000000000000'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // Entity data length. + const isAliveBit = reader.readBoolean(); + + expect(hash).toStrictEqual(entityHash); + expect(isAliveBit).toStrictEqual(entityIsAlive); + }); +}); diff --git a/src/Entity.ts b/src/Entity.ts new file mode 100644 index 0000000..8d68272 --- /dev/null +++ b/src/Entity.ts @@ -0,0 +1,222 @@ +import type { BinaryReader } from './BinaryReader.js'; +import type { ATTPrefabName } from './types/ATTPrefabName.js'; +import type { BinaryString } from './types/BinaryString.js'; +import type { EntityKey } from './types/EntityKey.js'; +import type { PrefabComponents } from './types/PrefabComponents.js'; +import type { SupportedPrefabComponents } from './types/SupportedPrefabComponents.js'; +import type { UnknownPrefabComponents } from './types/UnknownPrefabComponents.js'; +import type { UnsupportedPrefabComponents } from './types/UnsupportedPrefabComponents.js'; + +import { BinaryWriter } from './BinaryWriter.js'; +import { ATTPrefabs } from './types/ATTPrefabs.js'; +import { readComponents } from './utils/readComponents.js'; +import { writeComponents } from './utils/writeComponents.js'; + +export type EntityProps = { + hash?: number | undefined; + isAlive?: boolean | undefined; + components?: (SupportedPrefabComponents & UnsupportedPrefabComponents & Partial) | undefined; +}; + +type EntityFromBinaryProps = { + key: string; + hash: number; + componentVersions?: Map | undefined; +}; + +/** + * An "item" inside a prefab composition. The `Entity` can have its own components to alter its + * behaviour. A child prefab of the composition may attach to an `Entity`, forming an hierarchical + * structure inside the composition. This is primarily used in _A Township Tale_'s crafting system. + * + * @see [Class: `Entity`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/Entity.md) + * + * @example + * import { Entity } from 'att-string-transcoder'; + * + * const torchFireEntity = new Entity<'Torch'>('Fire_30100'); + * // or + * const torchFireEntity = Entity.fromBinary<'Torch'>(myBinaryString); + */ +export class Entity { + /** + * The hash of the entity. + * + * @example + * import { Entity } from 'att-string-transcoder'; + * + * const entity = new Entity<'Torch'>('Fire_30100'); + * + * const hash = entity.hash; + * // `hash` is `30100` + */ + hash: number; + + /** + * The name of the entity. + * + * @example + * import { Entity } from 'att-string-transcoder'; + * + * const entity = new Entity<'Torch'>('Fire_30100'); + * + * const name = entity.name; + * // `name` is `'Fire'` + */ + name: string; + + /** + * The alive state of the entity. + * + * @example + * import { Entity } from 'att-string-transcoder'; + * + * const entity = new Entity<'Torch'>('Fire_30100'); + * + * const isAlive = entity.isAlive; + * // `isAlive` is `true` + */ + isAlive: boolean; + + /** + * A map of the stored components. + * + * Provides access to the components stored in this entity. Components are keyed to their + * respective names, unless its data contained an unrecognised hash. In that case, the component + * will be stored in an array under the `Unknown` key. + * + * @example + * import { Entity } from 'att-string-transcoder'; + * + * const entity = new Entity<'Torch'>('Fire_30100'); + * + * const components = entity.components; + * // `components` is `{ Unknown: [] }` + */ + components: PrefabComponents; + + /** + * Creates a new `Entity` object configured with the passed in configuration. + * + * @see [Class: `Entity`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/Entity.md) + * + * @example + * import { Entity } from 'att-string-transcoder'; + * + * const torchFireEntity = new Entity<'Torch'>('Fire_30100', { + * hash: 30100, + * isAlive: true, + * components: {} + * }); + */ + constructor(key: EntityKey, { hash, isAlive, components }: EntityProps = {}) { + const resolvedName = key === 'Unknown' ? String(key) : String(key).split('_').slice(0, -1).join('_'); + const resolvedHash = resolvedName === 'Unknown' ? hash : Number(String(key).split('_').slice(-1)); + + if (typeof resolvedHash === 'undefined') { + throw new Error('You must manually pass an entity hash when instantiating an "Unknown" Entity.'); + } + + this.hash = resolvedHash; + this.name = resolvedName; + this.isAlive = isAlive ?? true; + this.components = { + ...components, + Unknown: components?.Unknown ?? [] + }; + } + + /** + * Reads the binary string data and returns an instantiated entity. + * + * @example + * import { Entity } from 'att-string-transcoder'; + * + * const torchFireEntity = Entity.fromBinary<'Torch'>(myBinaryString); + */ + static fromBinary( + reader: BinaryReader, + { key, hash, componentVersions }: EntityFromBinaryProps + ): Entity { + const isAlive = reader.readBoolean(); + const components = readComponents(reader, componentVersions); + + return new Entity(key as keyof (typeof ATTPrefabs)[ATTPrefabName]['embedded'], { + hash, + isAlive, + components + }); + } + + /** + * Returns a `BinaryString` representation of the entity. + * + * @example + * import { ComponentHash, Entity } from 'att-string-transcoder'; + * + * const torchFireEntity = new Entity<'Torch'>('Fire_30100'); + * + * const componentVersions = new Map([ + * [ComponentHash.NetworkRigidbody, 1], + * [ComponentHash.PhysicalMaterialPart, 1], + * [ComponentHash.Pickup, 2] + * // etc... + * ]); + * + * const binaryString = torchFireEntity.toBinary(componentVersions); + */ + toBinary(componentVersions: Map): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {boolean} isAlive + */ + writer.writeBoolean(this.isAlive); + + /** + * @property {PrefabComponents} components + */ + writeComponents(writer, this.components, componentVersions); + + return writer.flush(); + } + + /** + * Writes a `BinaryString` representation of the entity to the given `BinaryWriter`, including the + * entity hash and data length. + * + * @example + * import { BinaryWriter, ComponentHash, Entity } from 'att-string-transcoder'; + * + * const torchFireEntity = new Entity<'Torch'>('Fire_30100'); + * + * const componentVersions = new Map([ + * [ComponentHash.NetworkRigidbody, 1], + * [ComponentHash.PhysicalMaterialPart, 1], + * [ComponentHash.Pickup, 2] + * // etc... + * ]); + * + * const writer = new BinaryWriter(); + * + * torchFireEntity.write(writer, componentVersions); + */ + write(writer: BinaryWriter, componentVersions: Map): void { + const data = this.toBinary(componentVersions); + + /** + * @property {number} hash + */ + writer.writeUnsignedInteger(this.hash); + + /** + * @property {number} dataLength + */ + writer.writeUnsignedInteger(data.length); + + /** + * @property {BinaryString} data + */ + writer.writeBits(data); + } +} diff --git a/src/Prefab.test.ts b/src/Prefab.test.ts new file mode 100644 index 0000000..7ec1b99 --- /dev/null +++ b/src/Prefab.test.ts @@ -0,0 +1,2222 @@ +import type { BinaryString } from './types/BinaryString.js'; +import type { SaveString } from './types/SaveString.js'; + +import { vi } from 'vitest'; + +import { BinaryReader } from './BinaryReader.js'; +import { Entity } from './Entity.js'; +import { Prefab } from './Prefab.js'; +import { DurabilityModuleComponent } from './components/DurabilityModuleComponent.js'; +import { HeatSourceBaseComponent } from './components/HeatSourceBaseComponent.js'; +import { LiquidContainerComponent } from './components/LiquidContainerComponent.js'; +import { NetworkRigidbodyComponent } from './components/NetworkRigidbodyComponent.js'; +import { PhysicalMaterialPartComponent } from './components/PhysicalMaterialPartComponent.js'; +import { PickupComponent } from './components/PickupComponent.js'; +import { PopulationSpawnAreaComponent } from './components/PopulationSpawnAreaComponent.js'; +import { SentGiftComponent } from './components/SentGiftComponent.js'; +import { SpawnAreaComponent } from './components/SpawnAreaComponent.js'; +import { UnsupportedComponent } from './components/UnsupportedComponent.js'; +import { ATTPrefabs } from './types/ATTPrefabs.js'; +import { ComponentHash } from './types/ComponentHash.js'; +import { PhysicalMaterialPartHash } from './types/PhysicalMaterialPartHash.js'; +import { PopulationDefinitionHash } from './types/PopulationDefinitionHash.js'; + +describe('new Prefab()', () => { + describe('when given only a prefab name', () => { + it('returns an instance of the Prefab class', () => { + const prefab = new Prefab('Handle_Short'); + + expect(prefab.hash).toStrictEqual(ATTPrefabs.Handle_Short.hash); + expect(prefab.components).toStrictEqual({ Unknown: [] }); + expect(prefab.entities).toStrictEqual({}); + expect(prefab.children).toStrictEqual([]); + }); + }); + + describe('when given additional constructor props', () => { + it('returns an instance of the Prefab class', () => { + const prefab = new Prefab('Torch', { + components: { + Pickup: new PickupComponent({ version: 2 }) + }, + entities: { + Fire_30100: new Entity('Fire_30100', { isAlive: true }) + }, + children: [{ parentHash: 0, prefab: new Prefab('Guard') }] + }); + + expect(prefab.hash).toStrictEqual(ATTPrefabs.Torch.hash); + + expect(prefab.components).toEqual({ + Pickup: { + hash: ComponentHash.Pickup, + name: 'Pickup', + version: 2, + dockedMemory: [], + lastInteractorPlayerId: 0 + }, + Unknown: [] + }); + + expect(prefab.entities).toEqual({ + Fire_30100: { + hash: ATTPrefabs.Torch.embedded.Fire_30100.hash, + name: 'Fire', + isAlive: true, + components: { Unknown: [] } + } + }); + + expect(prefab.children).toEqual([ + { + parentHash: 0, + prefab: new Prefab('Guard', { + position: { x: 0, y: 0, z: 0 }, + rotation: { x: 0, y: 0, z: 0, w: 1 }, + scale: 1, + components: { Unknown: [] }, + entities: {}, + children: [] + }) + } + ]); + }); + }); +}); + +describe('Prefab.addChildPrefab()', () => { + let parent: Prefab<'Handle_Short'>; + + beforeEach(() => { + parent = new Prefab('Handle_Short'); + }); + + describe('when given invalid arguments', () => { + it('throws an error', () => { + // @ts-expect-error Passing invalid arguments + const expectedToThrow = () => parent.addChildPrefab(); + const expectedError = new Error( + 'You must pass a parent prefab entity hash (or null) and a child prefab to add as a child to this prefab.' + ); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + describe('when given a null parentKey', () => { + it('adds a child prefab attached to parentHash 0', () => { + const child = new Prefab('Guard'); + + parent.addChildPrefab(null, child); + + expect(parent.children).toStrictEqual([ + { + parentHash: 0, + prefab: child + } + ]); + }); + }); + + describe('when given a valid parentKey', () => { + it('adds a child prefab attached to the corresponding entity', () => { + const child = new Prefab('Guard'); + + parent.addChildPrefab('Slot_Multi_6136', child); + + expect(parent.children).toStrictEqual([ + { + parentHash: 6136, + prefab: child + } + ]); + }); + }); + + describe('when given an invalid parentKey', () => { + it('throws an error', () => { + const child = new Prefab('Guard'); + + // @ts-expect-error Passing invalid arguments + const expectedToThrow = () => parent.addChildPrefab('Invalid_Entity_Name', child); + const expectedError = new Error('"Invalid_Entity_Name" is not a valid entity on "Handle_Short".'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); +}); + +describe('Prefab.addComponent()', () => { + let prefab: Prefab<'Handle_Short'>; + + beforeEach(() => { + prefab = new Prefab('Handle_Short'); + }); + + it('adds a component to the prefab', () => { + const component = new PickupComponent({ version: 2, lastInteractorPlayerId: 1337 }); + + prefab.addComponent(component); + + expect(prefab.components).toStrictEqual({ + Pickup: component, + Unknown: [] + }); + }); +}); + +describe('Prefab.addEntity()', () => { + let prefab: Prefab<'Handle_Short'>; + + beforeEach(() => { + prefab = new Prefab('Handle_Short'); + }); + + it('adds an entity to the prefab', () => { + const entity = new Entity<'Handle_Short'>('Slot_Multi_6136'); + + prefab.addEntity(entity); + + expect(prefab.entities).toStrictEqual({ + Slot_Multi_6136: entity + }); + }); +}); + +describe('Prefab.addGift()', () => { + let prefab: Prefab<'Gift_Mail_Box'>; + let gift: Prefab<'Dynamite'>; + + beforeEach(() => { + prefab = new Prefab('Gift_Mail_Box'); + gift = new Prefab('Dynamite'); + }); + + describe('when given invalid arguments', () => { + it('throws an error', () => { + // @ts-expect-error Passing invalid arguments + const expectedToThrow = () => prefab.addGift(); + const expectedError = new Error('You must pass a gift prefab to add to this prefab as a gift.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + describe('when given required arguments', () => { + it('adds a gift to the prefab', () => { + prefab.addGift(gift); + + const unsignedIntegers = [31326, 0, 0, 0, 0, 0, 0, 1065353216, 1065353216, 0, 0, 0, 0]; + const hash = 31326; + const bytes = 48; + const chunkVersioning = [] as number[]; + + expect(gift.hash).toStrictEqual(hash); + expect(prefab.components.SentGift).toBeInstanceOf(SentGiftComponent); + expect(prefab.components.SentGift?.gifts.length).toStrictEqual(1); + expect(prefab.components.SentGift?.gifts[0]).toStrictEqual({ + data: unsignedIntegers, + messageSizeInBytes: bytes, + hash, + chunkVersioning + }); + }); + + it('adds an additional gift to the prefab', () => { + prefab.addGift(gift); + prefab.addGift(gift); + + const unsignedIntegers = [31326, 0, 0, 0, 0, 0, 0, 1065353216, 1065353216, 0, 0, 0, 0]; + const hash = 31326; + const bytes = 48; + const chunkVersioning = [] as number[]; + + expect(gift.hash).toStrictEqual(hash); + expect(prefab.components.SentGift).toBeInstanceOf(SentGiftComponent); + expect(prefab.components.SentGift?.gifts.length).toStrictEqual(2); + expect(prefab.components.SentGift?.gifts[0]).toStrictEqual({ + data: unsignedIntegers, + messageSizeInBytes: bytes, + hash, + chunkVersioning + }); + expect(prefab.components.SentGift?.gifts[1]).toStrictEqual({ + data: unsignedIntegers, + messageSizeInBytes: bytes, + hash, + chunkVersioning + }); + }); + }); + + describe('when the gift prefab SaveString contains no data', () => { + it('throws an error', () => { + const spy = vi.spyOn(gift, 'toSaveString'); + spy.mockImplementationOnce(() => '|' as SaveString); + + const expectedToThrow = () => prefab.addGift(gift); + const expectedError = new Error('Gift prefab data is corrupted.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + describe('when the gift prefab SaveString contains malformed data', () => { + it('throws an error', () => { + const spy = vi.spyOn(gift, 'toSaveString'); + spy.mockImplementationOnce(() => ',|,,' as SaveString); + + const expectedToThrow = () => prefab.addGift(gift); + const expectedError = new Error('Gift prefab data is corrupted.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); +}); + +describe('Prefab.clone()', () => { + it('returns a deep clone of the prefab', () => { + const original = new Prefab('Guard').setMaterial('Mythril'); + const clone = original.clone(); + + clone.setMaterial('Gold'); + + expect(original.getMaterial()).toStrictEqual(PhysicalMaterialPartHash.Mythril); + expect(clone.getMaterial()).toStrictEqual(PhysicalMaterialPartHash.Gold); + }); +}); + +describe('Prefab.fromBinary()', () => { + let reader: BinaryReader; + const componentVersions = new Map([[1454441398, 2]]); + const prefab = new Prefab('Handle_Short', { + components: { + Pickup: new PickupComponent({ version: 2 }) + } + }); + + beforeEach(() => { + const binaryString = + '0000000000000000101001001111011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111100000000000000000000000001111111000000000000000000000000101011010110001000000111011011000000000000000000000000001000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' as BinaryString; + reader = new BinaryReader(binaryString); + }); + + describe('when given required arguments', () => { + it('creates an instance of the Prefab class using the given BinaryReader', () => { + const prefabFromBinary = Prefab.fromBinary(reader); + + expect(prefabFromBinary).toStrictEqual(prefab); + }); + }); + + describe('when given optional arguments', () => { + it('creates an instance of the Prefab class using the given BinaryReader', () => { + const prefabFromBinary = Prefab.fromBinary(reader, componentVersions); + + expect(prefabFromBinary).toStrictEqual(prefab); + }); + }); + + describe('when given binary data containing an invalid prefab hash', () => { + it('throws an error', () => { + const readerWithInvalidData = new BinaryReader( + '1111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111100000000000000000000000001111111000000000000000000000000101011010110001000000111011011000000000000000000000000001000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' + ); + + const expectedToThrow = () => Prefab.fromBinary(readerWithInvalidData); + const expectedError = new Error('Cannot find ATT Prefab with hash 4294967295.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); +}); + +describe('Prefab.fromSaveString()', () => { + let saveString: SaveString; + const prefab = new Prefab('Handle_Short'); + + beforeEach(() => { + saveString = '42230,48,42230,0,0,0,0,0,0,1065353216,1065353216,0,0,0,' as SaveString; + }); + + describe('when the SaveString contains no component versions', () => { + it('creates an instance of the Prefab class using the given SaveString', () => { + const prefabFromSaveString = Prefab.fromSaveString(saveString); + + expect(prefabFromSaveString).toStrictEqual(prefab); + }); + }); + + describe('when the SaveString contains component versions', () => { + beforeEach(() => { + saveString = `${saveString}|3,2290978823,1,1454441398,2,4109360768,1,` as SaveString; + }); + + it('creates an instance of the Prefab class using the given SaveString', () => { + const prefabFromSaveString = Prefab.fromSaveString(saveString); + + expect(prefabFromSaveString).toStrictEqual(prefab); + }); + }); + + describe('when the SaveString contains incorrect component versions length', () => { + beforeEach(() => { + saveString = `${saveString}|69,2290978823,1,1454441398,2,4109360768,1,` as SaveString; + }); + + it('throws an error', () => { + const expectedToThrow = () => Prefab.fromSaveString(saveString); + const expectedError = new Error('SaveString contains invalid versioning. Expected 69 versions but parsed 3.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + describe('when the SaveString contains malformed component versions', () => { + beforeEach(() => { + saveString = `${saveString}|,,,` as SaveString; + }); + + it('throws an error', () => { + const expectedToThrow = () => Prefab.fromSaveString(saveString); + const expectedError = new Error('SaveString is malformed.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + describe('when the SaveString contains no data', () => { + beforeEach(() => { + saveString = `|,` as SaveString; + }); + + it('throws an error', () => { + const expectedToThrow = () => Prefab.fromSaveString(saveString); + const expectedError = new Error('SaveString is malformed.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + describe('when the SaveString contains malformed data', () => { + beforeEach(() => { + saveString = `0,0,` as SaveString; + }); + + it('throws an error', () => { + const expectedToThrow = () => Prefab.fromSaveString(saveString); + const expectedError = new Error('SaveString is malformed.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + describe('when the passed argument is not a valid SaveString', () => { + beforeEach(() => { + saveString = `0` as SaveString; + }); + + it('throws an error', () => { + const expectedToThrow = () => Prefab.fromSaveString(saveString); + const expectedError = new Error('SaveString is malformed.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); +}); + +describe('Prefab.getAngularVelocity()', () => { + describe('when the prefab has no NetworkRigidBody component', () => { + it('returns an angular velocity of zero', () => { + const prefab = new Prefab('Handle_Short'); + delete prefab.components.NetworkRigidbody; + + const angularVelocity = prefab.getAngularVelocity(); + + expect(angularVelocity).toStrictEqual({ x: 0, y: 0, z: 0 }); + }); + }); + + describe('when the prefab has a NetworkRigidBody component with angular velocity', () => { + it('returns the stored angular velocity', () => { + const prefab = new Prefab('Handle_Short', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ + version: 1, + angularVelocity: { x: 69, y: 420, z: 1337 } + }) + } + }); + + const angularVelocity = prefab.getAngularVelocity(); + + expect(angularVelocity).toStrictEqual({ x: 69, y: 420, z: 1337 }); + }); + }); +}); + +describe('Prefab.getChildPrefab()', () => { + describe('when providing the name of an existing child prefab', () => { + it('returns the first matching child prefab', () => { + const prefab = new Prefab('Handle_Short'); + + prefab.addChildPrefab('Slot_Large_SwordType_Craft_6134', new Prefab('Guard')); + prefab.addChildPrefab('Slot_Large_SwordType_Craft_54356', new Prefab('Guard')); + + const child = prefab.getChildPrefab('Guard'); + + expect(typeof child).not.toBeUndefined(); + expect(child?.name).toStrictEqual('Guard'); + }); + }); + + describe('when providing the name of an existing child prefab and a parent hash', () => { + it('returns the first matching child prefab', () => { + const prefab = new Prefab('Handle_Short'); + + const goldGuard = new Prefab('Guard').setMaterial('Gold'); + const mythrilGuard = new Prefab('Guard').setMaterial('Mythril'); + + prefab.addChildPrefab('Slot_Large_SwordType_Craft_6134', goldGuard); + prefab.addChildPrefab('Slot_Large_SwordType_Craft_54356', mythrilGuard); + + const child = prefab.getChildPrefab('Guard', 54356); + + expect(child).not.toBeUndefined(); + expect(child?.name).toStrictEqual('Guard'); + expect(child?.getMaterial()).toStrictEqual(PhysicalMaterialPartHash.Mythril); + }); + }); + + describe('when providing the name of a non-existent child prefab', () => { + it('returns undefined', () => { + const prefab = new Prefab('Handle_Short'); + + prefab.addChildPrefab('Slot_Large_SwordType_Craft_6134', new Prefab('Guard')); + prefab.addChildPrefab('Slot_Large_SwordType_Craft_54356', new Prefab('Guard')); + + const child = prefab.getChildPrefab('Pommel'); + + expect(child).toBeUndefined(); + }); + }); +}); + +describe('Prefab.getComponentVersions()', () => { + describe('when given consistent component versions', () => { + it('returns a Map of the versions of the components on a prefab', () => { + const prefab = new Prefab('Grass_Clump', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ version: 1 }), + Pickup: new PickupComponent({ version: 2 }), + Unknown: [ + new UnsupportedComponent({ + hash: 1337, + name: 'Unknown', + rawData: '1111011100110001000' as BinaryString, + version: 1 + }) + ] + }, + entities: { + Fire_30100: new Entity('Fire_30100', { + components: { + HeatSourceBase: new HeatSourceBaseComponent({ version: 1 }), + Unknown: [ + new UnsupportedComponent({ + hash: 1337, + name: 'Unknown', + rawData: '1111011100110001000' as BinaryString, + version: 1 + }) + ] + } + }) + }, + children: [ + { + parentHash: 0, + prefab: new Prefab('Guard', { + components: { + PhysicalMaterialPart: new PhysicalMaterialPartComponent({ version: 1 }) + } + }) + } + ] + }); + + const componentVersions = prefab.getComponentVersions(); + + expect(componentVersions).toStrictEqual( + new Map([ + [2290978823, 1], + [1454441398, 2], + [1337, 1], + [4109360768, 1], + [272188517, 1] + ]) + ); + }); + }); + + describe('when given inconsistent component versions', () => { + it('throws an error', () => { + const prefab = new Prefab('Grass_Clump', { + components: { + Unknown: [ + new UnsupportedComponent({ + hash: 1337, + name: 'Unknown', + rawData: '1111011100110001000' as BinaryString, + version: 420 + }) + ] + }, + entities: { + Fire_30100: new Entity('Fire_30100', { + components: { + Unknown: [ + new UnsupportedComponent({ + hash: 1337, + name: 'Unknown', + rawData: '1111011100110001000' as BinaryString, + version: 69 + }) + ] + } + }) + } + }); + + const expectedToThrow = () => prefab.getComponentVersions(); + const expectedError = new Error( + 'Component 1337 exists with version 420 and 69. All instances of a component must exist with the same version.' + ); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); +}); + +describe('Prefab.getGiftBoxLabel', () => { + describe('when the prefab has no SentGift component', () => { + it('returns an empty string', () => { + const prefab = new Prefab('Gift_Mail_Box'); + delete prefab.components.SentGift; + + const giftBoxLabel = prefab.getGiftBoxLabel(); + + expect(giftBoxLabel).toStrictEqual(''); + }); + }); + + describe('when the prefab has a SentGift component with senderName', () => { + it('returns the stored gift box label', () => { + const prefab = new Prefab('Gift_Mail_Box', { + components: { + SentGift: new SentGiftComponent({ + version: 1, + senderName: 'topkek' + }) + } + }); + + const giftBoxLabel = prefab.getGiftBoxLabel(); + + expect(giftBoxLabel).toStrictEqual('topkek'); + }); + }); +}); + +describe('Prefab.getIntegrity()', () => { + describe('when the prefab has no DurabilityModule component', () => { + it('returns full integrity', () => { + const prefab = new Prefab('Short_Sword_Blade'); + delete prefab.components.DurabilityModule; + + const integrity = prefab.getIntegrity(); + + expect(integrity).toStrictEqual(1); + }); + }); + + describe('when the prefab has a DurabilityModule component with integrity', () => { + it('returns the stored integrity', () => { + const prefab = new Prefab('Short_Sword_Blade', { + components: { + DurabilityModule: new DurabilityModuleComponent({ + version: 1, + integrity: 0.69 + }) + } + }); + + const integrity = prefab.getIntegrity(); + + expect(integrity).toBeCloseTo(0.69, 2); + }); + }); +}); + +describe('Prefab.getKinematic()', () => { + describe('when the prefab has no NetworkRigidbody component', () => { + it('returns isKinematic of false', () => { + const prefab = new Prefab('Handle_Short'); + delete prefab.components.NetworkRigidbody; + + const isKinematic = prefab.getKinematic(); + + expect(isKinematic).toStrictEqual(false); + }); + }); + + describe('when the prefab has a NetworkRigidbody component with isKinematic', () => { + it('returns the stored isKinematic', () => { + const prefab = new Prefab('Handle_Short', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ + version: 1, + isKinematic: true + }) + } + }); + + const isKinematic = prefab.getKinematic(); + + expect(isKinematic).toStrictEqual(true); + }); + }); +}); + +describe('Prefab.getMaterial()', () => { + describe('when the prefab has no PhysicalMaterialPart component', () => { + it('returns materialHash of zero', () => { + const prefab = new Prefab('Short_Sword_Blade'); + delete prefab.components.PhysicalMaterialPart; + + const materialHash = prefab.getMaterial(); + + expect(materialHash).toStrictEqual(0); + }); + }); + + describe('when the prefab has a PhysicalMaterialPart component with materialHash', () => { + it('returns the stored isKinematic', () => { + const prefab = new Prefab('Short_Sword_Blade', { + components: { + PhysicalMaterialPart: new PhysicalMaterialPartComponent({ + version: 1, + materialHash: PhysicalMaterialPartHash.EvinonSteelAlloy + }) + } + }); + + const materialHash = prefab.getMaterial(); + + expect(materialHash).toStrictEqual(31502); + }); + }); +}); + +describe('Prefab.getOnFire()', () => { + describe('when the prefab has no entity with HeatSourceBase component', () => { + it('returns false', () => { + const prefab = new Prefab('Grass_Clump'); + delete prefab.entities['Fire_30100']?.components.HeatSourceBase; + + const isOnFire = prefab.getOnFire(); + + expect(isOnFire).toStrictEqual(false); + }); + }); + + describe('when the prefab has an entity with HeatSourceBase component with isLit', () => { + it('returns the stored isLit', () => { + const prefab = new Prefab('Grass_Clump', { + entities: { + Fire_30100: new Entity('Fire_30100', { + components: { + HeatSourceBase: new HeatSourceBaseComponent({ + version: 1, + isLit: true + }) + } + }) + } + }); + + const isOnFire = prefab.getOnFire(); + + expect(isOnFire).toStrictEqual(true); + }); + }); +}); + +describe('Prefab.getPosition()', () => { + it('returns the Position of the Prefab', () => { + const prefab = new Prefab('Handle_Short', { position: { x: 69, y: 420, z: 1337 } }); + + const position = prefab.getPosition(); + + expect(position).toStrictEqual({ x: 69, y: 420, z: 1337 }); + }); +}); + +describe('Prefab.getRotation()', () => { + it('returns the Rotation of the Prefab', () => { + const prefab = new Prefab('Handle_Short', { rotation: { x: 0.69, y: 0.42, z: -0.1337, w: 0.88 } }); + + const rotation = prefab.getRotation(); + + expect(rotation).toStrictEqual({ x: 0.69, y: 0.42, z: -0.1337, w: 0.88 }); + }); +}); + +describe('Prefab.getScale()', () => { + it('returns the scale of the Prefab', () => { + const prefab = new Prefab('Handle_Short', { scale: 0.69 }); + + const scale = prefab.getScale(); + + expect(scale).toBeCloseTo(0.69, 2); + }); +}); + +describe('Prefab.getServerSleeping()', () => { + describe('when the prefab has no NetworkRigidbody component', () => { + it('returns isServerSleeping of false', () => { + const prefab = new Prefab('Handle_Short'); + delete prefab.components.NetworkRigidbody; + + const isServerSleeping = prefab.getServerSleeping(); + + expect(isServerSleeping).toStrictEqual(false); + }); + }); + + describe('when the prefab has a NetworkRigidbody component with isServerSleeping', () => { + it('returns the stored isServerSleeping', () => { + const prefab = new Prefab('Handle_Short', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ + version: 1, + isServerSleeping: true + }) + } + }); + + const isServerSleeping = prefab.getServerSleeping(); + + expect(isServerSleeping).toStrictEqual(true); + }); + }); +}); + +describe('Prefab.getServings()', () => { + describe('when the prefab has no LiquidContainer component', () => { + it('returns a servings of zero', () => { + const prefab = new Prefab('Potion_Medium'); + delete prefab.components.LiquidContainer; + + const servings = prefab.getServings(); + + expect(servings).toStrictEqual(0); + }); + }); + + describe('when the prefab has a LiquidContainer component with contentLevel', () => { + it('returns the stored contentLevel', () => { + const prefab = new Prefab('Potion_Medium', { + components: { + LiquidContainer: new LiquidContainerComponent({ + version: 1, + contentLevel: 420 + }) + } + }); + + const servings = prefab.getServings(); + + expect(servings).toStrictEqual(420); + }); + }); +}); + +describe('Prefab.getSpawnAreaPopulationName()', () => { + describe('when the prefab has no PopulationSpawnArea component', () => { + it('returns undefined', () => { + const prefab = new Prefab('Anvil'); + delete prefab.components.PopulationSpawnArea; + + const populationName = prefab.getSpawnAreaPopulationName(); + + expect(populationName).toStrictEqual(undefined); + }); + }); + + describe('when the prefab has a PopulationSpawnArea component', () => { + describe('when the stored population definition is not recognised', () => { + it('returns a population definition name of "Unknown"', () => { + const prefab = new Prefab('Disk_Encounter', { + components: { + PopulationSpawnArea: new PopulationSpawnAreaComponent({ + version: 2, + definition: 1337 + }) + } + }); + + const populationName = prefab.getSpawnAreaPopulationName(); + + expect(populationName).toStrictEqual('Unknown'); + }); + }); + + describe('when the stored population definition is recognised', () => { + it('returns the stored population definition name', () => { + const prefab = new Prefab('Disk_Encounter', { + components: { + PopulationSpawnArea: new PopulationSpawnAreaComponent({ + version: 2, + definition: PopulationDefinitionHash.WyrmPopulation + }) + } + }); + + const populationName = prefab.getSpawnAreaPopulationName(); + + expect(populationName).toStrictEqual('WyrmPopulation'); + }); + }); + }); +}); + +describe('Prefab.getVelocity()', () => { + describe('when the prefab has no NetworkRigidBody component', () => { + it('returns a velocity of zero', () => { + const prefab = new Prefab('Handle_Short'); + delete prefab.components.NetworkRigidbody; + + const velocity = prefab.getVelocity(); + + expect(velocity).toStrictEqual({ x: 0, y: 0, z: 0 }); + }); + }); + + describe('when the prefab has a NetworkRigidBody component with angular velocity', () => { + it('returns the stored velocity', () => { + const prefab = new Prefab('Handle_Short', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ + version: 1, + velocity: { x: 69, y: 420, z: 1337 } + }) + } + }); + + const velocity = prefab.getVelocity(); + + expect(velocity).toStrictEqual({ x: 69, y: 420, z: 1337 }); + }); + }); +}); + +describe('Prefab.inspect()', () => { + it('prints the internal data structure of the prefab to the stdout', () => { + const spy = vi.spyOn(process.stdout, 'write'); + spy.mockImplementationOnce(() => true); + + const prefab = new Prefab('Handle_Short'); + prefab.inspect(); + + expect(spy).toHaveBeenCalledWith(`Prefab { + name: 'Handle_Short', + hash: 42230, + position: { x: 0, y: 0, z: 0 }, + rotation: { x: 0, y: 0, z: 0, w: 1 }, + scale: 1, + components: { Unknown: [] }, + entities: {}, + children: [] +}\n`); + }); +}); + +describe('Prefab.print()', () => { + it('prints the SaveString of the prefab to the stdout', () => { + const spy = vi.spyOn(process.stdout, 'write'); + spy.mockImplementationOnce(() => true); + + const prefab = new Prefab('Handle_Short'); + prefab.print(); + + expect(spy).toHaveBeenCalledWith('42230,48,42230,0,0,0,0,0,0,1065353216,1065353216,0,0,0,\n'); + }); +}); + +describe('Prefab.removeAllChildPrefabs()', () => { + it('removes all child prefabs from the Prefab', () => { + const prefab = new Prefab('Handle_Short', { + children: [ + { parentHash: 0, prefab: new Prefab('Phantom_Guard') }, + { parentHash: 0, prefab: new Prefab('Phantom_Guard') }, + { parentHash: 0, prefab: new Prefab('Phantom_Guard') } + ] + }); + + prefab.removeAllChildPrefabs(); + + expect(prefab.children).toStrictEqual([]); + }); +}); + +describe('Prefab.removeAllComponents()', () => { + it('removes all components from the Prefab', () => { + const prefab = new Prefab('Handle_Short', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ version: 1 }), + Pickup: new PickupComponent({ version: 2 }), + Unknown: [ + new UnsupportedComponent({ + hash: 1337, + name: 'Unknown', + rawData: '1111011100110001000' as BinaryString, + version: 1 + }) + ] + } + }); + + prefab.removeAllComponents(); + + expect(prefab.components).toStrictEqual({ Unknown: [] }); + }); +}); + +describe('Prefab.removeAllEntities()', () => { + it('removes all entities from the Prefab', () => { + const prefab = new Prefab('Grass_Clump', { + entities: { + Fire_30100: new Entity('Fire_30100', { + components: { + Unknown: [ + new UnsupportedComponent({ + hash: 1337, + name: 'Unknown', + rawData: '1111011100110001000' as BinaryString, + version: 69 + }) + ] + } + }), + Unknown_1337: new Entity('Unknown', { hash: 1337 }) + } + }); + + prefab.removeAllEntities(); + + expect(prefab.entities).toStrictEqual({}); + }); +}); + +describe('Prefab.removeAllGifts()', () => { + it('removes all gift `Prefab` from the Prefab', () => { + const prefab = new Prefab('Gift_Mail_Box') + .addGift(new Prefab('Dynamite')) + .addGift(new Prefab('Dynamite')) + .addGift(new Prefab('Dynamite')); + + expect(prefab.components.SentGift?.gifts.length).toStrictEqual(3); + + prefab.removeAllGifts(); + + expect(prefab.components.SentGift?.gifts.length).toStrictEqual(0); + }); +}); + +describe('Prefab.removeChildPrefab()', () => { + describe('when given invalid arguments', () => { + it('throws an error', () => { + const prefab = new Prefab('Handle_Short', { + children: [ + { parentHash: 0, prefab: new Prefab('Phantom_Guard') }, + { parentHash: 0, prefab: new Prefab('Phantom_Guard') }, + { parentHash: 0, prefab: new Prefab('Guard') }, + { parentHash: 0, prefab: new Prefab('Guard') } + ] + }); + + // @ts-expect-error Passing invalid arguments + const expectedToThrow = () => prefab.removeChildPrefab(); + const expectedError = new Error('You must pass a child prefab hash or name to remove from this prefab.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + describe('when given a child prefab hash', () => { + it('removes all matching children from the Prefab', () => { + const prefab = new Prefab('Handle_Short', { + children: [ + { parentHash: 0, prefab: new Prefab('Phantom_Guard') }, + { parentHash: 0, prefab: new Prefab('Phantom_Guard') }, + { parentHash: 0, prefab: new Prefab('Guard') }, + { parentHash: 0, prefab: new Prefab('Guard') } + ] + }); + + prefab.removeChildPrefab(6940); + + expect(prefab.children).toStrictEqual([ + { parentHash: 0, prefab: new Prefab('Guard') }, + { parentHash: 0, prefab: new Prefab('Guard') } + ]); + }); + }); + + describe('when given a child prefab name', () => { + it('removes all matching children from the Prefab', () => { + const prefab = new Prefab('Handle_Short', { + children: [ + { parentHash: 0, prefab: new Prefab('Phantom_Guard') }, + { parentHash: 0, prefab: new Prefab('Phantom_Guard') }, + { parentHash: 0, prefab: new Prefab('Guard') }, + { parentHash: 0, prefab: new Prefab('Guard') } + ] + }); + + prefab.removeChildPrefab('Phantom_Guard'); + + expect(prefab.children).toStrictEqual([ + { parentHash: 0, prefab: new Prefab('Guard') }, + { parentHash: 0, prefab: new Prefab('Guard') } + ]); + }); + }); +}); + +describe('Prefab.removeComponent()', () => { + describe('when given invalid arguments', () => { + it('throws an error', () => { + const prefab = new Prefab('Handle_Short', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ version: 1 }), + Pickup: new PickupComponent({ version: 2 }) + } + }); + + // @ts-expect-error Passing invalid arguments + const expectedToThrow = () => prefab.removeComponent(); + const expectedError = new Error('You must pass a component hash or name to remove from this prefab.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + describe('when given a valid component hash', () => { + it('removes all matching components from the Prefab', () => { + const prefab = new Prefab('Handle_Short', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ version: 1 }), + Pickup: new PickupComponent({ version: 2 }) + } + }); + + prefab.removeComponent(2290978823); + + expect(prefab.components).toStrictEqual({ + Pickup: new PickupComponent({ version: 2 }), + Unknown: [] + }); + }); + }); + + describe('when given a valid component name', () => { + it('removes all matching components from the Prefab', () => { + const prefab = new Prefab('Handle_Short', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ version: 1 }), + Pickup: new PickupComponent({ version: 2 }) + } + }); + + prefab.removeComponent('NetworkRigidbody'); + + expect(prefab.components).toStrictEqual({ + Pickup: new PickupComponent({ version: 2 }), + Unknown: [] + }); + }); + }); + + describe('when given an invalid component hash', () => { + it('removes zero components from the Prefab', () => { + const prefab = new Prefab('Handle_Short', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ version: 1 }), + Pickup: new PickupComponent({ version: 2 }) + } + }); + + // @ts-expect-error Passing invalid arguments + prefab.removeComponent(0); + + expect(prefab.components).toStrictEqual({ + NetworkRigidbody: new NetworkRigidbodyComponent({ version: 1 }), + Pickup: new PickupComponent({ version: 2 }), + Unknown: [] + }); + }); + }); + + describe('when given an unknown component hash', () => { + it('removes all matching components from the Prefab', () => { + const prefab = new Prefab('Handle_Short', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ version: 1 }), + Pickup: new PickupComponent({ version: 2 }), + // @ts-expect-error Creating unknown component + TestComponent: new UnsupportedComponent({ + hash: 1337, + name: 'TestComponent', + rawData: '1111011100110001000' as BinaryString, + version: 1 + }) + } + }); + + // @ts-expect-error Passing invalid arguments + prefab.removeComponent(1337); + + expect(prefab.components).toStrictEqual({ + NetworkRigidbody: new NetworkRigidbodyComponent({ version: 1 }), + Pickup: new PickupComponent({ version: 2 }), + Unknown: [] + }); + }); + }); + + describe('when given an unknown component name', () => { + it('removes all matching components from the Prefab', () => { + const prefab = new Prefab('Handle_Short', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ version: 1 }), + Pickup: new PickupComponent({ version: 2 }), + Unknown: [ + new UnsupportedComponent({ + hash: 1337, + name: 'TestComponent', + rawData: '1111011100110001000' as BinaryString, + version: 1 + }) + ] + } + }); + + // @ts-expect-error Passing invalid arguments + prefab.removeComponent('TestComponent'); + + expect(prefab.components).toStrictEqual({ + NetworkRigidbody: new NetworkRigidbodyComponent({ version: 1 }), + Pickup: new PickupComponent({ version: 2 }), + Unknown: [] + }); + }); + }); +}); + +describe('Prefab.removeEntity()', () => { + describe('when given invalid arguments', () => { + it('throws an error', () => { + const prefab = new Prefab('Grass_Clump', { + entities: { + Fire_30100: new Entity('Fire_30100'), + Insert_Grass_7796: new Entity('Insert_Grass_7796') + } + }); + + // @ts-expect-error Passing invalid arguments + const expectedToThrow = () => prefab.removeEntity(); + const expectedError = new Error('You must pass an entity name to remove from this prefab.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + describe('when given an entity name', () => { + it('removes all matching entities from the Prefab', () => { + const prefab = new Prefab('Grass_Clump', { + entities: { + Fire_30100: new Entity('Fire_30100'), + Insert_Grass_7796: new Entity('Insert_Grass_7796') + } + }); + + prefab.removeEntity('Insert_Grass_7796'); + + expect(prefab.entities).toStrictEqual({ + Fire_30100: new Entity<'Grass_Clump'>('Fire_30100') + }); + }); + }); +}); + +describe('Prefab.removeGift()', () => { + describe('when given invalid arguments', () => { + it('throws an error', () => { + const prefab = new Prefab('Gift_Mail_Box') + .addGift(new Prefab('Dynamite')) + .addGift(new Prefab('Dynamite')) + .addGift(new Prefab('Firework')); + + // @ts-expect-error Passing invalid arguments + const expectedToThrow = () => prefab.removeGift(); + const expectedError = new Error('You must pass a gift prefab hash or name to remove from this prefab.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + describe('when given a gift prefab hash', () => { + it('removes all matching gifts from the Prefab', () => { + const prefab = new Prefab('Gift_Mail_Box') + .addGift(new Prefab('Dynamite')) + .addGift(new Prefab('Dynamite')) + .addGift(new Prefab('Firework')); + + prefab.removeGift(new Prefab('Dynamite').hash); + + expect(prefab.components.SentGift?.gifts.length).toStrictEqual(1); + }); + }); + + describe('when given a gift prefab name', () => { + it('removes all matching gifts from the Prefab', () => { + const prefab = new Prefab('Gift_Mail_Box') + .addGift(new Prefab('Dynamite')) + .addGift(new Prefab('Dynamite')) + .addGift(new Prefab('Firework')); + + prefab.removeGift(new Prefab('Dynamite').name); + + expect(prefab.components.SentGift?.gifts.length).toStrictEqual(1); + }); + }); + + describe('when given an invalid gift prefab name', () => { + it('removes all matching gifts from the Prefab', () => { + const prefab = new Prefab('Gift_Mail_Box') + .addGift(new Prefab('Dynamite')) + .addGift(new Prefab('Dynamite')) + .addGift(new Prefab('Firework')); + + // @ts-expect-error Passing invalid arguments + prefab.removeGift('Invalid_Prefab_Name'); + + expect(prefab.components.SentGift?.gifts.length).toStrictEqual(3); + }); + }); +}); + +describe('Prefab.removeSpawnArea()', () => { + it('removes the spawn area components', () => { + const prefab = new Prefab('Disk_Encounter', { + components: { + PopulationSpawnArea: new PopulationSpawnAreaComponent({ version: 1 }), + SpawnArea: new SpawnAreaComponent({ version: 1 }) + } + }); + + prefab.removeSpawnArea(); + + expect(prefab.components.PopulationSpawnArea).toStrictEqual(undefined); + expect(prefab.components.SpawnArea).toStrictEqual(undefined); + }); +}); + +describe('Prefab.setAngularVelocity()', () => { + describe('when the prefab cannot have a NetworkRigidbody component', () => { + it('sets no angular velocity', () => { + const prefab = new Prefab('Anvil'); + delete prefab.components.NetworkRigidbody; + + prefab.setAngularVelocity({ x: 69, y: 420, z: 1337 }); + const angularVelocity = prefab.getAngularVelocity(); + + expect(angularVelocity).toStrictEqual({ x: 0, y: 0, z: 0 }); + }); + }); + + describe('when the prefab can have a NetworkRigidbody component', () => { + it('sets the given angular velocity', () => { + const prefab = new Prefab('Grass_Clump'); + + prefab.setAngularVelocity({ x: 69, y: 420, z: 1337 }); + const angularVelocity = prefab.getAngularVelocity(); + + expect(angularVelocity).toStrictEqual({ x: 69, y: 420, z: 1337 }); + }); + }); + + describe('when the prefab already has a NetworkRigidbody component', () => { + it('sets the given angular velocity', () => { + const prefab = new Prefab('Grass_Clump', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ + version: 1, + angularVelocity: { x: 88, y: -88, z: -88 } + }) + } + }); + + prefab.setAngularVelocity({ x: 69, y: 420, z: 1337 }); + const angularVelocity = prefab.getAngularVelocity(); + + expect(angularVelocity).toStrictEqual({ x: 69, y: 420, z: 1337 }); + }); + }); +}); + +describe('Prefab.setGiftBoxLabel()', () => { + describe('when given invalid arguments', () => { + it('throws an error', () => { + const prefab = new Prefab('Gift_Mail_Box'); + + // @ts-expect-error Passing invalid arguments + const expectedToThrow = () => prefab.setGiftBoxLabel(); + const expectedError = new Error('You must pass a string to set as the gift box label.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + describe('when the prefab cannot have a SentGift component', () => { + it('sets no gift box label', () => { + const prefab = new Prefab('Anvil'); + delete prefab.components.SentGift; + + prefab.setGiftBoxLabel('topkek'); + const giftBoxLabel = prefab.getGiftBoxLabel(); + + expect(giftBoxLabel).toStrictEqual(''); + }); + }); + + describe('when the prefab can have a SentGift component', () => { + it('sets the given gift box label', () => { + const prefab = new Prefab('Gift_Mail_Box'); + + prefab.setGiftBoxLabel('topkek'); + const giftBoxLabel = prefab.getGiftBoxLabel(); + + expect(giftBoxLabel).toStrictEqual('topkek'); + }); + }); + + describe('when the prefab already has a SentGift component', () => { + it('sets the given gift box label', () => { + const prefab = new Prefab('Gift_Mail_Box', { + components: { + SentGift: new SentGiftComponent({ + version: 1, + senderName: 'lolwut' + }) + } + }); + + prefab.setGiftBoxLabel('topkek'); + const giftBoxLabel = prefab.getGiftBoxLabel(); + + expect(giftBoxLabel).toStrictEqual('topkek'); + }); + }); +}); + +describe('Prefab.setIntegrity()', () => { + describe('when given invalid arguments', () => { + it('throws an error', () => { + const prefab = new Prefab('Short_Sword_Blade'); + + // @ts-expect-error Passing invalid arguments + const expectedToThrow = () => prefab.setIntegrity(); + const expectedError = new Error('You must pass a number to set as the integrity.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + describe('when the prefab cannot have a DurabilityModule component', () => { + it('sets no integrity', () => { + const prefab = new Prefab('Anvil'); + delete prefab.components.DurabilityModule; + + prefab.setIntegrity(0.69); + const integrity = prefab.getIntegrity(); + + expect(integrity).toStrictEqual(1); + }); + }); + + describe('when the prefab can have a DurabilityModule component', () => { + it('sets the given integrity', () => { + const prefab = new Prefab('Short_Sword_Blade'); + + prefab.setIntegrity(0.69); + const integrity = prefab.getIntegrity(); + + expect(integrity).toBeCloseTo(0.69, 2); + }); + }); + + describe('when the prefab already has a DurabilityModule component', () => { + it('sets the given integrity', () => { + const prefab = new Prefab('Short_Sword_Blade', { + components: { + DurabilityModule: new DurabilityModuleComponent({ + version: 1, + integrity: 0.1337 + }) + } + }); + + prefab.setIntegrity(0.69); + const integrity = prefab.getIntegrity(); + + expect(integrity).toBeCloseTo(0.69, 2); + }); + }); +}); + +describe('Prefab.setKinematic()', () => { + describe('when the prefab cannot have a NetworkRigidbody component', () => { + it('sets no isKinematic', () => { + const prefab = new Prefab('Anvil'); + delete prefab.components.NetworkRigidbody; + + prefab.setKinematic(true); + const isKinematic = prefab.getKinematic(); + + expect(isKinematic).toStrictEqual(false); + }); + }); + + describe('when the prefab can have a NetworkRigidbody component', () => { + it('sets the given isKinematic', () => { + const prefab = new Prefab('Grass_Clump', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ + version: 1, + isKinematic: false + }) + } + }); + + prefab.setKinematic(true); + const isKinematic = prefab.getKinematic(); + + expect(isKinematic).toStrictEqual(true); + }); + }); + + describe('when the prefab already has a NetworkRigidbody component', () => { + it('sets the given isKinematic', () => { + const prefab = new Prefab('Grass_Clump'); + + prefab.setKinematic(true); + const isKinematic = prefab.getKinematic(); + + expect(isKinematic).toStrictEqual(true); + }); + }); + + describe('when given no arguments', () => { + it('sets isKinematic of true', () => { + const prefab = new Prefab('Grass_Clump'); + + prefab.setKinematic(); + const isKinematic = prefab.getKinematic(); + + expect(isKinematic).toStrictEqual(true); + }); + }); +}); + +describe('Prefab.setMaterial()', () => { + describe('when given invalid arguments', () => { + it('throws an error', () => { + const prefab = new Prefab('Short_Sword_Blade'); + + // @ts-expect-error Passing invalid arguments + const expectedToThrow = () => prefab.setMaterial(); + const expectedError = new Error('You must pass a PhysicalMaterialPartHash to set as the material.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + describe('when the prefab cannot have a PhysicalMaterialPart component', () => { + it('sets no material', () => { + const prefab = new Prefab('Anvil'); + delete prefab.components.PhysicalMaterialPart; + + prefab.setMaterial(PhysicalMaterialPartHash.EvinonSteelAlloy); + const materialHash = prefab.getMaterial(); + + expect(materialHash).toStrictEqual(0); + }); + }); + + describe('when the prefab can have a PhysicalMaterialPart component', () => { + describe('when given a material hash', () => { + it('sets the given material', () => { + const prefab = new Prefab('Short_Sword_Blade'); + + prefab.setMaterial(PhysicalMaterialPartHash.EvinonSteelAlloy); + const materialHash = prefab.getMaterial(); + + expect(materialHash).toStrictEqual(31502); + }); + }); + + describe('when given a material name', () => { + it('sets the given material', () => { + const prefab = new Prefab('Short_Sword_Blade'); + + prefab.setMaterial('EvinonSteelAlloy'); + const materialHash = prefab.getMaterial(); + + expect(materialHash).toStrictEqual(31502); + }); + }); + }); + + describe('when the prefab already has a PhysicalMaterialPart component', () => { + it('sets the given material', () => { + const prefab = new Prefab('Short_Sword_Blade', { + components: { + PhysicalMaterialPart: new PhysicalMaterialPartComponent({ + version: 1, + materialHash: PhysicalMaterialPartHash.Gold + }) + } + }); + + prefab.setMaterial(PhysicalMaterialPartHash.EvinonSteelAlloy); + const materialHash = prefab.getMaterial(); + + expect(materialHash).toStrictEqual(31502); + }); + }); +}); + +describe('Prefab.setOnFire()', () => { + describe('when the prefab cannot have a Fire entity', () => { + it('sets no isLit', () => { + const prefab = new Prefab('Anvil'); + prefab.entities = {}; + + prefab.setOnFire(true); + const isLit = prefab.getOnFire(); + + expect(isLit).toStrictEqual(false); + }); + }); + + describe('when the prefab can have a Fire entity', () => { + it('sets the given isLit', () => { + const prefab = new Prefab('Grass_Clump'); + + prefab.setOnFire(true); + const isLit = prefab.getOnFire(); + + expect(isLit).toStrictEqual(true); + }); + }); + + describe('when the prefab already has a Fire entity but no HeatSourceBase component', () => { + it('sets the given isLit', () => { + const prefab = new Prefab('Grass_Clump', { + entities: { + Fire_30100: new Entity('Fire_30100') + } + }); + + prefab.setOnFire(true); + const isLit = prefab.getOnFire(); + + expect(isLit).toStrictEqual(true); + }); + }); + + describe('when the prefab already has a Fire entity with a HeatSourceBase component', () => { + it('sets the given isLit', () => { + const prefab = new Prefab('Grass_Clump', { + entities: { + Fire_30100: new Entity('Fire_30100', { + components: { + HeatSourceBase: new HeatSourceBaseComponent({ + version: 1, + isLit: false + }) + } + }) + } + }); + + prefab.setOnFire(true); + const isLit = prefab.getOnFire(); + + expect(isLit).toStrictEqual(true); + }); + }); + + describe('when given no arguments', () => { + it('sets isLit of true', () => { + const prefab = new Prefab('Grass_Clump'); + + prefab.setOnFire(); + const isLit = prefab.getOnFire(); + + expect(isLit).toStrictEqual(true); + }); + }); +}); + +describe('Prefab.setPosition()', () => { + describe('when the prefab cannot have a NetworkRigidbody component', () => { + it('sets the given position on prefab only', () => { + const prefab = new Prefab('Anvil'); + delete prefab.components.NetworkRigidbody; + + prefab.setPosition({ x: 69, y: 420, z: 1337 }); + const position = prefab.getPosition(); + + expect(position).toStrictEqual({ x: 69, y: 420, z: 1337 }); + // @ts-expect-error Deleted object becomes `never` + expect(prefab.components.NetworkRigidbody?.position).toStrictEqual(undefined); + }); + }); + + describe('when the prefab can have a NetworkRigidbody component', () => { + it('sets the given position on prefab and NetworkRigidbody component', () => { + const prefab = new Prefab('Grass_Clump'); + + prefab.setPosition({ x: 69, y: 420, z: 1337 }); + const position = prefab.getPosition(); + + expect(position).toStrictEqual({ x: 69, y: 420, z: 1337 }); + expect(prefab.components.NetworkRigidbody?.position).toStrictEqual({ x: 69, y: 420, z: 1337 }); + }); + }); + + describe('when the prefab already has a NetworkRigidbody component', () => { + it('sets the given position on prefab and NetworkRigidbody component', () => { + const prefab = new Prefab('Grass_Clump', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ + version: 1, + position: { x: 88, y: -88, z: -88 } + }) + } + }); + + prefab.setPosition({ x: 69, y: 420, z: 1337 }); + const position = prefab.getPosition(); + + expect(position).toStrictEqual({ x: 69, y: 420, z: 1337 }); + expect(prefab.components.NetworkRigidbody?.position).toStrictEqual({ x: 69, y: 420, z: 1337 }); + }); + }); +}); + +describe('Prefab.setRotation()', () => { + describe('when the prefab cannot have a NetworkRigidbody component', () => { + it('sets the given rotation on prefab only', () => { + const prefab = new Prefab('Anvil'); + delete prefab.components.NetworkRigidbody; + + prefab.setRotation({ x: 0.69, y: 0.42, z: -0.1337, w: 0.88 }); + const rotation = prefab.getRotation(); + + expect(rotation).toStrictEqual({ x: 0.69, y: 0.42, z: -0.1337, w: 0.88 }); + // @ts-expect-error Deleted object becomes `never` + expect(prefab.components.NetworkRigidbody?.rotation).toStrictEqual(undefined); + }); + }); + + describe('when the prefab can have a NetworkRigidbody component', () => { + it('sets the given rotation on prefab and NetworkRigidbody component', () => { + const prefab = new Prefab('Grass_Clump'); + + prefab.setRotation({ x: 0.69, y: 0.42, z: -0.1337, w: 0.88 }); + const rotation = prefab.getRotation(); + + expect(rotation).toStrictEqual({ x: 0.69, y: 0.42, z: -0.1337, w: 0.88 }); + expect(prefab.components.NetworkRigidbody?.rotation).toStrictEqual({ x: 0.69, y: 0.42, z: -0.1337, w: 0.88 }); + }); + }); + + describe('when the prefab already has a NetworkRigidbody component', () => { + it('sets the given rotation on prefab and NetworkRigidbody component', () => { + const prefab = new Prefab('Grass_Clump', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ + version: 1, + rotation: { x: 0.88, y: -0.88, z: -0.88, w: 0.88 } + }) + } + }); + + prefab.setRotation({ x: 0.69, y: 0.42, z: -0.1337, w: 0.88 }); + const rotation = prefab.getRotation(); + + expect(rotation).toStrictEqual({ x: 0.69, y: 0.42, z: -0.1337, w: 0.88 }); + expect(prefab.components.NetworkRigidbody?.rotation).toStrictEqual({ x: 0.69, y: 0.42, z: -0.1337, w: 0.88 }); + }); + }); +}); + +describe('Prefab.setScale()', () => { + describe('when given invalid arguments', () => { + it('throws an error', () => { + const prefab = new Prefab('Short_Sword_Blade'); + + // @ts-expect-error Passing invalid arguments + const expectedToThrow = () => prefab.setScale(); + const expectedError = new Error('You must pass a number to set as the scale.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + it('sets the given scale', () => { + const prefab = new Prefab('Short_Sword_Blade'); + + prefab.setScale(0.69); + const scale = prefab.getScale(); + + expect(scale).toBeCloseTo(0.69, 2); + }); +}); + +describe('Prefab.setServerSleeping()', () => { + describe('when the prefab cannot have a NetworkRigidbody component', () => { + it('sets no isServerSleeping', () => { + const prefab = new Prefab('Anvil'); + delete prefab.components.NetworkRigidbody; + + prefab.setServerSleeping(true); + const isServerSleeping = prefab.getServerSleeping(); + + expect(isServerSleeping).toStrictEqual(false); + }); + }); + + describe('when the prefab can have a NetworkRigidbody component', () => { + it('sets the given isServerSleeping', () => { + const prefab = new Prefab('Grass_Clump'); + + prefab.setServerSleeping(true); + const isServerSleeping = prefab.getServerSleeping(); + + expect(isServerSleeping).toStrictEqual(true); + }); + }); + + describe('when the prefab already has a NetworkRigidbody component', () => { + it('sets the given isServerSleeping', () => { + const prefab = new Prefab('Grass_Clump', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ + version: 1, + isServerSleeping: false + }) + } + }); + + prefab.setServerSleeping(true); + const isServerSleeping = prefab.getServerSleeping(); + + expect(isServerSleeping).toStrictEqual(true); + }); + }); + + describe('when given no arguments', () => { + it('sets isServerSleeping of true', () => { + const prefab = new Prefab('Grass_Clump'); + + prefab.setServerSleeping(); + const isServerSleeping = prefab.getServerSleeping(); + + expect(isServerSleeping).toStrictEqual(true); + }); + }); +}); + +describe('Prefab.setServings()', () => { + describe('when given invalid arguments', () => { + it('throws an error', () => { + const prefab = new Prefab('Potion_Medium'); + + // @ts-expect-error Passing invalid arguments + const expectedToThrow = () => prefab.setServings(); + const expectedError = new Error('You must pass a number to set as the amount of servings.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + describe('when the prefab cannot have a LiquidContainer component', () => { + it('sets no servings', () => { + const prefab = new Prefab('Anvil'); + delete prefab.components.LiquidContainer; + + prefab.setServings(69); + const servings = prefab.getServings(); + + expect(servings).toStrictEqual(0); + }); + }); + + describe('when the prefab can have a LiquidContainer component', () => { + it('sets the given amount of servings', () => { + const prefab = new Prefab('Potion_Medium'); + + prefab.setServings(69); + const servings = prefab.getServings(); + + expect(servings).toStrictEqual(69); + }); + }); + + describe('when the prefab already has a LiquidContainer component', () => { + it('sets the given amount of servings', () => { + const prefab = new Prefab('Potion_Medium', { + components: { + LiquidContainer: new LiquidContainerComponent({ + version: 1, + contentLevel: 1337 + }) + } + }); + + prefab.setServings(69); + const servings = prefab.getServings(); + + expect(servings).toStrictEqual(69); + }); + }); +}); + +describe('Prefab.setSpawnArea()', () => { + describe('when given invalid arguments', () => { + it('throws an error', () => { + const prefab = new Prefab('Directional_Encounter'); + + // @ts-expect-error Passing invalid arguments + const expectedToThrow = () => prefab.setSpawnArea(); + const expectedError = new Error('You must pass a population definition hash or name to set on this spawn area.'); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + describe('when the prefab cannot have PopulationSpawnArea and SpawnArea components', () => { + it('sets no spawn area', () => { + const prefab = new Prefab('Anvil'); + delete prefab.components.PopulationSpawnArea; + delete prefab.components.SpawnArea; + + prefab.setSpawnArea(PopulationDefinitionHash.WyrmPopulation); + + expect(prefab.components.PopulationSpawnArea).toStrictEqual(undefined); + expect(prefab.components.SpawnArea).toStrictEqual(undefined); + }); + }); + + describe('when the prefab can have PopulationSpawnArea and SpawnArea components', () => { + describe('when given the required arguments', () => { + describe('when given a population definition hash', () => { + it('sets the given population on the spawn area with additional default values', () => { + const prefab = new Prefab('Directional_Encounter'); + + prefab.setSpawnArea(PopulationDefinitionHash.WyrmPopulation); + + expect(prefab.components.PopulationSpawnArea?.currentPopulation).toStrictEqual(5); + expect(prefab.components.PopulationSpawnArea?.isOneOff).toStrictEqual(false); + expect(prefab.components.PopulationSpawnArea?.isPopulationStarted).toStrictEqual(true); + expect(prefab.components.PopulationSpawnArea?.maxPopulation).toStrictEqual(20); + expect(prefab.components.PopulationSpawnArea?.numberOfSpawnPoints).toStrictEqual(40); + expect(prefab.components.PopulationSpawnArea?.startingPopulation).toStrictEqual(5); + expect(prefab.components.SpawnArea?.size).toStrictEqual(5); + }); + }); + + describe('when given a population definition name', () => { + it('sets the given population on the spawn area with additional default values', () => { + const prefab = new Prefab('Directional_Encounter'); + + prefab.setSpawnArea('WyrmPopulation'); + + expect(prefab.components.PopulationSpawnArea?.currentPopulation).toStrictEqual(5); + expect(prefab.components.PopulationSpawnArea?.isOneOff).toStrictEqual(false); + expect(prefab.components.PopulationSpawnArea?.isPopulationStarted).toStrictEqual(true); + expect(prefab.components.PopulationSpawnArea?.maxPopulation).toStrictEqual(20); + expect(prefab.components.PopulationSpawnArea?.numberOfSpawnPoints).toStrictEqual(40); + expect(prefab.components.PopulationSpawnArea?.startingPopulation).toStrictEqual(5); + expect(prefab.components.SpawnArea?.size).toStrictEqual(5); + }); + }); + }); + + describe('when given the additional arguments', () => { + it('sets the given population on the spawn area with additional given values', () => { + const prefab = new Prefab('Directional_Encounter'); + + prefab.setSpawnArea(PopulationDefinitionHash.WyrmPopulation, { + currentPopulation: 69, + isOneOff: true, + isPopulationStarted: false, + maxPopulation: 1337, + numberOfSpawnPoints: 69, + size: 420, + startingPopulation: 1337 + }); + + expect(prefab.components.PopulationSpawnArea?.currentPopulation).toStrictEqual(69); + expect(prefab.components.PopulationSpawnArea?.isOneOff).toStrictEqual(true); + expect(prefab.components.PopulationSpawnArea?.isPopulationStarted).toStrictEqual(false); + expect(prefab.components.PopulationSpawnArea?.maxPopulation).toStrictEqual(1337); + expect(prefab.components.PopulationSpawnArea?.numberOfSpawnPoints).toStrictEqual(69); + expect(prefab.components.PopulationSpawnArea?.startingPopulation).toStrictEqual(1337); + expect(prefab.components.SpawnArea?.size).toStrictEqual(420); + }); + }); + }); + + describe('when the prefab already has PopulationSpawnArea and SpawnArea components', () => { + it('sets the given spawn area', () => { + const prefab = new Prefab('Directional_Encounter', { + components: { + PopulationSpawnArea: new PopulationSpawnAreaComponent({ + version: 2, + definition: PopulationDefinitionHash.TurabadaOverworldPopulation + }), + SpawnArea: new SpawnAreaComponent({ + version: 1, + size: 1337 + }) + } + }); + + prefab.setSpawnArea(PopulationDefinitionHash.WyrmPopulation, { size: 69 }); + + expect(prefab.components.PopulationSpawnArea?.definition).toStrictEqual(PopulationDefinitionHash.WyrmPopulation); + expect(prefab.components.SpawnArea?.size).toStrictEqual(69); + }); + }); +}); + +describe('Prefab.setVelocity()', () => { + describe('when the prefab cannot have a NetworkRigidbody component', () => { + it('sets no velocity', () => { + const prefab = new Prefab('Anvil'); + delete prefab.components.NetworkRigidbody; + + prefab.setVelocity({ x: 69, y: 420, z: 1337 }); + const velocity = prefab.getVelocity(); + + expect(velocity).toStrictEqual({ x: 0, y: 0, z: 0 }); + }); + }); + + describe('when the prefab can have a NetworkRigidbody component', () => { + it('sets the given velocity', () => { + const prefab = new Prefab('Grass_Clump'); + + prefab.setVelocity({ x: 69, y: 420, z: 1337 }); + const velocity = prefab.getVelocity(); + + expect(velocity).toStrictEqual({ x: 69, y: 420, z: 1337 }); + }); + }); + + describe('when the prefab already has a NetworkRigidbody component', () => { + it('sets the given velocity', () => { + const prefab = new Prefab('Grass_Clump', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ + version: 1, + velocity: { x: 88, y: -88, z: -88 } + }) + } + }); + + prefab.setVelocity({ x: 69, y: 420, z: 1337 }); + const velocity = prefab.getVelocity(); + + expect(velocity).toStrictEqual({ x: 69, y: 420, z: 1337 }); + }); + }); +}); + +describe('Prefab.toBinary()', () => { + it('returns the BinaryString of the prefab', () => { + const prefab = new Prefab('Torch', { + components: { + Pickup: new PickupComponent({ version: 2 }) + }, + entities: { + Fire_30100: new Entity('Fire_30100', { + components: { + HeatSourceBase: new HeatSourceBaseComponent({ + version: 1, + isLit: true + }) + } + }) + }, + children: [{ parentHash: 0, prefab: new Prefab('Guard') }] + }); + + const componentVersions = prefab.getComponentVersions(); + const binaryString = prefab.toBinary(componentVersions); + + expect(binaryString).toStrictEqual( + '000000000000000011011101011110100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111110000000000000000000000000111111100000000000000000000000010101101011000100000011101101100000000000000000000000000100000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111010110010100000000000000000000000000110000101111101001110111111011110100000000000000000000000000000000110000110000000000000000000000000000000001010001111101101100000000000000000000000111000000011101011110000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000011001001110110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111110000000000000000000000000111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' + ); + }); +}); + +describe('Prefab.toSaveString()', () => { + it('returns the SaveString of the prefab', () => { + const prefab = new Prefab('Torch', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ version: 1 }), + Pickup: new PickupComponent({ version: 2 }) + }, + entities: { + Fire_30100: new Entity('Fire_30100', { + components: { + HeatSourceBase: new HeatSourceBaseComponent({ + version: 1, + isLit: true + }) + } + }) + }, + children: [{ parentHash: 0, prefab: new Prefab('Guard') }] + }); + + const saveString = prefab.toSaveString(); + + expect(saveString).toStrictEqual( + '56698,204,56698,0,0,0,0,0,0,1065353216,1065353216,2290978823,418,0,0,0,0,0,0,1065353216,0,0,0,0,0,0,363610349,2147483664,536870912,0,0,7525,48,3198024656,12,805306368,85945344,459223,2147483648,0,134217728,1614,3221225472,0,0,0,0,0,33292288,33292288,0,0,0,|3,2290978823,1,1454441398,2,4109360768,1,' + ); + }); + + describe('when the binary data does not align to full bytes', () => { + it('returns a SaveString containing padded bits of the prefab', () => { + const prefab = new Prefab('Torch', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ version: 1 }), + Pickup: new PickupComponent({ version: 2 }) + }, + entities: { + Fire_30100: new Entity('Fire_30100', { + components: { + HeatSourceBase: new HeatSourceBaseComponent({ + version: 1, + isLit: true + }) + } + }) + }, + children: [{ parentHash: 0, prefab: new Prefab('Guard') }] + }); + + const spy = vi.spyOn(prefab, 'toBinary'); + spy.mockImplementationOnce( + /* Added 25 false bits at the end to force Prefab.toSaveString() to skip bit alignment. */ + () => + '000000000000000011011101011110100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111110000000000000000000000000111111100000000000000000000000100010001000110110010000000001110000000000000000000000011010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101011010110001000000111011011000000000000000000000000001000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001110101100101000000000000000000000000001100001011111010011101111110111101000000000000000000000000000000001100001100000000000000000000000000000000010100011111011011000000000000000000000001110000000111010111100000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000110010011101100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111100000000000000000000000001111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' as BinaryString + ); + + const saveString = prefab.toSaveString(); + + expect(saveString).toStrictEqual( + '56698,204,56698,0,0,0,0,0,0,1065353216,1065353216,2290978823,418,0,0,0,0,0,0,1065353216,0,0,0,0,0,0,363610349,2147483664,536870912,0,0,7525,48,3198024656,12,805306368,85945344,459223,2147483648,0,134217728,1614,3221225472,0,0,0,0,0,33292288,33292288,0,0,0,|3,2290978823,1,1454441398,2,4109360768,1,' + ); + }); + }); + + describe('when the prefab contains components with indeterminate versions', () => { + describe('when not excluding component versions', () => { + it('throws an error', () => { + const prefab = new Prefab('Torch', { + components: { + Unknown: [ + new UnsupportedComponent({ + hash: 1337, + name: 'Unknown_1337', + rawData: '11110111001100010000' as BinaryString, + version: 0 + }) + ] + } + }); + + const expectedToThrow = () => prefab.toSaveString(); + const expectedError = new Error( + 'Prefab contains components with version `0`. Current in-game versions for those components are not available. The produced save string will not contain component versions and may not be spawnable in-game.\n\nYou may call `.toSaveString(true)` to force producing a save string with this limitation.\n' + ); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + + describe('when ignoring indeterminate component versions', () => { + it('returns a save string without component versions', () => { + const prefab = new Prefab('Torch', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ version: 1 }), + Unknown: [ + new UnsupportedComponent({ + hash: 1337, + name: 'Unknown_1337', + rawData: '11110111001100010000' as BinaryString, + version: 0 + }) + ] + } + }); + + const saveString = prefab.toSaveString({ + ignoreIndeterminateComponentVersions: true + }); + + expect(saveString).toStrictEqual( + '56698,116,56698,0,0,0,0,0,0,1065353216,1065353216,2290978823,418,0,0,0,0,0,0,1065353216,0,0,0,0,0,0,334,1073741829,1036795904,0,0,' + ); + }); + }); + + describe('when excluding component versions', () => { + it('returns a save string without component versions', () => { + const prefab = new Prefab('Torch', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ version: 1 }) + } + }); + + const saveString = prefab.toSaveString({ + excludeComponentVersions: true + }); + + expect(saveString).toStrictEqual( + '56698,108,56698,0,0,0,0,0,0,1065353216,1065353216,2290978823,418,0,0,0,0,0,0,1065353216,0,0,0,0,0,0,0,0,0,' + ); + }); + }); + }); +}); diff --git a/src/Prefab.ts b/src/Prefab.ts index 17b6e20..401a071 100644 --- a/src/Prefab.ts +++ b/src/Prefab.ts @@ -1,41467 +1,1770 @@ -export type Prefab = { - hash: number; - name: string; - embedded: { - [entity: string]: { - hash: number; - name: string; - savables: { - [savable: string]: { - hash: number; - name: string; - }; - }; - }; - }; +import type { Component } from './components/Component.js'; +import type { ATTPrefabHash } from './types/ATTPrefabHash.js'; +import type { ATTPrefabName } from './types/ATTPrefabName.js'; +import type { AngularVelocity } from './types/AngularVelocity.js'; +import type { BinaryString } from './types/BinaryString.js'; +import type { EntityKey } from './types/EntityKey.js'; +import type { PopulationDefinitionName } from './types/PopulationDefinitionName.js'; +import type { Position } from './types/Position.js'; +import type { PrefabChild } from './types/PrefabChild.js'; +import type { PrefabComponents } from './types/PrefabComponents.js'; +import type { PrefabEntities } from './types/PrefabEntities.js'; +import type { Rotation } from './types/Rotation.js'; +import type { SaveString } from './types/SaveString.js'; +import type { SetSpawnAreaProps } from './types/SetSpawnAreaProps.js'; +import type { Velocity } from './types/Velocity.js'; + +import { inspect } from 'node:util'; + +import { BinaryData, type BinaryDataOptions } from './BinaryData.js'; +import { BinaryReader } from './BinaryReader.js'; +import { BinaryWriter } from './BinaryWriter.js'; +import { Entity } from './Entity.js'; +import { DurabilityModuleComponent } from './components/DurabilityModuleComponent.js'; +import { HeatSourceBaseComponent } from './components/HeatSourceBaseComponent.js'; +import { LiquidContainerComponent } from './components/LiquidContainerComponent.js'; +import { NetworkRigidbodyComponent } from './components/NetworkRigidbodyComponent.js'; +import { PhysicalMaterialPartComponent } from './components/PhysicalMaterialPartComponent.js'; +import { PopulationSpawnAreaComponent } from './components/PopulationSpawnAreaComponent.js'; +import { SentGiftComponent } from './components/SentGiftComponent.js'; +import { SpawnAreaComponent } from './components/SpawnAreaComponent.js'; +import * as constants from './constants.js'; +import { ATTPrefabs } from './types/ATTPrefabs.js'; +import { ComponentHash } from './types/ComponentHash.js'; +import { PhysicalMaterialPartHash } from './types/PhysicalMaterialPartHash.js'; +import { PopulationDefinitionHash } from './types/PopulationDefinitionHash.js'; +import { isSavableComponent } from './utils/isSavableComponent.js'; +import { readChildren } from './utils/readChildren.js'; +import { readComponents } from './utils/readComponents.js'; +import { readEntities } from './utils/readEntities.js'; +import { writeChildren } from './utils/writeChildren.js'; +import { writeComponents } from './utils/writeComponents.js'; +import { writeEntities } from './utils/writeEntities.js'; + +type PrefabHash = (typeof ATTPrefabs)[TPrefabName]['hash']; + +type PrefabName = (typeof ATTPrefabs)[TPrefabName]['name']; + +type ToSaveStringOptions = { + excludeComponentVersions?: boolean | undefined; + ignoreIndeterminateComponentVersions?: boolean | undefined; }; -export const Prefab = { - '(Child_Node)_Climbing_Tower_Teleporter_Node': { - 'hash': 5078, - 'name': '(Child Node) Climbing Tower Teleporter Node', - 'embedded': { - '(Child_Node)_Climbing_Tower_Teleporter_Node_56704': { - 'hash': 56704, - 'name': '(Child Node) Climbing Tower Teleporter Node', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - }, - 'ClimbingTowerTeleporterNode': { - 'hash': 392234266, - 'name': 'ClimbingTowerTeleporterNode' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - } - } - }, - 'Visualizer_56774': { - 'hash': 56774, - 'name': 'Visualizer', - 'savables': { - 'ClimbingTowerProgressionVisualizer': { - 'hash': 623957243, - 'name': 'ClimbingTowerProgressionVisualizer' - } - } - } - } - }, - '(OriginalRoot_Node)_Climbing_Tower_Teleporter_Node': { - 'hash': 55446, - 'name': '(OriginalRoot Node) Climbing Tower Teleporter Node', - 'embedded': { - '(OriginalRoot_Node)_Climbing_Tower_Teleporter_Node_55438': { - 'hash': 55438, - 'name': '(OriginalRoot Node) Climbing Tower Teleporter Node', - 'savables': { - 'ClimbingTowerTeleporterNode': { - 'hash': 392234266, - 'name': 'ClimbingTowerTeleporterNode' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - } - } - } - } - }, - '(Original_Child_Node)_Climbing_Tower_Teleporter_Node': { - 'hash': 26916, - 'name': '(Original Child Node) Climbing Tower Teleporter Node', - 'embedded': { - '(Original_Child_Node)_Climbing_Tower_Teleporter_Node_26908': { - 'hash': 26908, - 'name': '(Original Child Node) Climbing Tower Teleporter Node', - 'savables': { - 'ClimbingTowerTeleporterNode': { - 'hash': 392234266, - 'name': 'ClimbingTowerTeleporterNode' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - } - } - } - } - }, - '(Root_Node)_Climbing_Tower_Teleporter_Node': { - 'hash': 7668, - 'name': '(Root Node) Climbing Tower Teleporter Node', - 'embedded': { - '(Root_Node)_Climbing_Tower_Teleporter_Node_56148': { - 'hash': 56148, - 'name': '(Root Node) Climbing Tower Teleporter Node', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - }, - 'ClimbingTowerTeleporterNode': { - 'hash': 392234266, - 'name': 'ClimbingTowerTeleporterNode' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - } - } - }, - 'Visualizer_56330': { - 'hash': 56330, - 'name': 'Visualizer', - 'savables': { - 'ClimbingTowerProgressionVisualizer': { - 'hash': 623957243, - 'name': 'ClimbingTowerProgressionVisualizer' - } - } - } - } - }, - 'ATM_Coin_Bank': { - 'hash': 9780, - 'name': 'ATM Coin Bank', - 'embedded': { - 'ATM_Coin_Bank_7202': { - 'hash': 7202, - 'name': 'ATM Coin Bank', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - }, - 'Base_Dock_28320': { - 'hash': 28320, - 'name': 'Base Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'DepositDock_33532': { - 'hash': 33532, - 'name': 'DepositDock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Grab_22452': { - 'hash': 22452, - 'name': 'Grab', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Hand_Touch_46540': { - 'hash': 46540, - 'name': 'Hand Touch', - 'savables': {} - }, - 'Withdraw_Dock_34750': { - 'hash': 34750, - 'name': 'Withdraw Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - } - } - }, - 'Absolute_Apple_Tree_Variant': { - 'hash': 15898, - 'name': 'Absolute Apple Tree Variant', - 'embedded': { - 'Absolute_Apple_Tree_Variant_58592': { - 'hash': 58592, - 'name': 'Absolute Apple Tree Variant', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Absolute_Blueberry_Tree_Variant': { - 'hash': 16322, - 'name': 'Absolute Blueberry Tree Variant', - 'embedded': { - 'Absolute_Blueberry_Tree_Variant_24412': { - 'hash': 24412, - 'name': 'Absolute Blueberry Tree Variant', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'And': { - 'hash': 42422, - 'name': 'And', - 'embedded': {} - }, - 'Anvil': { - 'hash': 23182, - 'name': 'Anvil', - 'embedded': { - 'Anvil_57386': { - 'hash': 57386, - 'name': 'Anvil', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - } - } - }, - 'Anvil_Training': { - 'hash': 24218, - 'name': 'Anvil Training', - 'embedded': { - 'Anvil_Training_24216': { - 'hash': 24216, - 'name': 'Anvil Training', - 'savables': {} - } - } - }, - 'Apple_Core_Burnt': { - 'hash': 50484, - 'name': 'Apple Core Burnt', - 'embedded': { - 'Apple_Core_Burnt_10462': { - 'hash': 10462, - 'name': 'Apple Core Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_5784': { - 'hash': 5784, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Apple_Core_Cooked': { - 'hash': 15500, - 'name': 'Apple Core Cooked', - 'embedded': { - 'Apple_Core_Cooked_10462': { - 'hash': 10462, - 'name': 'Apple Core Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_5784': { - 'hash': 5784, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Apple_Core_Ripe': { - 'hash': 902, - 'name': 'Apple Core Ripe', - 'embedded': { - 'Apple_Core_Ripe_10462': { - 'hash': 10462, - 'name': 'Apple Core Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_5784': { - 'hash': 5784, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Apple_Core_Unripe': { - 'hash': 31614, - 'name': 'Apple Core Unripe', - 'embedded': { - 'Apple_Core_Unripe_10462': { - 'hash': 10462, - 'name': 'Apple Core Unripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'RaycastCrafter': { - 'hash': 2815374842, - 'name': 'RaycastCrafter' - } - } - }, - 'Cooking_5784': { - 'hash': 5784, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Apple_Flower_Bloom': { - 'hash': 12580, - 'name': 'Apple Flower Bloom', - 'embedded': { - 'Apple_Flower_Bloom_29560': { - 'hash': 29560, - 'name': 'Apple Flower Bloom', - 'savables': {} - } - } - }, - 'Apple_Flower_Bud': { - 'hash': 12578, - 'name': 'Apple Flower Bud', - 'embedded': { - 'Apple_Flower_Bud_35946': { - 'hash': 35946, - 'name': 'Apple Flower Bud', - 'savables': {} - } - } - }, - 'Apple_Full_Burnt': { - 'hash': 62102, - 'name': 'Apple Full Burnt', - 'embedded': { - 'Apple_Core_Spawner_52298': { - 'hash': 52298, - 'name': 'Apple Core Spawner', - 'savables': {} - }, - 'Apple_Full_Burnt_57036': { - 'hash': 57036, - 'name': 'Apple Full Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_11820': { - 'hash': 11820, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Apple_Full_Cooked': { - 'hash': 14844, - 'name': 'Apple Full Cooked', - 'embedded': { - 'Apple_Core_Spawner_53358': { - 'hash': 53358, - 'name': 'Apple Core Spawner', - 'savables': {} - }, - 'Apple_Full_Cooked_56646': { - 'hash': 56646, - 'name': 'Apple Full Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_5588': { - 'hash': 5588, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Apple_Full_Ripe': { - 'hash': 40010, - 'name': 'Apple Full Ripe', - 'embedded': { - 'Apple_Core_Spawner_56836': { - 'hash': 56836, - 'name': 'Apple Core Spawner', - 'savables': {} - }, - 'Apple_Full_Ripe_56174': { - 'hash': 56174, - 'name': 'Apple Full Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_2434': { - 'hash': 2434, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } +export type PrefabProps = { + position?: Position | undefined; + rotation?: Rotation | undefined; + scale?: number | undefined; + components?: Partial | undefined; + entities?: Partial> | undefined; + children?: PrefabChild[] | undefined; +}; + +/* c8 ignore start */ +const FALLBACK_DURABILITY_MODULE_VERSION = + constants.latestSupportedComponentVersions.get(ComponentHash.DurabilityModule) ?? + constants.latestDurabilityModuleComponentVersion; + +const FALLBACK_HEAT_SOURCE_BASE_VERSION = + constants.latestSupportedComponentVersions.get(ComponentHash.HeatSourceBase) ?? + constants.latestHeatSourceBaseComponentVersion; + +const FALLBACK_LIQUID_CONTAINER_VERSION = + constants.latestSupportedComponentVersions.get(ComponentHash.LiquidContainer) ?? + constants.latestLiquidContainerComponentVersion; + +const FALLBACK_PHYSICAL_MATERIAL_PART_VERSION = + constants.latestSupportedComponentVersions.get(ComponentHash.PhysicalMaterialPart) ?? + constants.latestPhysicalMaterialPartComponentVersion; + +const FALLBACK_POPULATION_SPAWN_AREA_VERSION = + constants.latestSupportedComponentVersions.get(ComponentHash.PopulationSpawnArea) ?? + constants.latestPopulationSpawnAreaComponentVersion; + +const FALLBACK_NETWORK_RIGIDBODY_VERSION = + constants.latestSupportedComponentVersions.get(ComponentHash.NetworkRigidbody) ?? + constants.latestNetworkRigidbodyComponentVersion; + +const FALLBACK_SENT_GIFT_VERSION = + constants.latestSupportedComponentVersions.get(ComponentHash.SentGift) ?? constants.latestSentGiftComponentVersion; + +const FALLBACK_SPAWN_AREA_VERSION = + constants.latestSupportedComponentVersions.get(ComponentHash.SpawnArea) ?? constants.latestSpawnAreaComponentVersion; +/* c8 ignore stop */ + +/** + * A JavaScript object representation of an _A Township Tale_ in-game prefab. + * + * @see [Class: `Prefab`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/Prefab.md) + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Handle_Short'); + * // or + * const prefab = Prefab.fromSaveString<'Handle_Short'>(mySaveString); + * // or + * const prefab = Prefab.fromBinary<'Handle_Short'>(myBinaryString); + */ +export class Prefab { + /** + * The name of the prefab. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Handle_Short'); + * + * const name = prefab.name; + * // `name` is `'Handle_Short'` + */ + readonly name: PrefabName; + + /** + * The hash of the prefab. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Handle_Short'); + * + * const hash = prefab.hash; + * // `hash` is `42230` + */ + readonly hash: PrefabHash; + + /** + * The position of the prefab. + * + * ⚠️ Note that although you can safely read from this public property, you should not modify this + * property directly. This is because some prefabs also use a `NetworkRigidbodyComponent` to + * control their position. You can safely set the position of a prefab using the + * `setPosition(position)` method. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Handle_Short', { + * position: { x: 420, y: 69, z: 1337 } + * }); + * + * const position = prefab.position; + * // `position` is `{ x: 420, y: 69, z: 1337 }` + */ + position: Position; + + /** + * The rotation of the prefab. + * + * Note that although you can safely read from this public property, you should not modify this + * property directly. This is because some prefabs also use a `NetworkRigidbodyComponent` to + * control their rotation. You can safely set the rotation of a prefab using the + * `setRotation(rotation)` method. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Handle_Short', { + * rotation: { x: 0.42, y: -0.69, z: -0.1337, w: 0.88 } + * }); + * + * const rotation = prefab.rotation; + * // `rotation` is `{ x: 0.42, y: -0.69, z: -0.1337, w: 0.88 }` + */ + rotation: Rotation; + + /** + * The scale of the prefab. + * + * Contains the scale of the prefab. You can also set the scale of a prefab using the + * `setScale(scale)` method. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Handle_Short', { + * scale: 0.69 + * }); + * + * const scale = prefab.scale; + * // `scale` is approx. `0.69` (within JavaScript floating point precision) + */ + scale: number; + + /** + * A map of the stored components. + * + * Provides access to the components stored in this prefab. Components are keyed to their + * respective names, unless its data contained an unrecognised hash. In that case, the component + * will be stored in an array under the `Unknown` key. + * + * 💡 It might be easier to add components using the `addComponent(component)` method. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Handle_Short', { + * components: { + * NetworkRigidbody: new NetworkRigidbodyComponent({ version: 1 }) + * } + * }); + * + * const components = prefab.components; + * // `components` is `{ + * // NetworkRigidbody: NetworkRigidbodyComponent { + * // hash: 2290978823, + * // name: 'NetworkRigidbody', + * // position: { x: 0, y: 0, z: 0 }, + * // rotation: { x: 0, y: 0, z: 0, w: 1 }, + * // isKinematic: false, + * // isServerSleeping: false, + * // velocity: { x: 0, y: 0, z: 0 }, + * // angularVelocity: { x: 0, y: 0, z: 0 } + * // }, + * // Unknown: [] + * // }` + */ + components: PrefabComponents; + + /** + * A map of the stored entities. + * + * Provides access to the entities stored in this prefab. Entities are keyed to a combination of + * their respective names and hashes, unless its data contained an unrecognised hash. In that + * case, the entity will be keyed as `Unknown_` followed by its hash. The reason that entities + * cannot be keyed without their hashes (like components) is because some prefabs have multiple + * entities with the same name. For example, the `Handle_Fist` prefab has several `Slot_Deco` + * entities that are only differentiated by their hash. Conversely, it's also possible that an + * entity exists on different prefabs with the same name but different hashes. For example, the + * `Fire` entity exists on the `Infinite_Fire` prefab with hash `8488`, but exists on the + * `Grass_Clump` prefab with hash `30100`. For this reason, _ATT String Transcoder_ uses spawn + * infodumps from the game to figure out which entities belong to which prefabs and uses this data + * to provide you with auto-complete options. + * + * ⚠️ Unfortunately this means that it's not easy to tell upfront which hash a `Fire` entity has on + * a prefab that you're building. Please ensure that you assign a key that is identical to the + * entity key (which is name, underscore, and hash). + * + * 💡 It might be easier to add entities using the `addEntity(entity)` method. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Handle_Short', { + * entities: { + * // Please note the keys include the hash, not just the name. + * Slot_Multi_6136: new Entity('Slot_Multi_6136'), + * Slot_Multi_6138: new Entity('Slot_Multi_6138'), + * Unknown_1337: new Entity('Unknown', { hash: 1337 }) + * } + * }); + * + * const entities = prefab.entities; + * // `entities` is `{ + * // Slot_Multi_6136: Entity { + * // hash: 6136, + * // name: 'Slot_Multi', + * // isAlive: true, + * // components: { Unknown: [] } + * // }, + * // Slot_Multi_6138: Entity { + * // hash: 6138, + * // name: 'Slot_Multi', + * // isAlive: true, + * // components: { Unknown: [] } + * // }, + * // Unknown_1337: Entity { + * // hash: 1337, + * // name: 'Unknown', + * // isAlive: true, + * // components: { Unknown: [] } + * // }, + * // }` + */ + entities: PrefabEntities>; + + /** + * An array of the stored child prefabs. + * + * Contains an array of objects that map nested prefabs to entities on the current prefab. + * + * ⚠️ Note that the entity _does not need to exist_ in the prefab in your program! The ATT game + * server will fill in the blanks. For example, if you create a save string for a `Handle_Short` + * prefab with several children and no entities on it, and spawn it in-game, it will in fact + * have all its usual entities to which child prefabs can attach. + * + * 💡 It might be easier to add child prefabs using the `addChildPrefab(parentKey, childPrefab)` + * method. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Handle_Short', { + * children: [ + * { + * // Please note the entity hash below wasn't defined elsewhere in this prefab, yet this will work when spawned in-game. + * parentHash: 6136, // The hash for `Slot_Multi_6136` on `Handle_Short` prefab. + * prefab: new Prefab('Guard') + * } + * ] + * }); + * + * const children = prefab.children; + * // `children` is `[ + * // { + * // parentHash: 6136, + * // prefab: Prefab { + * // name: 'Guard', + * // hash: 51672, + * // position: { x: 0, y: 0, z: 0 }, + * // rotation: { x: 0, y: 0, z: 0, w: 1 } + * // scale: 1, + * // components: { Unknown: [] }, + * // entities: {}, + * // children: [] + * // } + * // } + * // ]` + */ + children: PrefabChild[]; + + /** + * Creates a new `Prefab` from a list of known _A Township Tale_ prefab names. You may optionally + * provide additional properties in the second argument. + * + * @see [Class: `Prefab`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/Prefab.md) + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const simple = new Prefab('Grass_Clump'); + * + * const advanced = new Prefab('Wooden_Stake', { + * position: { x: 133.7, y: 420, z: 69 }, + * rotation: { x: 0.3, y: 0.4, z: 0.1, w: 0.8 }, + * scale: 1.5, + * components: { + * NetworkRigidbody: new NetworkRigidbodyComponent({ + * version: 1, + * position: { x: 133.7, y: 420, z: 69 }, + * rotation: { x: 0.3, y: 0.4, z: 0.1, w: 0.8 }, + * isKinematic: false, + * isServerSleeping: false, + * velocity: { x: 0, y: 1, z: 0 }, + * angularVelocity: { x: 0, y: 1, z: 0 } + * }) + * }, + * entities: { + * Slot_Multi_11474: new Entity('Slot_Multi_11474') + * }, + * children: [ + * { + * parentHash: 11474, + * prefab: new Prefab('Grass_Clump', { + * entities: { + * Fire_30100: new Entity('Fire_30100', { + * components: { + * HeatSourceBase: new HeatSourceBaseComponent({ + * version: 2, + * isLit: true, + * progress: 0.8 + * }) + * } + * }) + * } + * }) + * } + * ] + * }); + */ + constructor( + prefabName: TPrefabName, + { position, rotation, scale, components, entities, children }: PrefabProps> = {} + ) { + this.hash = ATTPrefabs[prefabName].hash; + this.name = prefabName; + this.position = position ?? { x: 0, y: 0, z: 0 }; + this.rotation = rotation ?? { x: 0, y: 0, z: 0, w: 1 }; + this.scale = scale ?? 1; + this.components = { ...components, Unknown: components?.Unknown ?? [] } as PrefabComponents; + this.entities = { ...entities } as PrefabEntities>; + this.children = children ?? []; + } + + /** + * Attaches a `Prefab` to this prefab as a child. It can optionally be attached onto one of this + * prefab's embedded entities, which is required for most child prefabs under normal circumstances. + * If you do not specify a `parentKey`, you may pass `null` to create a "floating" child. It will + * be part of this prefab's hierarchy but will most likely behave unexpectedly in the game. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const parent = new Prefab('Handle_Short'); + * const child = new Prefab('Guard'); + * + * parent.addChildPrefab('Slot_Large_SwordType_Craft_54356', child); + */ + addChildPrefab( + parentKey: Exclude>, 'Unknown'> | null, + childPrefab: Prefab + ): Prefab> { + if (typeof parentKey === 'undefined' || typeof childPrefab === 'undefined') { + throw new Error( + 'You must pass a parent prefab entity hash (or null) and a child prefab to add as a child to this prefab.' + ); } - }, - 'Apple_Full_Unripe': { - 'hash': 6740, - 'name': 'Apple Full Unripe', - 'embedded': { - 'Apple_Core_Spawner_37092': { - 'hash': 37092, - 'name': 'Apple Core Spawner', - 'savables': {} - }, - 'Apple_Full_Unripe_55618': { - 'hash': 55618, - 'name': 'Apple Full Unripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_430': { - 'hash': 430, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } + + let entityHash: number; + + if (parentKey === null) { + entityHash = 0; + } else { + const entities = ATTPrefabs[this.name].embedded as Readonly< + Record }> + >; + + const entity = entities[parentKey as string]; + + if (typeof entity === 'undefined') { + throw new Error(`"${String(parentKey)}" is not a valid entity on "${this.name}".`); } + + entityHash = entity.hash; } - }, - 'Apple_Growth': { - 'hash': 19192, - 'name': 'Apple Growth', - 'embedded': { - 'Apple_Growth_33458': { - 'hash': 33458, - 'name': 'Apple Growth', - 'savables': { - 'GrowerComponent': { - 'hash': 3402094521, - 'name': 'GrowerComponent' - } - } + + this.children = [ + ...this.children, + { + parentHash: entityHash, + prefab: childPrefab } + ]; + + return this; + } + + /** + * Adds a `Component` to the prefab. Will override any existing component with that name. + * + * @example + * import { NetworkRigidbodyComponent, Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Handle_Short'); + * const component = new NetworkRigidbodyComponent({ version: 1 }); + * + * prefab.addComponent(component); + */ + addComponent(component: Component): Prefab> { + this.components = { + ...this.components, + [component.name]: component + }; + + return this; + } + + /** + * Adds an `Entity` to the prefab. Will override any existing entity with that key. + * + * @example + * import { Entity, Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Handle_Short'); + * const entity = new Entity<'Handle_Short'>('Slot_Multi_6136'); + * + * prefab.addEntity(entity); + */ + addEntity(entity: Entity): Prefab> { + this.entities = { + ...this.entities, + [`${entity.name}_${entity.hash}`]: entity + }; + + return this; + } + + /** + * Adds a `Prefab` gift to this prefab's `SentGift` component. You may call this method more than + * once to add additional gifts. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const box = new Prefab('Gift_Mail_Box'); + * const gift = new Prefab('Dynamite'); + * + * box.addGift(gift); + */ + addGift(giftPrefab: Prefab): Prefab> { + if (typeof giftPrefab === 'undefined') { + throw new Error('You must pass a gift prefab to add to this prefab as a gift.'); } - }, - 'Apple_Half_Burnt': { - 'hash': 65526, - 'name': 'Apple Half Burnt', - 'embedded': { - 'Apple_Half_Burnt_55062': { - 'hash': 55062, - 'name': 'Apple Half Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_64844': { - 'hash': 64844, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } + + if (isSavableComponent('SentGift', this.name)) { + const version = this.components.SentGift?.version ?? FALLBACK_SENT_GIFT_VERSION; + const saveString = giftPrefab.toSaveString(); + const [dataString, versionsString] = saveString.split('|'); + + if (typeof dataString === 'undefined' || dataString.length === 0) { + throw new Error(`Gift prefab data is corrupted.`); } - } - }, - 'Apple_Half_Cooked': { - 'hash': 2000, - 'name': 'Apple Half Cooked', - 'embedded': { - 'Apple_Half_Cooked_54784': { - 'hash': 54784, - 'name': 'Apple Half Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_61738': { - 'hash': 61738, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } + + const unsignedIntegers = dataString.split(',').map(Number); + const hash = unsignedIntegers.shift(); + const bytes = unsignedIntegers.shift(); + const chunkVersioning = versionsString?.split(',').map(Number) ?? []; + + if (typeof hash === 'undefined' || typeof bytes === 'undefined' || bytes === 0) { + throw new Error(`Gift prefab data is corrupted.`); } + + this.components.SentGift = new SentGiftComponent({ + ...this.components.SentGift, + version, + gifts: [ + ...(this.components.SentGift?.gifts ?? []), + { + data: unsignedIntegers, + messageSizeInBytes: bytes, + hash, + chunkVersioning + } + ] + }); } - }, - 'Apple_Half_Ripe': { - 'hash': 7278, - 'name': 'Apple Half Ripe', - 'embedded': { - 'Apple_Half_Ripe_54506': { - 'hash': 54506, - 'name': 'Apple Half Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } + + return this; + } + + /** + * Returns a deep clone of the prefab. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const original = new Prefab('Guard').setMaterial('Mythril'); + * const clone = original.clone(); + * + * clone.setMaterial('Gold'); + * + * const originalMaterial = original.getMaterial(); + * // `originalMaterial` is still `31174` (Mythril) + * + * const cloneMaterial = clone.getMaterial(); + * // `cloneMaterial` is `56394` (Gold) + */ + clone(options: ToSaveStringOptions = {}): Prefab> { + return Prefab.fromSaveString>(this.toSaveString(options)); + } + + /** + * Creates a `Prefab` from reading the prefab's binary data stored in a `SaveString`. + * + * @example + * import { BinaryReader, ComponentHash, Prefab, type BinaryString } from 'att-string-transcoder'; + * + * const binaryString = `0000000000000000101001001111011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111100000000000000000000000001111111000000000000000000000000101011010110001000000111011011000000000000000000000000001000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000`; + * + * const reader = new BinaryReader(binaryString as BinaryString); + * + * const componentVersions = new Map([ + * [ComponentHash.NetworkRigidbody, 1], + * [ComponentHash.PhysicalMaterialPart, 1], + * [ComponentHash.Pickup, 1] + * // etc... + * ]); + * + * const prefab = Prefab.fromBinary<'Handle_Short'>(reader, componentVersions); + */ + static fromBinary( + reader: BinaryReader, + componentVersions?: Map + ): Prefab> { + const versions = componentVersions ?? constants.latestSupportedComponentVersions; + + /** + * @property {number} hash + */ + const hash = reader.readUnsignedInteger(); + + const name = constants.attPrefabNames[hash as ATTPrefabHash]; + + if (typeof name === 'undefined') throw new Error(`Cannot find ATT Prefab with hash ${hash}.`); + + // const prefab = ATTPrefabs[name]; + + return new Prefab>(name as TPrefabName, { + /** + * @property {Position} position + */ + position: { + x: reader.readFloat(), + y: reader.readFloat(), + z: reader.readFloat() }, - 'Cooking_54586': { - 'hash': 54586, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Apple_Half_Unripe': { - 'hash': 62012, - 'name': 'Apple Half Unripe', - 'embedded': { - 'Apple_Half_Unripe_54228': { - 'hash': 54228, - 'name': 'Apple Half Unripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } + + /** + * @property {Rotation} rotation + */ + rotation: { + x: reader.readFloat(), + y: reader.readFloat(), + z: reader.readFloat(), + w: reader.readFloat() }, - 'Cooking_60662': { - 'hash': 60662, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Apple_Tree': { - 'hash': 61222, - 'name': 'Apple Tree', - 'embedded': { - 'Apple_Tree_58592': { - 'hash': 58592, - 'name': 'Apple Tree', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Apple_Tree_Growth': { - 'hash': 14226, - 'name': 'Apple Tree Growth', - 'embedded': { - 'Apple_Tree_Growth_33458': { - 'hash': 33458, - 'name': 'Apple Tree Growth', - 'savables': { - 'GrowerComponent': { - 'hash': 3402094521, - 'name': 'GrowerComponent' - } - } - } - } - }, - 'Apple_Tree_Separated': { - 'hash': 8974, - 'name': 'Apple Tree Separated', - 'embedded': {} - }, - 'Apple_Tree_Stage_1': { - 'hash': 50926, - 'name': 'Apple Tree Stage 1', - 'embedded': { - 'Apple_Tree_Stage_1_63514': { - 'hash': 63514, - 'name': 'Apple Tree Stage 1', - 'savables': {} - } - } - }, - 'Apple_Tree_Stage_2': { - 'hash': 57538, - 'name': 'Apple Tree Stage 2', - 'embedded': { - 'Apple_Tree_Stage_2_11646': { - 'hash': 11646, - 'name': 'Apple Tree Stage 2', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Apple_Tree_Stage_3': { - 'hash': 62702, - 'name': 'Apple Tree Stage 3', - 'embedded': { - 'Apple_Tree_Stage_3_15774': { - 'hash': 15774, - 'name': 'Apple Tree Stage 3', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Area_of_Influence_Receiver_puzzle': { - 'hash': 13256, - 'name': 'Area of Influence Receiver puzzle', - 'embedded': { - 'Area_of_Influence_Receiver_puzzle_13236': { - 'hash': 13236, - 'name': 'Area of Influence Receiver puzzle', - 'savables': { - 'AreaOfInfluenceReceiver': { - 'hash': 309083880, - 'name': 'AreaOfInfluenceReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - } - } - } - } - }, - 'Area_of_Influence_Sender_puzzle': { - 'hash': 59482, - 'name': 'Area of Influence Sender puzzle', - 'embedded': { - 'Area_of_Influence_Sender_puzzle_59428': { - 'hash': 59428, - 'name': 'Area of Influence Sender puzzle', - 'savables': { - 'AreaOfInfluenceSender': { - 'hash': 176949352, - 'name': 'AreaOfInfluenceSender' - }, - 'LogicIntSender': { - 'hash': 2880587164, - 'name': 'LogicIntSender' - } - } - } + + /** + * @property {number} scale + */ + scale: reader.readFloat(), + + /** + * @property {PrefabComponents} components + */ + components: readComponents(reader, versions), + + /** + * @property {PrefabEntities} entities + */ + entities: readEntities(reader, name, versions), + + /** + * @property {PrefabChild[]} children + */ + children: readChildren(reader, versions) + }); + } + + /** + * Creates a `Prefab` from reading a `SaveString`. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const saveString = `43430,230,43430,3290698471,1125743666,1132721897,1050703933,3208373430,1039090831,1058493384,1043542835,2290978823,418,3290698471,1125743666,1132721897,1050703933,3208373430,1039090831,1058493384,3221225472,0,0,0,0,0,363610349,2147483736,3005828291,3221225472,2415919104,0,395228240,397619388,393508864,400941080,2546407302,4157020038,3890602430,1579755829,536870916,374086096,2147483844,1610612736,765,2684354569,338752663,2281701377,0,0,19021736,1744830465,67108864,75722752,0,303,67108864,1124073472,0,0,`; + * + * const prefab = Prefab.fromSaveString<'SpriggullDrumstick_Full_Ripe'>(saveString); + */ + static fromSaveString( + saveString: string, + options?: BinaryDataOptions + ): Prefab> { + if (!BinaryData.isSaveString(saveString)) { + throw new Error('SaveString is malformed.'); } - }, - 'Arrow': { - 'hash': 56460, - 'name': 'Arrow', - 'embedded': { - 'Arrow_43746': { - 'hash': 43746, - 'name': 'Arrow', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'Embeddable': { - 'hash': 22446553, - 'name': 'Embeddable' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Arrow_Tip_59378': { - 'hash': 59378, - 'name': 'Arrow Tip', - 'savables': {} - } + + const [dataString, componentVersionsString] = saveString.split('|'); + + if (typeof dataString === 'undefined' || dataString.length === 0) throw new Error('SaveString is malformed.'); + + const [hashString, dataLengthString, ...unsignedIntegerStrings] = dataString.split(',').filter(Boolean); + + if ( + typeof hashString === 'undefined' || + typeof dataLengthString === 'undefined' || + unsignedIntegerStrings.length === 0 + ) { + throw new Error('SaveString is malformed.'); } - }, - 'Arrow_Light_Beam_Effect': { - 'hash': 1798, - 'name': 'Arrow Light Beam Effect', - 'embedded': { - 'Arrow_Light_Beam_Effect_64504': { - 'hash': 64504, - 'name': 'Arrow Light Beam Effect', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } + + const unsignedIntegers = unsignedIntegerStrings.map(Number); + let componentVersions: Map | undefined = undefined; + + if (typeof componentVersionsString !== 'undefined') { + componentVersions = new Map(); + + const [pairCountString, ...versionPairStrings] = componentVersionsString.split(',').filter(Boolean); + + if (typeof pairCountString === 'undefined' || typeof versionPairStrings === 'undefined') { + throw new Error('SaveString is malformed.'); } - } - }, - 'Arrow_Shaft_Wooden': { - 'hash': 29772, - 'name': 'Arrow Shaft Wooden', - 'embedded': { - 'Arrow_Shaft_Wooden_31664': { - 'hash': 31664, - 'name': 'Arrow Shaft Wooden', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'Embeddable': { - 'hash': 22446553, - 'name': 'Embeddable' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_Deco_33560': { - 'hash': 33560, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Feather_38282': { - 'hash': 38282, - 'name': 'Slot Feather', - 'savables': {} - }, - 'Slot_Grass_13582': { - 'hash': 13582, - 'name': 'Slot Grass', - 'savables': {} - }, - 'Tip_59148': { - 'hash': 59148, - 'name': 'Tip', - 'savables': {} + + const expectedCount = Number(pairCountString); + const versionPairs = versionPairStrings.map(Number); + + if (expectedCount !== versionPairs.length / 2) { + throw new Error( + `SaveString contains invalid versioning. Expected ${expectedCount} versions but parsed ${ + versionPairs.length / 2 + }.` + ); } - } - }, - 'Arrow_Shaft_Wooden_Training': { - 'hash': 36772, - 'name': 'Arrow Shaft Wooden Training', - 'embedded': { - 'Arrow_Shaft_Wooden_Training_36760': { - 'hash': 36760, - 'name': 'Arrow Shaft Wooden Training', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Tip_59796': { - 'hash': 59796, - 'name': 'Tip', - 'savables': {} - } - } - }, - 'Arrow_Training': { - 'hash': 36190, - 'name': 'Arrow Training', - 'embedded': { - 'Arrow_Training_43746': { - 'hash': 43746, - 'name': 'Arrow Training', - 'savables': { - 'Embeddable': { - 'hash': 22446553, - 'name': 'Embeddable' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Tip_59502': { - 'hash': 59502, - 'name': 'Tip', - 'savables': {} - } - } - }, - 'Arrow_Training_Dud': { - 'hash': 8858, - 'name': 'Arrow Training Dud', - 'embedded': { - 'Arrow_Training_Dud_43746': { - 'hash': 43746, - 'name': 'Arrow Training Dud', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Ash_Gotera_Seed_Spray': { - 'hash': 61862, - 'name': 'Ash Gotera Seed Spray', - 'embedded': { - 'Ash_Gotera_Seed_Spray_44772': { - 'hash': 44772, - 'name': 'Ash Gotera Seed Spray', - 'savables': {} - } - } - }, - 'Ash_Gotera_Smoke': { - 'hash': 48860, - 'name': 'Ash Gotera Smoke', - 'embedded': { - 'Ash_Gotera_Smoke_50236': { - 'hash': 50236, - 'name': 'Ash Gotera Smoke', - 'savables': {} - } - } - }, - 'Ash_Pile': { - 'hash': 53398, - 'name': 'Ash Pile', - 'embedded': { - 'Ash_Pile_41772': { - 'hash': 41772, - 'name': 'Ash Pile', - 'savables': { - 'BasicDecay': { - 'hash': 3801256786, - 'name': 'BasicDecay' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Ash_Tree_Growth': { - 'hash': 48208, - 'name': 'Ash Tree Growth', - 'embedded': { - 'Ash_Tree_Growth_33458': { - 'hash': 33458, - 'name': 'Ash Tree Growth', - 'savables': { - 'GrowerComponent': { - 'hash': 3402094521, - 'name': 'GrowerComponent' - } - } - } - } - }, - 'Ash_Tree_Seed': { - 'hash': 35274, - 'name': 'Ash Tree Seed', - 'embedded': { - 'Ash_Tree_Seed_35258': { - 'hash': 35258, - 'name': 'Ash Tree Seed', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'RaycastCrafter': { - 'hash': 2815374842, - 'name': 'RaycastCrafter' - } - } - } - } - }, - 'Ash_Tree_Stage_1': { - 'hash': 17892, - 'name': 'Ash Tree Stage 1', - 'embedded': { - 'Ash_Tree_Stage_1_63514': { - 'hash': 63514, - 'name': 'Ash Tree Stage 1', - 'savables': {} - } - } - }, - 'Assembly_Deck': { - 'hash': 17520, - 'name': 'Assembly Deck', - 'embedded': { - 'Assembly_Deck_17438': { - 'hash': 17438, - 'name': 'Assembly Deck', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - }, - 'GenericAssemblyStation': { - 'hash': 2971871217, - 'name': 'GenericAssemblyStation' - } - } - }, - 'Dock_5748': { - 'hash': 5748, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Pickup_59306': { - 'hash': 59306, - 'name': 'Pickup', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Auto_Cam_Player': { - 'hash': 61644, - 'name': 'Auto_Cam_Player', - 'embedded': {} - }, - 'Axe_Head': { - 'hash': 34412, - 'name': 'Axe Head', - 'embedded': { - 'Axe_Head_56484': { - 'hash': 56484, - 'name': 'Axe Head', - 'savables': { - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_59758': { - 'hash': 59758, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_Pole_7796': { - 'hash': 7796, - 'name': 'Insert Pole', - 'savables': {} - }, - 'metal_axeHead_curve_geo_17472': { - 'hash': 17472, - 'name': 'metal_axeHead_curve_geo', - 'savables': {} - } - } - }, - 'Axe_Head_Curve': { - 'hash': 50322, - 'name': 'Axe Head Curve', - 'embedded': { - 'Axe_Head_Curve_56484': { - 'hash': 56484, - 'name': 'Axe Head Curve', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_60150': { - 'hash': 60150, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_AxeType_7796': { - 'hash': 7796, - 'name': 'Insert AxeType', - 'savables': {} - }, - 'metal_axeHead_Curve_geo_LOD0_46530': { - 'hash': 46530, - 'name': 'metal_axeHead_Curve_geo_LOD0', - 'savables': {} - } - } - }, - 'Axe_Head_Felling': { - 'hash': 9918, - 'name': 'Axe Head Felling', - 'embedded': { - 'Axe_Head_Felling_58934': { - 'hash': 58934, - 'name': 'Axe Head Felling', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_60560': { - 'hash': 60560, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_AxeType_7796': { - 'hash': 7796, - 'name': 'Insert AxeType', - 'savables': {} - }, - 'metal_axeHead_felling_geo_LOD0_40512': { - 'hash': 40512, - 'name': 'metal_axeHead_felling_geo_LOD0', - 'savables': {} - } - } - }, - 'Axe_Head_GreatCurve': { - 'hash': 10056, - 'name': 'Axe Head GreatCurve', - 'embedded': { - 'Axe_Head_GreatCurve_39022': { - 'hash': 39022, - 'name': 'Axe Head GreatCurve', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_61024': { - 'hash': 61024, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_HammerType_End_Cap_7796': { - 'hash': 7796, - 'name': 'Insert HammerType End Cap', - 'savables': {} - }, - 'metal_axeHead_greatCurve_geo_LOD0_47596': { - 'hash': 47596, - 'name': 'metal_axeHead_greatCurve_geo_LOD0', - 'savables': {} - } - } - }, - 'Axe_Head_LShape': { - 'hash': 17400, - 'name': 'Axe Head LShape', - 'embedded': { - 'Axe_Head_LShape_25390': { - 'hash': 25390, - 'name': 'Axe Head LShape', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_61514': { - 'hash': 61514, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_AxeType_7796': { - 'hash': 7796, - 'name': 'Insert AxeType', - 'savables': {} - }, - 'metal_axeHead_Lshape_LOD0_22814': { - 'hash': 22814, - 'name': 'metal_axeHead_Lshape_LOD0', - 'savables': {} - } - } - }, - 'Axe_Training': { - 'hash': 57010, - 'name': 'Axe_Training', - 'embedded': {} - }, - 'Babu': { - 'hash': 9140, - 'name': 'Babu', - 'embedded': { - 'Babu_55348': { - 'hash': 55348, - 'name': 'Babu', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Babu_AI_55590': { - 'hash': 55590, - 'name': 'Babu AI', - 'savables': {} - }, - 'Body_41706': { - 'hash': 41706, - 'name': 'Body', - 'savables': {} - }, - 'Dig_Spawn_65330': { - 'hash': 65330, - 'name': 'Dig Spawn', - 'savables': {} - }, - 'Drop_Spawn_3448': { - 'hash': 3448, - 'name': 'Drop Spawn', - 'savables': {} - }, - 'Head_Collision_43064': { - 'hash': 43064, - 'name': 'Head Collision', - 'savables': {} - }, - 'Interactor_49402': { - 'hash': 49402, - 'name': 'Interactor', - 'savables': {} - }, - 'babu_tusk_L_(1)_16632': { - 'hash': 16632, - 'name': 'babu_tusk_L (1)', - 'savables': {} - }, - 'babu_tusk_R_(1)_17014': { - 'hash': 17014, - 'name': 'babu_tusk_R (1)', - 'savables': {} - } - } - }, - 'Babu_Leg_Bone': { - 'hash': 32526, - 'name': 'Babu Leg Bone', - 'embedded': { - 'Babu_Leg_Bone_26390': { - 'hash': 26390, - 'name': 'Babu Leg Bone', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Babu_Leg_Full_Burnt': { - 'hash': 64844, - 'name': 'Babu Leg Full Burnt', - 'embedded': { - 'Babu_Leg_Full_Burnt_25250': { - 'hash': 25250, - 'name': 'Babu Leg Full Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Bone_Spawner_38786': { - 'hash': 38786, - 'name': 'Bone Spawner', - 'savables': {} - }, - 'Cooking_24500': { - 'hash': 24500, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Babu_Leg_Full_Cooked': { - 'hash': 42916, - 'name': 'Babu Leg Full Cooked', - 'embedded': { - 'Babu_Leg_Full_Cooked_25250': { - 'hash': 25250, - 'name': 'Babu Leg Full Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Bone_Spawner_38786': { - 'hash': 38786, - 'name': 'Bone Spawner', - 'savables': {} - }, - 'Cooking_24500': { - 'hash': 24500, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Babu_Leg_Full_Ripe': { - 'hash': 2562, - 'name': 'Babu Leg Full Ripe', - 'embedded': { - 'Babu_Leg_Full_Ripe_25250': { - 'hash': 25250, - 'name': 'Babu Leg Full Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Bone_Spawner_38786': { - 'hash': 38786, - 'name': 'Bone Spawner', - 'savables': {} - }, - 'Cooking_24500': { - 'hash': 24500, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Babu_Leg_Half_Burnt': { - 'hash': 50328, - 'name': 'Babu Leg Half Burnt', - 'embedded': { - 'Babu_Leg_Half_Burnt_16238': { - 'hash': 16238, - 'name': 'Babu Leg Half Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_16182': { - 'hash': 16182, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Babu_Leg_Half_Cooked': { - 'hash': 50326, - 'name': 'Babu Leg Half Cooked', - 'embedded': { - 'Babu_Leg_Half_Cooked_16238': { - 'hash': 16238, - 'name': 'Babu Leg Half Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_16182': { - 'hash': 16182, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Babu_Leg_Half_Ripe': { - 'hash': 50252, - 'name': 'Babu Leg Half Ripe', - 'embedded': { - 'Babu_Leg_Half_Ripe_16238': { - 'hash': 16238, - 'name': 'Babu Leg Half Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_16182': { - 'hash': 16182, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Bag': { - 'hash': 35324, - 'name': 'Bag', - 'embedded': { - 'Bag_43012': { - 'hash': 43012, - 'name': 'Bag', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Bag_Body_42972': { - 'hash': 42972, - 'name': 'Bag Body', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Dock_BL_42978': { - 'hash': 42978, - 'name': 'Dock BL', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_BM_42976': { - 'hash': 42976, - 'name': 'Dock BM', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_BR_42974': { - 'hash': 42974, - 'name': 'Dock BR', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_ML_42984': { - 'hash': 42984, - 'name': 'Dock ML', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_MM_42982': { - 'hash': 42982, - 'name': 'Dock MM', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_MR_42980': { - 'hash': 42980, - 'name': 'Dock MR', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_TL_42990': { - 'hash': 42990, - 'name': 'Dock TL', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_TM_42988': { - 'hash': 42988, - 'name': 'Dock TM', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_TR_42986': { - 'hash': 42986, - 'name': 'Dock TR', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Roll_Dock_47074': { - 'hash': 47074, - 'name': 'Roll Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Slot_Bag_Attach_30776': { - 'hash': 30776, - 'name': 'Slot Bag Attach', - 'savables': {} - }, - 'Slot_Bag_Attach_55164': { - 'hash': 55164, - 'name': 'Slot Bag Attach', - 'savables': {} - }, - 'Slot_Bag_Pin_Collectible_Attach_31454': { - 'hash': 31454, - 'name': 'Slot Bag Pin Collectible Attach', - 'savables': {} - }, - 'Slot_Bag_Tool_Attachment_36292': { - 'hash': 36292, - 'name': 'Slot Bag Tool Attachment', - 'savables': {} - }, - 'Slot_Bag_Tool_Attachment_36386': { - 'hash': 36386, - 'name': 'Slot Bag Tool Attachment', - 'savables': {} - }, - 'standard_bag_Body_14336': { - 'hash': 14336, - 'name': 'standard_bag_Body', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_backPin_L_14300': { - 'hash': 14300, - 'name': 'standard_bag_backPin_L', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_backPin_R_14296': { - 'hash': 14296, - 'name': 'standard_bag_backPin_R', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_crossStrap_01_14332': { - 'hash': 14332, - 'name': 'standard_bag_crossStrap_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_flap_14328': { - 'hash': 14328, - 'name': 'standard_bag_flap', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_flap_clasp_01_14324': { - 'hash': 14324, - 'name': 'standard_bag_flap_clasp_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_handle_body_14308': { - 'hash': 14308, - 'name': 'standard_bag_handle_body', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_handle_wraps_14304': { - 'hash': 14304, - 'name': 'standard_bag_handle_wraps', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_sideBuckle_L_01_14316': { - 'hash': 14316, - 'name': 'standard_bag_sideBuckle_L_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_sideBuckle_L_02_14312': { - 'hash': 14312, - 'name': 'standard_bag_sideBuckle_L_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_sideBuckle_R_01_14376': { - 'hash': 14376, - 'name': 'standard_bag_sideBuckle_R_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_sideBuckle_R_02_14372': { - 'hash': 14372, - 'name': 'standard_bag_sideBuckle_R_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_strap_bot_L_01_14360': { - 'hash': 14360, - 'name': 'standard_bag_strap_bot_L_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_strap_bot_R_01_14356': { - 'hash': 14356, - 'name': 'standard_bag_strap_bot_R_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_strap_bot_buckle_L_02_14368': { - 'hash': 14368, - 'name': 'standard_bag_strap_bot_buckle_L_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_strap_bot_buckle_R_02_14364': { - 'hash': 14364, - 'name': 'standard_bag_strap_bot_buckle_R_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_strap_top_L_01_14344': { - 'hash': 14344, - 'name': 'standard_bag_strap_top_L_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_strap_top_R_01_14340': { - 'hash': 14340, - 'name': 'standard_bag_strap_top_R_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_strap_top_buckle_L_01_14352': { - 'hash': 14352, - 'name': 'standard_bag_strap_top_buckle_L_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_strap_top_buckle_R_01_14348': { - 'hash': 14348, - 'name': 'standard_bag_strap_top_buckle_R_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Barrel_Bag': { - 'hash': 19354, - 'name': 'Barrel Bag', - 'embedded': { - 'Bag_Body_42972': { - 'hash': 42972, - 'name': 'Bag Body', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Barrel_Bag_43012': { - 'hash': 43012, - 'name': 'Barrel Bag', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Dock_TL_42990': { - 'hash': 42990, - 'name': 'Dock TL', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Heat_47560': { - 'hash': 47560, - 'name': 'Heat', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Liquid_Part_65316': { - 'hash': 65316, - 'name': 'Liquid Part', - 'savables': { - 'LiquidContainer': { - 'hash': 4179293747, - 'name': 'LiquidContainer' - } - } - }, - 'Slot_Bag_Attach_30776': { - 'hash': 30776, - 'name': 'Slot Bag Attach', - 'savables': {} - }, - 'Slot_Bag_Attach_55164': { - 'hash': 55164, - 'name': 'Slot Bag Attach', - 'savables': {} - }, - 'barrel_bag_bottomCap_37710': { - 'hash': 37710, - 'name': 'barrel_bag_bottomCap', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'barrel_bag_handleRod_37706': { - 'hash': 37706, - 'name': 'barrel_bag_handleRod', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'barrel_bag_handleTop_37702': { - 'hash': 37702, - 'name': 'barrel_bag_handleTop', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'barrel_bag_ladleHook_37698': { - 'hash': 37698, - 'name': 'barrel_bag_ladleHook', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'barrel_bag_plank_01_37746': { - 'hash': 37746, - 'name': 'barrel_bag_plank_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'barrel_bag_plank_02_37742': { - 'hash': 37742, - 'name': 'barrel_bag_plank_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'barrel_bag_plank_03_37738': { - 'hash': 37738, - 'name': 'barrel_bag_plank_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'barrel_bag_plank_04_37734': { - 'hash': 37734, - 'name': 'barrel_bag_plank_04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'barrel_bag_plank_05_37730': { - 'hash': 37730, - 'name': 'barrel_bag_plank_05', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'barrel_bag_plank_06_37726': { - 'hash': 37726, - 'name': 'barrel_bag_plank_06', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'barrel_bag_plank_07_37714': { - 'hash': 37714, - 'name': 'barrel_bag_plank_07', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'barrel_bag_plank_08_37722': { - 'hash': 37722, - 'name': 'barrel_bag_plank_08', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'barrel_bag_ringBottom_37718': { - 'hash': 37718, - 'name': 'barrel_bag_ringBottom', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'barrel_bag_ringtop_37750': { - 'hash': 37750, - 'name': 'barrel_bag_ringtop', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Basic_Population_Folder': { - 'hash': 31116, - 'name': 'Basic_Population_Folder', - 'embedded': {} - }, - 'Birch_Tree_Growth': { - 'hash': 48218, - 'name': 'Birch Tree Growth', - 'embedded': { - 'Birch_Tree_Growth_33458': { - 'hash': 33458, - 'name': 'Birch Tree Growth', - 'savables': { - 'GrowerComponent': { - 'hash': 3402094521, - 'name': 'GrowerComponent' - } - } - } - } - }, - 'Birch_Tree_Seed': { - 'hash': 55274, - 'name': 'Birch Tree Seed', - 'embedded': { - 'Birch_Tree_Seed_35258': { - 'hash': 35258, - 'name': 'Birch Tree Seed', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'RaycastCrafter': { - 'hash': 2815374842, - 'name': 'RaycastCrafter' - } - } - } - } - }, - 'Birch_Tree_Stage_1': { - 'hash': 17704, - 'name': 'Birch Tree Stage 1', - 'embedded': { - 'Birch_Tree_Stage_1_63514': { - 'hash': 63514, - 'name': 'Birch Tree Stage 1', - 'savables': {} - } - } - }, - 'Blue_Mix_Recipe_Burnt_Stew': { - 'hash': 57666, - 'name': 'Blue_Mix_Recipe_Burnt_Stew', - 'embedded': {} - }, - 'Blue_Mix_Recipe_Cooked_Stew': { - 'hash': 57642, - 'name': 'Blue_Mix_Recipe_Cooked_Stew', - 'embedded': {} - }, - 'Blue_Mix_Recipe_Raw_Stew': { - 'hash': 57614, - 'name': 'Blue_Mix_Recipe_Raw_Stew', - 'embedded': {} - }, - 'Blueberry_Flower_Bloom': { - 'hash': 40922, - 'name': 'Blueberry Flower Bloom', - 'embedded': { - 'Blueberry_Flower_Bloom_25566': { - 'hash': 25566, - 'name': 'Blueberry Flower Bloom', - 'savables': {} - } - } - }, - 'Blueberry_Flower_Bud': { - 'hash': 40920, - 'name': 'Blueberry Flower Bud', - 'embedded': { - 'Blueberry_Flower_Bud_25268': { - 'hash': 25268, - 'name': 'Blueberry Flower Bud', - 'savables': {} - } - } - }, - 'Blueberry_Full_Burnt': { - 'hash': 49890, - 'name': 'Blueberry Full Burnt', - 'embedded': { - 'Blueberry_Full_Burnt_56526': { - 'hash': 56526, - 'name': 'Blueberry Full Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_46248': { - 'hash': 46248, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Blueberry_Full_Cooked': { - 'hash': 47468, - 'name': 'Blueberry Full Cooked', - 'embedded': { - 'Blueberry_Full_Cooked_55520': { - 'hash': 55520, - 'name': 'Blueberry Full Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_45334': { - 'hash': 45334, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Blueberry_Full_Ripe': { - 'hash': 45012, - 'name': 'Blueberry Full Ripe', - 'embedded': { - 'Blueberry_Full_Ripe_54516': { - 'hash': 54516, - 'name': 'Blueberry Full Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_44398': { - 'hash': 44398, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Blueberry_Full_Unripe': { - 'hash': 42556, - 'name': 'Blueberry Full Unripe', - 'embedded': { - 'Blueberry_Full_Unripe_53512': { - 'hash': 53512, - 'name': 'Blueberry Full Unripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'RaycastCrafter': { - 'hash': 2815374842, - 'name': 'RaycastCrafter' - } - } - }, - 'Cooking_43444': { - 'hash': 43444, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Blueberry_Growth': { - 'hash': 19292, - 'name': 'Blueberry Growth', - 'embedded': { - 'Blueberry_Growth_33458': { - 'hash': 33458, - 'name': 'Blueberry Growth', - 'savables': { - 'GrowerComponent': { - 'hash': 3402094521, - 'name': 'GrowerComponent' - } - } - } - } - }, - 'Blueberry_Recipe_Burnt_Stew': { - 'hash': 36830, - 'name': 'Blueberry_Recipe_Burnt_Stew', - 'embedded': {} - }, - 'Blueberry_Recipe_Cooked_Stew': { - 'hash': 36086, - 'name': 'Blueberry_Recipe_Cooked_Stew', - 'embedded': {} - }, - 'Blueberry_Recipe_Raw_Stew': { - 'hash': 35338, - 'name': 'Blueberry_Recipe_Raw_Stew', - 'embedded': {} - }, - 'Blueberry_Tree': { - 'hash': 878, - 'name': 'Blueberry Tree', - 'embedded': { - 'Blueberry_Tree_24412': { - 'hash': 24412, - 'name': 'Blueberry Tree', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Blueberry_Tree_Growth': { - 'hash': 14700, - 'name': 'Blueberry Tree Growth', - 'embedded': { - 'Blueberry_Tree_Growth_33458': { - 'hash': 33458, - 'name': 'Blueberry Tree Growth', - 'savables': { - 'GrowerComponent': { - 'hash': 3402094521, - 'name': 'GrowerComponent' - } - } - } - } - }, - 'Blueberry_Tree_Separated': { - 'hash': 13784, - 'name': 'Blueberry_Tree_Separated', - 'embedded': {} - }, - 'Blueberry_Tree_Stage_1': { - 'hash': 26588, - 'name': 'Blueberry Tree Stage 1', - 'embedded': { - 'Blueberry_Tree_Stage_1_63514': { - 'hash': 63514, - 'name': 'Blueberry Tree Stage 1', - 'savables': {} - } - } - }, - 'Blueberry_Tree_Stage_2': { - 'hash': 1038, - 'name': 'Blueberry Tree Stage 2', - 'embedded': { - 'Blueberry_Tree_Stage_2_1020': { - 'hash': 1020, - 'name': 'Blueberry Tree Stage 2', - 'savables': {} - } - } - }, - 'Blueberry_Tree_Stage_3': { - 'hash': 1040, - 'name': 'Blueberry Tree Stage 3', - 'embedded': { - 'Blueberry_Tree_Stage_3_1022': { - 'hash': 1022, - 'name': 'Blueberry Tree Stage 3', - 'savables': {} - } - } - }, - 'Book': { - 'hash': 44174, - 'name': 'Book', - 'embedded': {} - }, - 'Bookshelf': { - 'hash': 64316, - 'name': 'Bookshelf', - 'embedded': { - 'Bookshelf_64030': { - 'hash': 64030, - 'name': 'Bookshelf', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - }, - 'Dock_2780': { - 'hash': 2780, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_64568': { - 'hash': 64568, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_64570': { - 'hash': 64570, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_64572': { - 'hash': 64572, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_64574': { - 'hash': 64574, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_64576': { - 'hash': 64576, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_64578': { - 'hash': 64578, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_64580': { - 'hash': 64580, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_64582': { - 'hash': 64582, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_64584': { - 'hash': 64584, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_64586': { - 'hash': 64586, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_64588': { - 'hash': 64588, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_64590': { - 'hash': 64590, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_64592': { - 'hash': 64592, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_64594': { - 'hash': 64594, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_64596': { - 'hash': 64596, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_64598': { - 'hash': 64598, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_64600': { - 'hash': 64600, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_64602': { - 'hash': 64602, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_64604': { - 'hash': 64604, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - } - } - }, - 'Bookshelf_NoBackboard': { - 'hash': 59952, - 'name': 'Bookshelf_NoBackboard', - 'embedded': { - 'Bookshelf_NoBackboard_64030': { - 'hash': 64030, - 'name': 'Bookshelf_NoBackboard', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - }, - 'Dock_2780': { - 'hash': 2780, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62044': { - 'hash': 62044, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62046': { - 'hash': 62046, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62048': { - 'hash': 62048, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62050': { - 'hash': 62050, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62052': { - 'hash': 62052, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62054': { - 'hash': 62054, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62056': { - 'hash': 62056, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62058': { - 'hash': 62058, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62060': { - 'hash': 62060, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62062': { - 'hash': 62062, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62064': { - 'hash': 62064, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62066': { - 'hash': 62066, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62068': { - 'hash': 62068, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62070': { - 'hash': 62070, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62072': { - 'hash': 62072, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62074': { - 'hash': 62074, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62076': { - 'hash': 62076, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62078': { - 'hash': 62078, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62080': { - 'hash': 62080, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - } - } - }, - 'Bought_Skill_Orb_Replacer': { - 'hash': 42842, - 'name': 'Bought_Skill_Orb_Replacer', - 'embedded': {} - }, - 'Boulder_Button_Spawner': { - 'hash': 21830, - 'name': 'Boulder_Button_Spawner', - 'embedded': {} - }, - 'Bouncing_Movement': { - 'hash': 34396, - 'name': 'Bouncing Movement', - 'embedded': { - 'Bouncing_Movement_60930': { - 'hash': 60930, - 'name': 'Bouncing Movement', - 'savables': { - 'WayPointPath': { - 'hash': 1063725326, - 'name': 'WayPointPath' - } - } - } - } - }, - 'Bow': { - 'hash': 56546, - 'name': 'Bow', - 'embedded': { - 'Arrow_Dock_40686': { - 'hash': 40686, - 'name': 'Arrow Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bow_40716': { - 'hash': 40716, - 'name': 'Bow', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'String_40688': { - 'hash': 40688, - 'name': 'String', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Bow_Blade': { - 'hash': 27416, - 'name': 'Bow Blade', - 'embedded': { - 'Bow_Blade_27418': { - 'hash': 27418, - 'name': 'Bow Blade', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_12228': { - 'hash': 12228, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_Bow_Blade_7796': { - 'hash': 7796, - 'name': 'Insert Bow Blade', - 'savables': {} - }, - 'metal_blade_bow_full_geo_LOD0_52240': { - 'hash': 52240, - 'name': 'metal_blade_bow_full_geo_LOD0', - 'savables': {} - } - } - }, - 'Bow_Training': { - 'hash': 42340, - 'name': 'Bow Training', - 'embedded': { - 'Arrow_Dock_40686': { - 'hash': 40686, - 'name': 'Arrow Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bow_Training_42328': { - 'hash': 42328, - 'name': 'Bow Training', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'String_40688': { - 'hash': 40688, - 'name': 'String', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Bramble_Obstacle': { - 'hash': 59178, - 'name': 'Bramble Obstacle', - 'embedded': { - 'Bramble_Obstacle_59546': { - 'hash': 59546, - 'name': 'Bramble Obstacle', - 'savables': {} - } - } - }, - 'Bramble_Obstacle_No_Bush': { - 'hash': 24434, - 'name': 'Bramble Obstacle No Bush', - 'embedded': { - 'Bramble_Obstacle_No_Bush_24428': { - 'hash': 24428, - 'name': 'Bramble Obstacle No Bush', - 'savables': {} - } - } - }, - 'Breakable_Box': { - 'hash': 19624, - 'name': 'Breakable Box', - 'embedded': { - 'Breakable_Box_17050': { - 'hash': 17050, - 'name': 'Breakable Box', - 'savables': { - 'MultiHandPickup': { - 'hash': 1556697998, - 'name': 'MultiHandPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Spawn_Content_40226': { - 'hash': 40226, - 'name': 'Spawn Content', - 'savables': {} - } - } - }, - 'Breakable_Pot': { - 'hash': 60800, - 'name': 'Breakable Pot', - 'embedded': { - 'Breakable_Pot_17050': { - 'hash': 17050, - 'name': 'Breakable Pot', - 'savables': { - 'MultiHandPickup': { - 'hash': 1556697998, - 'name': 'MultiHandPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Spawn_Content_40226': { - 'hash': 40226, - 'name': 'Spawn Content', - 'savables': {} - } - } - }, - 'Breakable_Root_2.5m_Bendy': { - 'hash': 35896, - 'name': 'Breakable Root 2.5m Bendy', - 'embedded': { - 'Breakable_Root_2.5m_Bendy_35892': { - 'hash': 35892, - 'name': 'Breakable Root 2.5m Bendy', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_2.5m_Curved': { - 'hash': 35738, - 'name': 'Breakable Root 2.5m Curved', - 'embedded': { - 'Breakable_Root_2.5m_Curved_35734': { - 'hash': 35734, - 'name': 'Breakable Root 2.5m Curved', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_2.5m_Straight': { - 'hash': 34564, - 'name': 'Breakable Root 2.5m Straight', - 'embedded': { - 'Breakable_Root_2.5m_Straight_34560': { - 'hash': 34560, - 'name': 'Breakable Root 2.5m Straight', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_2.5m_Wavy': { - 'hash': 36054, - 'name': 'Breakable Root 2.5m Wavy', - 'embedded': { - 'Breakable_Root_2.5m_Wavy_36050': { - 'hash': 36050, - 'name': 'Breakable Root 2.5m Wavy', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_Bendy': { - 'hash': 41482, - 'name': 'Breakable Root Bendy', - 'embedded': { - 'Breakable_Root_Bendy_42186': { - 'hash': 42186, - 'name': 'Breakable Root Bendy', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_Curved': { - 'hash': 64388, - 'name': 'Breakable Root Curved', - 'embedded': { - 'Breakable_Root_Curved_2746': { - 'hash': 2746, - 'name': 'Breakable Root Curved', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_Fence': { - 'hash': 62846, - 'name': 'Breakable Root Fence', - 'embedded': { - 'Breakable_Root_Fence_63540': { - 'hash': 63540, - 'name': 'Breakable Root Fence', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_Ground_01': { - 'hash': 34014, - 'name': 'Breakable Root Ground 01', - 'embedded': { - 'Breakable_Root_Ground_01_34010': { - 'hash': 34010, - 'name': 'Breakable Root Ground 01', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_Ground_02': { - 'hash': 23246, - 'name': 'Breakable Root Ground 02', - 'embedded': { - 'Breakable_Root_Ground_02_23250': { - 'hash': 23250, - 'name': 'Breakable Root Ground 02', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_Ground_03': { - 'hash': 21206, - 'name': 'Breakable Root Ground 03', - 'embedded': { - 'Breakable_Root_Ground_03_21202': { - 'hash': 21202, - 'name': 'Breakable Root Ground 03', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_Ground_04': { - 'hash': 18702, - 'name': 'Breakable Root Ground 04', - 'embedded': { - 'Breakable_Root_Ground_04_18706': { - 'hash': 18706, - 'name': 'Breakable Root Ground 04', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_Ground_05': { - 'hash': 16298, - 'name': 'Breakable Root Ground 05', - 'embedded': { - 'Breakable_Root_Ground_05_16294': { - 'hash': 16294, - 'name': 'Breakable Root Ground 05', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_Ground_06': { - 'hash': 13634, - 'name': 'Breakable Root Ground 06', - 'embedded': { - 'Breakable_Root_Ground_06_13638': { - 'hash': 13638, - 'name': 'Breakable Root Ground 06', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_HangingShort_Bendy': { - 'hash': 13856, - 'name': 'Breakable Root HangingShort Bendy', - 'embedded': { - 'Breakable_Root_HangingShort_Bendy_13860': { - 'hash': 13860, - 'name': 'Breakable Root HangingShort Bendy', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_HangingShort_Curved': { - 'hash': 12224, - 'name': 'Breakable Root HangingShort Curved', - 'embedded': { - 'Breakable_Root_HangingShort_Curved_12228': { - 'hash': 12228, - 'name': 'Breakable Root HangingShort Curved', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_HangingShort_Straight': { - 'hash': 9226, - 'name': 'Breakable Root HangingShort Straight', - 'embedded': { - 'Breakable_Root_HangingShort_Straight_9230': { - 'hash': 9230, - 'name': 'Breakable Root HangingShort Straight', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_HangingShort_Wavy': { - 'hash': 8534, - 'name': 'Breakable Root HangingShort Wavy', - 'embedded': { - 'Breakable_Root_HangingShort_Wavy_8538': { - 'hash': 8538, - 'name': 'Breakable Root HangingShort Wavy', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_Hanging_Bendy': { - 'hash': 63792, - 'name': 'Breakable Root Hanging Bendy', - 'embedded': { - 'Breakable_Root_Hanging_Bendy_63796': { - 'hash': 63796, - 'name': 'Breakable Root Hanging Bendy', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_Hanging_Column_01': { - 'hash': 37666, - 'name': 'Breakable Root Hanging Column 01', - 'embedded': { - 'Breakable_Root_Hanging_Column_01_37662': { - 'hash': 37662, - 'name': 'Breakable Root Hanging Column 01', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_Hanging_Column_02': { - 'hash': 24548, - 'name': 'Breakable Root Hanging Column 02', - 'embedded': { - 'Breakable_Root_Hanging_Column_02_24552': { - 'hash': 24552, - 'name': 'Breakable Root Hanging Column 02', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_Hanging_Straight': { - 'hash': 12714, - 'name': 'Breakable Root Hanging Straight', - 'embedded': { - 'Breakable_Root_Hanging_Straight_12710': { - 'hash': 12710, - 'name': 'Breakable Root Hanging Straight', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_Hanging_Thin_Bendy': { - 'hash': 6394, - 'name': 'Breakable Root Hanging Thin Bendy', - 'embedded': { - 'Breakable_Root_Hanging_Thin_Bendy_6398': { - 'hash': 6398, - 'name': 'Breakable Root Hanging Thin Bendy', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_Hanging_Thin_Straight': { - 'hash': 57168, - 'name': 'Breakable Root Hanging Thin Straight', - 'embedded': { - 'Breakable_Root_Hanging_Thin_Straight_57164': { - 'hash': 57164, - 'name': 'Breakable Root Hanging Thin Straight', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_Mound_Large': { - 'hash': 15602, - 'name': 'Breakable Root Mound Large', - 'embedded': { - 'Breakable_Root_Mound_Large_15598': { - 'hash': 15598, - 'name': 'Breakable Root Mound Large', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_Mound_Small': { - 'hash': 43010, - 'name': 'Breakable Root Mound Small', - 'embedded': { - 'Breakable_Root_Mound_Small_43014': { - 'hash': 43014, - 'name': 'Breakable Root Mound Small', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_Spawner': { - 'hash': 40946, - 'name': 'Breakable Root Spawner', - 'embedded': { - 'Breakable_Root_Spawner_6790': { - 'hash': 6790, - 'name': 'Breakable Root Spawner', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - } - } - }, - 'Breakable_Root_Straight': { - 'hash': 47012, - 'name': 'Breakable Root Straight', - 'embedded': { - 'Breakable_Root_Straight_47710': { - 'hash': 47710, - 'name': 'Breakable Root Straight', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Breakable_Root_Wavy': { - 'hash': 28332, - 'name': 'Breakable Root Wavy', - 'embedded': { - 'Breakable_Root_Wavy_28960': { - 'hash': 28960, - 'name': 'Breakable Root Wavy', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Broken_Box_Piece': { - 'hash': 260, - 'name': 'Broken Box Piece', - 'embedded': { - 'Broken_Box_Piece_1356': { - 'hash': 1356, - 'name': 'Broken Box Piece', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Broken_Breakable_Root_Piece_Ground': { - 'hash': 43996, - 'name': 'Broken Breakable Root Piece Ground', - 'embedded': { - 'Broken_Breakable_Root_Piece_Ground_45852': { - 'hash': 45852, - 'name': 'Broken Breakable Root Piece Ground', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Broken_Breakable_Root_Piece_Short': { - 'hash': 43998, - 'name': 'Broken Breakable Root Piece Short', - 'embedded': { - 'Broken_Breakable_Root_Piece_Short_45854': { - 'hash': 45854, - 'name': 'Broken Breakable Root Piece Short', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Broken_Breakable_Root_Piece_Thick': { - 'hash': 43994, - 'name': 'Broken Breakable Root Piece Thick', - 'embedded': { - 'Broken_Breakable_Root_Piece_Thick_45850': { - 'hash': 45850, - 'name': 'Broken Breakable Root Piece Thick', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Broken_Breakable_Root_Piece_Thin': { - 'hash': 44000, - 'name': 'Broken Breakable Root Piece Thin', - 'embedded': { - 'Broken_Breakable_Root_Piece_Thin_45856': { - 'hash': 45856, - 'name': 'Broken Breakable Root Piece Thin', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Broken_Burnable_Root_Piece_Ground': { - 'hash': 60406, - 'name': 'Broken Burnable Root Piece Ground', - 'embedded': { - 'Broken_Burnable_Root_Piece_Ground_21172': { - 'hash': 21172, - 'name': 'Broken Burnable Root Piece Ground', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Broken_Burnable_Root_Piece_Short': { - 'hash': 58460, - 'name': 'Broken Burnable Root Piece Short', - 'embedded': { - 'Broken_Burnable_Root_Piece_Short_21416': { - 'hash': 21416, - 'name': 'Broken Burnable Root Piece Short', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Broken_Burnable_Root_Piece_Thick': { - 'hash': 64302, - 'name': 'Broken Burnable Root Piece Thick', - 'embedded': { - 'Broken_Burnable_Root_Piece_Thick_20728': { - 'hash': 20728, - 'name': 'Broken Burnable Root Piece Thick', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Broken_Burnable_Root_Piece_Thin': { - 'hash': 61492, - 'name': 'Broken Burnable Root Piece Thin', - 'embedded': { - 'Broken_Burnable_Root_Piece_Thin_21074': { - 'hash': 21074, - 'name': 'Broken Burnable Root Piece Thin', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Broken_Crystal_Piece_01': { - 'hash': 60484, - 'name': 'Broken Crystal Piece 01', - 'embedded': { - 'Broken_Crystal_Piece_01_63000': { - 'hash': 63000, - 'name': 'Broken Crystal Piece 01', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Broken_Crystal_Piece_02': { - 'hash': 49198, - 'name': 'Broken Crystal Piece 02', - 'embedded': { - 'Broken_Crystal_Piece_02_46364': { - 'hash': 46364, - 'name': 'Broken Crystal Piece 02', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Broken_Crystal_Piece_03': { - 'hash': 37046, - 'name': 'Broken Crystal Piece 03', - 'embedded': { - 'Broken_Crystal_Piece_03_34076': { - 'hash': 34076, - 'name': 'Broken Crystal Piece 03', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Broken_Crystal_Piece_04': { - 'hash': 23220, - 'name': 'Broken Crystal Piece 04', - 'embedded': { - 'Broken_Crystal_Piece_04_20126': { - 'hash': 20126, - 'name': 'Broken Crystal Piece 04', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Broken_ExplosionBoulder_Part_01': { - 'hash': 45514, - 'name': 'Broken_ExplosionBoulder_Part_01', - 'embedded': { - 'Broken_ExplosionBoulder_Part_01_53690': { - 'hash': 53690, - 'name': 'Broken_ExplosionBoulder_Part_01', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Broken_ExplosionBoulder_Part_02': { - 'hash': 45518, - 'name': 'Broken_ExplosionBoulder_Part_02', - 'embedded': { - 'Broken_ExplosionBoulder_Part_02_3998': { - 'hash': 3998, - 'name': 'Broken_ExplosionBoulder_Part_02', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Broken_ExplosionBoulder_Part_03': { - 'hash': 45516, - 'name': 'Broken_ExplosionBoulder_Part_03', - 'embedded': { - 'Broken_ExplosionBoulder_Part_03_39886': { - 'hash': 39886, - 'name': 'Broken_ExplosionBoulder_Part_03', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Broken_ExplosionBoulder_Part_04': { - 'hash': 45512, - 'name': 'Broken_ExplosionBoulder_Part_04', - 'embedded': { - 'Broken_ExplosionBoulder_Part_04_29214': { - 'hash': 29214, - 'name': 'Broken_ExplosionBoulder_Part_04', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Broken_ExplosionBoulder_Part_05': { - 'hash': 45520, - 'name': 'Broken_ExplosionBoulder_Part_05', - 'embedded': { - 'Broken_ExplosionBoulder_Part_05_18196': { - 'hash': 18196, - 'name': 'Broken_ExplosionBoulder_Part_05', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Broken_Vine_Bunch_Dead_Piece': { - 'hash': 7264, - 'name': 'Broken Vine Bunch Dead Piece', - 'embedded': { - 'Broken_Vine_Bunch_Dead_Piece_11182': { - 'hash': 11182, - 'name': 'Broken Vine Bunch Dead Piece', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Bronze_Alloy_Ingot': { - 'hash': 26316, - 'name': 'Bronze_Alloy_Ingot', - 'embedded': {} - }, - 'Brown_Mushroom_Shield': { - 'hash': 17258, - 'name': 'Brown Mushroom Shield', - 'embedded': { - 'Brown_Mushroom_Shield_15482': { - 'hash': 15482, - 'name': 'Brown Mushroom Shield', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Bung': { - 'hash': 8050, - 'name': 'Bung', - 'embedded': {} - }, - 'Buried_Grass': { - 'hash': 47090, - 'name': 'Buried Grass', - 'embedded': { - 'Buried_Grass_64192': { - 'hash': 64192, - 'name': 'Buried Grass', - 'savables': { - 'SpawnBuried': { - 'hash': 654225716, - 'name': 'SpawnBuried' - } - } - }, - 'PullPickup_51602': { - 'hash': 51602, - 'name': 'PullPickup', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Buried_Pullup': { - 'hash': 61742, - 'name': 'Buried Pullup', - 'embedded': { - 'Buried_Pullup_64192': { - 'hash': 64192, - 'name': 'Buried Pullup', - 'savables': { - 'SpawnBuried': { - 'hash': 654225716, - 'name': 'SpawnBuried' - } - } - }, - 'PullPickup_51602': { - 'hash': 51602, - 'name': 'PullPickup', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Buried_Pullup_Bramble': { - 'hash': 37764, - 'name': 'Buried Pullup Bramble', - 'embedded': { - 'Buried_Pullup_Bramble_64192': { - 'hash': 64192, - 'name': 'Buried Pullup Bramble', - 'savables': { - 'SpawnBuried': { - 'hash': 654225716, - 'name': 'SpawnBuried' - } - } - }, - 'PullPickup_51602': { - 'hash': 51602, - 'name': 'PullPickup', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Buried_Pullup_Carrot': { - 'hash': 59026, - 'name': 'Buried Pullup Carrot', - 'embedded': { - 'Buried_Pullup_Carrot_59022': { - 'hash': 59022, - 'name': 'Buried Pullup Carrot', - 'savables': { - 'SpawnBuried': { - 'hash': 654225716, - 'name': 'SpawnBuried' - } - } - }, - 'PullPickup_51602': { - 'hash': 51602, - 'name': 'PullPickup', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Buried_Pullup_Potato_Sapling': { - 'hash': 10960, - 'name': 'Buried Pullup Potato Sapling', - 'embedded': { - 'Buried_Pullup_Potato_Sapling_64192': { - 'hash': 64192, - 'name': 'Buried Pullup Potato Sapling', - 'savables': { - 'SpawnBuried': { - 'hash': 654225716, - 'name': 'SpawnBuried' - } - } - }, - 'PullPickup_51602': { - 'hash': 51602, - 'name': 'PullPickup', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Buried_Pullup_Primitive': { - 'hash': 29550, - 'name': 'Buried Pullup Primitive', - 'embedded': { - 'Buried_Pullup_Primitive_64192': { - 'hash': 64192, - 'name': 'Buried Pullup Primitive', - 'savables': { - 'SpawnBuried': { - 'hash': 654225716, - 'name': 'SpawnBuried' - } - } - }, - 'PullPickup_51602': { - 'hash': 51602, - 'name': 'PullPickup', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Burnable_Root_Fence': { - 'hash': 45144, - 'name': 'Burnable Root Fence', - 'embedded': { - 'Burnable_Root_Fence_63540': { - 'hash': 63540, - 'name': 'Burnable Root Fence', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Burnable_Root_Ground_01': { - 'hash': 5702, - 'name': 'Burnable Root Ground 01', - 'embedded': { - 'Burnable_Root_Ground_01_10714': { - 'hash': 10714, - 'name': 'Burnable Root Ground 01', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Burnable_Root_Ground_02': { - 'hash': 34852, - 'name': 'Burnable Root Ground 02', - 'embedded': { - 'Burnable_Root_Ground_02_36732': { - 'hash': 36732, - 'name': 'Burnable Root Ground 02', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Burnable_Root_Ground_03': { - 'hash': 65260, - 'name': 'Burnable Root Ground 03', - 'embedded': { - 'Burnable_Root_Ground_03_2088': { - 'hash': 2088, - 'name': 'Burnable Root Ground 03', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Burnable_Root_Ground_04': { - 'hash': 36342, - 'name': 'Burnable Root Ground 04', - 'embedded': { - 'Burnable_Root_Ground_04_38842': { - 'hash': 38842, - 'name': 'Burnable Root Ground 04', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Burnable_Root_Ground_05': { - 'hash': 35154, - 'name': 'Burnable Root Ground 05', - 'embedded': { - 'Burnable_Root_Ground_05_37204': { - 'hash': 37204, - 'name': 'Burnable Root Ground 05', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Burnable_Root_Ground_06': { - 'hash': 37414, - 'name': 'Burnable Root Ground 06', - 'embedded': { - 'Burnable_Root_Ground_06_59980': { - 'hash': 59980, - 'name': 'Burnable Root Ground 06', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Burnable_Root_HangingShort_Bendy': { - 'hash': 58042, - 'name': 'Burnable Root HangingShort Bendy', - 'embedded': { - 'Burnable_Root_HangingShort_Bendy_60188': { - 'hash': 60188, - 'name': 'Burnable Root HangingShort Bendy', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Burnable_Root_HangingShort_Curved': { - 'hash': 29008, - 'name': 'Burnable Root HangingShort Curved', - 'embedded': { - 'Burnable_Root_HangingShort_Curved_31246': { - 'hash': 31246, - 'name': 'Burnable Root HangingShort Curved', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Burnable_Root_HangingShort_Straight': { - 'hash': 43200, - 'name': 'Burnable Root HangingShort Straight', - 'embedded': { - 'Burnable_Root_HangingShort_Straight_45316': { - 'hash': 45316, - 'name': 'Burnable Root HangingShort Straight', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Burnable_Root_HangingShort_Wavy': { - 'hash': 680, - 'name': 'Burnable Root HangingShort Wavy', - 'embedded': { - 'Burnable_Root_HangingShort_Wavy_3040': { - 'hash': 3040, - 'name': 'Burnable Root HangingShort Wavy', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Burnable_Root_Hanging_Bendy': { - 'hash': 44884, - 'name': 'Burnable Root Hanging Bendy', - 'embedded': { - 'Burnable_Root_Hanging_Bendy_46884': { - 'hash': 46884, - 'name': 'Burnable Root Hanging Bendy', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Burnable_Root_Hanging_Column_01': { - 'hash': 39694, - 'name': 'Burnable Root Hanging Column 01', - 'embedded': { - 'Burnable_Root_Hanging_Column_01_43274': { - 'hash': 43274, - 'name': 'Burnable Root Hanging Column 01', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Burnable_Root_Hanging_Column_02': { - 'hash': 14166, - 'name': 'Burnable Root Hanging Column 02', - 'embedded': { - 'Burnable_Root_Hanging_Column_02_16140': { - 'hash': 16140, - 'name': 'Burnable Root Hanging Column 02', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Burnable_Root_Hanging_Straight': { - 'hash': 39592, - 'name': 'Burnable Root Hanging Straight', - 'embedded': { - 'Burnable_Root_Hanging_Straight_41518': { - 'hash': 41518, - 'name': 'Burnable Root Hanging Straight', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Burnable_Root_Hanging_Thin_Bendy': { - 'hash': 64866, - 'name': 'Burnable Root Hanging Thin Bendy', - 'embedded': { - 'Burnable_Root_Hanging_Thin_Bendy_1566': { - 'hash': 1566, - 'name': 'Burnable Root Hanging Thin Bendy', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Burnable_Root_Hanging_Thin_Straight': { - 'hash': 36356, - 'name': 'Burnable Root Hanging Thin Straight', - 'embedded': { - 'Burnable_Root_Hanging_Thin_Straight_38530': { - 'hash': 38530, - 'name': 'Burnable Root Hanging Thin Straight', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Burnable_Root_Mound_Large': { - 'hash': 48874, - 'name': 'Burnable Root Mound Large', - 'embedded': { - 'Burnable_Root_Mound_Large_15598': { - 'hash': 15598, - 'name': 'Burnable Root Mound Large', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Burnable_Root_Mound_Small': { - 'hash': 17066, - 'name': 'Burnable Root Mound Small', - 'embedded': { - 'Burnable_Root_Mound_Small_17070': { - 'hash': 17070, - 'name': 'Burnable Root Mound Small', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Burnable_VineBunch': { - 'hash': 35828, - 'name': 'Burnable VineBunch', - 'embedded': { - 'Burnable_VineBunch_35834': { - 'hash': 35834, - 'name': 'Burnable VineBunch', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Burnable_VineBunch_Tutorial': { - 'hash': 38202, - 'name': 'Burnable VineBunch Tutorial', - 'embedded': { - 'Burnable_VineBunch_Tutorial_35834': { - 'hash': 35834, - 'name': 'Burnable VineBunch Tutorial', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Button_Spawner': { - 'hash': 42752, - 'name': 'Button_Spawner', - 'embedded': {} - }, - 'Campfire': { - 'hash': 63848, - 'name': 'Campfire', - 'embedded': { - 'Campfire_8496': { - 'hash': 8496, - 'name': 'Campfire', - 'savables': {} - }, - 'Fire_8488': { - 'hash': 8488, - 'name': 'Fire', - 'savables': { - 'Fire': { - 'hash': 3457519710, - 'name': 'Fire' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Campfire_Infinite': { - 'hash': 63034, - 'name': 'Campfire Infinite', - 'embedded': { - 'Campfire_Infinite_8496': { - 'hash': 8496, - 'name': 'Campfire Infinite', - 'savables': {} - } - } - }, - 'Campfire_Spawner': { - 'hash': 6584, - 'name': 'Campfire Spawner', - 'embedded': { - 'Campfire_Spawner_55752': { - 'hash': 55752, - 'name': 'Campfire Spawner', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - }, - 'Tinder_Spawner_64618': { - 'hash': 64618, - 'name': 'Tinder Spawner', - 'savables': {} - } - } - }, - 'Campfire_Weak': { - 'hash': 9276, - 'name': 'Campfire Weak', - 'embedded': { - 'Campfire_Weak_8496': { - 'hash': 8496, - 'name': 'Campfire Weak', - 'savables': {} - }, - 'Fire_8488': { - 'hash': 8488, - 'name': 'Fire', - 'savables': { - 'Fire': { - 'hash': 3457519710, - 'name': 'Fire' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Candy_Cane': { - 'hash': 27314, - 'name': 'Candy Cane', - 'embedded': { - 'Candy_Cane_24532': { - 'hash': 24532, - 'name': 'Candy Cane', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Candy_Cane_Knife_Spawner_3782': { - 'hash': 3782, - 'name': 'Candy Cane Knife Spawner', - 'savables': {} - } - } - }, - 'Candy_Cane_Knife': { - 'hash': 7676, - 'name': 'Candy Cane Knife', - 'embedded': { - 'Candy_Cane_Knife_24532': { - 'hash': 24532, - 'name': 'Candy Cane Knife', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'Embeddable': { - 'hash': 22446553, - 'name': 'Embeddable' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Carrot_Full_Burnt': { - 'hash': 62634, - 'name': 'Carrot Full Burnt', - 'embedded': { - 'Carrot_Full_Burnt_61108': { - 'hash': 61108, - 'name': 'Carrot Full Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_3266': { - 'hash': 3266, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Carrot_Full_Cooked': { - 'hash': 60742, - 'name': 'Carrot Full Cooked', - 'embedded': { - 'Carrot_Full_Cooked_59204': { - 'hash': 59204, - 'name': 'Carrot Full Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_1986': { - 'hash': 1986, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Carrot_Full_Ripe': { - 'hash': 58838, - 'name': 'Carrot Full Ripe', - 'embedded': { - 'Carrot_Full_Ripe_57300': { - 'hash': 57300, - 'name': 'Carrot Full Ripe', - 'savables': { - 'BuildupPickup': { - 'hash': 3373651539, - 'name': 'BuildupPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_706': { - 'hash': 706, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Leaves_Parent_29566': { - 'hash': 29566, - 'name': 'Leaves Parent', - 'savables': {} - } - } - }, - 'Carrot_Full_Unripe': { - 'hash': 56934, - 'name': 'Carrot Full Unripe', - 'embedded': { - 'Carrot_Full_Unripe_55396': { - 'hash': 55396, - 'name': 'Carrot Full Unripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_64962': { - 'hash': 64962, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Carrot_Half_Burnt': { - 'hash': 64146, - 'name': 'Carrot Half Burnt', - 'embedded': { - 'Carrot_Half_Burnt_63824': { - 'hash': 63824, - 'name': 'Carrot Half Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_38970': { - 'hash': 38970, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Carrot_Half_Cooked': { - 'hash': 63758, - 'name': 'Carrot Half Cooked', - 'embedded': { - 'Carrot_Half_Cooked_63420': { - 'hash': 63420, - 'name': 'Carrot Half Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_38624': { - 'hash': 38624, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Carrot_Half_Ripe': { - 'hash': 63354, - 'name': 'Carrot Half Ripe', - 'embedded': { - 'Carrot_Half_Ripe_63016': { - 'hash': 63016, - 'name': 'Carrot Half Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_38278': { - 'hash': 38278, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Carrot_Half_Unripe': { - 'hash': 62950, - 'name': 'Carrot Half Unripe', - 'embedded': { - 'Carrot_Half_Unripe_62612': { - 'hash': 62612, - 'name': 'Carrot Half Unripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Cooking_37932': { - 'hash': 37932, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Carrot_Leaves': { - 'hash': 10440, - 'name': 'Carrot Leaves', - 'embedded': { - 'Carrot_Leaves_14888': { - 'hash': 14888, - 'name': 'Carrot Leaves', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'PullPickup_32134': { - 'hash': 32134, - 'name': 'PullPickup', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Carsi_Ingot': { - 'hash': 60868, - 'name': 'Carsi Ingot', - 'embedded': { - 'Carsi_Ingot_32738': { - 'hash': 32738, - 'name': 'Carsi Ingot', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_12680': { - 'hash': 12680, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Carved_Pumpkin_Smelter': { - 'hash': 27322, - 'name': 'Carved Pumpkin Smelter', - 'embedded': { - 'Carved_Pumpkin_Smelter_24226': { - 'hash': 24226, - 'name': 'Carved Pumpkin Smelter', - 'savables': { - 'MultiHandPickup': { - 'hash': 1556697998, - 'name': 'MultiHandPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Fire_30100': { - 'hash': 30100, - 'name': 'Fire', - 'savables': { - 'Fire': { - 'hash': 3457519710, - 'name': 'Fire' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Cast_Iron_Lamp': { - 'hash': 24782, - 'name': 'Cast Iron Lamp', - 'embedded': { - 'Cast_Iron_Lamp_48448': { - 'hash': 48448, - 'name': 'Cast Iron Lamp', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - }, - 'Fire_30100': { - 'hash': 30100, - 'name': 'Fire', - 'savables': { - 'Fire': { - 'hash': 3457519710, - 'name': 'Fire' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Cauldron_Medium': { - 'hash': 45082, - 'name': 'Cauldron Medium', - 'embedded': { - 'Cauldron_Medium_42440': { - 'hash': 42440, - 'name': 'Cauldron Medium', - 'savables': { - 'CookingPot': { - 'hash': 2882590463, - 'name': 'CookingPot' - }, - 'LiquidContainer': { - 'hash': 4179293747, - 'name': 'LiquidContainer' - }, - 'MultiHandPickup': { - 'hash': 1556697998, - 'name': 'MultiHandPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'StewManager': { - 'hash': 1499506132, - 'name': 'StewManager' - } - } - }, - 'Handle_Top_20': { - 'hash': 20, - 'name': 'Handle Top', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'Heat_47560': { - 'hash': 47560, - 'name': 'Heat', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Liquid_19522': { - 'hash': 19522, - 'name': 'Liquid', - 'savables': {} - }, - 'Top_of_Liquid_not_rotating_59824': { - 'hash': 59824, - 'name': 'Top of Liquid not rotating', - 'savables': {} - }, - 'cookingPot_main_40': { - 'hash': 40, - 'name': 'cookingPot_main', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'cookingPot_medium_handle_L_grp_52': { - 'hash': 52, - 'name': 'cookingPot_medium_handle_L_grp', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'cookingPot_medium_handle_R_grp_44': { - 'hash': 44, - 'name': 'cookingPot_medium_handle_R_grp', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'cookingPot_plate_01_24': { - 'hash': 24, - 'name': 'cookingPot_plate_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'cookingPot_plate_02_28': { - 'hash': 28, - 'name': 'cookingPot_plate_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'cookingPot_plate_03_36': { - 'hash': 36, - 'name': 'cookingPot_plate_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'cookingPot_plate_04_32': { - 'hash': 32, - 'name': 'cookingPot_plate_04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'cookingPot_plate_mid_01_48': { - 'hash': 48, - 'name': 'cookingPot_plate_mid_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'cookingPot_plate_mid_02_56': { - 'hash': 56, - 'name': 'cookingPot_plate_mid_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Cave_Explosion_Boulder': { - 'hash': 31136, - 'name': 'Cave Explosion Boulder', - 'embedded': { - 'Cave_Explosion_Boulder_31140': { - 'hash': 31140, - 'name': 'Cave Explosion Boulder', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Cave_Explosion_Boulder_Clusters': { - 'hash': 17608, - 'name': 'Cave Explosion Boulder Clusters', - 'embedded': { - 'Cave_Explosion_Boulder_Clusters_17602': { - 'hash': 17602, - 'name': 'Cave Explosion Boulder Clusters', - 'savables': {} - } - } - }, - 'Cave_Grass': { - 'hash': 63846, - 'name': 'Cave Grass', - 'embedded': { - 'Cave_Grass_7194': { - 'hash': 7194, - 'name': 'Cave Grass', - 'savables': {} - }, - 'Fire_7186': { - 'hash': 7186, - 'name': 'Fire', - 'savables': { - 'FireDissolve': { - 'hash': 3457519710, - 'name': 'FireDissolve' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Cave_Layer_Chunk': { - 'hash': 61672, - 'name': 'Cave_Layer_Chunk', - 'embedded': {} - }, - 'Cave_Layer_Generation': { - 'hash': 61664, - 'name': 'Cave_Layer_Generation', - 'embedded': {} - }, - 'Cave_Surface_Teleporter_Ruins': { - 'hash': 43368, - 'name': 'Cave_Surface_Teleporter_Ruins', - 'embedded': {} - }, - 'Cave_Teleporter': { - 'hash': 27074, - 'name': 'Cave_Teleporter', - 'embedded': {} - }, - 'Cave_Teleporter_Station': { - 'hash': 22840, - 'name': 'Cave_Teleporter_Station', - 'embedded': {} - }, - 'Cave_Teleporter_Station_Ruins': { - 'hash': 29310, - 'name': 'Cave_Teleporter_Station_Ruins', - 'embedded': {} - }, - 'Cave_Wall_Support': { - 'hash': 63840, - 'name': 'Cave Wall Support', - 'embedded': { - 'Cave_Wall_Support_5636': { - 'hash': 5636, - 'name': 'Cave Wall Support', - 'savables': {} - }, - 'Torch_Dock_5626': { - 'hash': 5626, - 'name': 'Torch Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - } - } - }, - 'Cave_Water_Mound': { - 'hash': 57530, - 'name': 'Cave Water Mound', - 'embedded': { - 'Cave_Water_Mound_57514': { - 'hash': 57514, - 'name': 'Cave Water Mound', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - }, - 'LiquidContainer': { - 'hash': 4179293747, - 'name': 'LiquidContainer' - } - } - }, - 'Heat_Point_52154': { - 'hash': 52154, - 'name': 'Heat Point', - 'savables': {} - }, - 'Mushroom_Spawn_Area_22970': { - 'hash': 22970, - 'name': 'Mushroom Spawn Area', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'SpawnArea': { - 'hash': 2617495528, - 'name': 'SpawnArea' - } - } - }, - 'Wyrm_Spawn_Area_45512': { - 'hash': 45512, - 'name': 'Wyrm Spawn Area', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'SpawnArea': { - 'hash': 2617495528, - 'name': 'SpawnArea' - } - } - } - } - }, - 'Ceiling_Lantern': { - 'hash': 682, - 'name': 'Ceiling Lantern', - 'embedded': { - 'Ceiling_Lantern_684': { - 'hash': 684, - 'name': 'Ceiling Lantern', - 'savables': {} - }, - 'ceilingLight_Light_jnt_48980': { - 'hash': 48980, - 'name': 'ceilingLight_Light_jnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'ceilingLight_arm_jnt_48984': { - 'hash': 48984, - 'name': 'ceilingLight_arm_jnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'ceilingLight_root_jnt_48976': { - 'hash': 48976, - 'name': 'ceilingLight_root_jnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Ceiling_Lantern_Lit': { - 'hash': 32476, - 'name': 'Ceiling Lantern Lit', - 'embedded': { - 'Ceiling_Lantern_Lit_684': { - 'hash': 684, - 'name': 'Ceiling Lantern Lit', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Fire_55870': { - 'hash': 55870, - 'name': 'Fire', - 'savables': { - 'Fire': { - 'hash': 3457519710, - 'name': 'Fire' - } - } - }, - 'ceilingLight_Light_jnt_48980': { - 'hash': 48980, - 'name': 'ceilingLight_Light_jnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'ceilingLight_arm_jnt_48984': { - 'hash': 48984, - 'name': 'ceilingLight_arm_jnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'ceilingLight_root_jnt_48976': { - 'hash': 48976, - 'name': 'ceilingLight_root_jnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Ceiling_Light': { - 'hash': 8226, - 'name': 'Ceiling Light', - 'embedded': { - 'Ceiling_Light_8232': { - 'hash': 8232, - 'name': 'Ceiling Light', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Fire_54948': { - 'hash': 54948, - 'name': 'Fire', - 'savables': { - 'Fire': { - 'hash': 3457519710, - 'name': 'Fire' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'ceilingLight_Light_jnt_48980': { - 'hash': 48980, - 'name': 'ceilingLight_Light_jnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'ceilingLight_arm_jnt_48984': { - 'hash': 48984, - 'name': 'ceilingLight_arm_jnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'ceilingLight_root_jnt_48976': { - 'hash': 48976, - 'name': 'ceilingLight_root_jnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Character_Level_Stone': { - 'hash': 60762, - 'name': 'Character Level Stone', - 'embedded': { - 'Character_Level_Stone_57948': { - 'hash': 57948, - 'name': 'Character Level Stone', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - }, - 'Hand_Touch_46540': { - 'hash': 46540, - 'name': 'Hand Touch', - 'savables': {} - }, - 'Landmark_Finder_24472': { - 'hash': 24472, - 'name': 'Landmark Finder', - 'savables': { - 'Landmark': { - 'hash': 2590537994, - 'name': 'Landmark' - }, - 'LandmarkDiscoverZone': { - 'hash': 4095875831, - 'name': 'LandmarkDiscoverZone' - } - } - } - } - }, - 'Chess_Black_Bishop': { - 'hash': 16998, - 'name': 'Chess Black Bishop', - 'embedded': { - 'Chess_Black_Bishop_42198': { - 'hash': 42198, - 'name': 'Chess Black Bishop', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Chess_Black_Checker': { - 'hash': 16378, - 'name': 'Chess Black Checker', - 'embedded': { - 'Chess_Black_Checker_42196': { - 'hash': 42196, - 'name': 'Chess Black Checker', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Chess_Black_King': { - 'hash': 17200, - 'name': 'Chess Black King', - 'embedded': { - 'Chess_Black_King_42194': { - 'hash': 42194, - 'name': 'Chess Black King', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Chess_Black_Knight': { - 'hash': 17291, - 'name': 'Chess Black Knight', - 'embedded': { - 'Chess_Black_Knight_42200': { - 'hash': 42200, - 'name': 'Chess Black Knight', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Chess_Black_Pawn': { - 'hash': 17282, - 'name': 'Chess Black Pawn', - 'embedded': { - 'Chess_Black_Pawn_42202': { - 'hash': 42202, - 'name': 'Chess Black Pawn', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Chess_Black_Queen': { - 'hash': 16204, - 'name': 'Chess Black Queen', - 'embedded': { - 'Chess_Black_Queen_42192': { - 'hash': 42192, - 'name': 'Chess Black Queen', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Chess_Black_Rook': { - 'hash': 16142, - 'name': 'Chess Black Rook', - 'embedded': { - 'Chess_Black_Rook_42196': { - 'hash': 42196, - 'name': 'Chess Black Rook', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Chess_Board': { - 'hash': 16896, - 'name': 'Chess Board', - 'embedded': { - 'Chess_Board_24184': { - 'hash': 24184, - 'name': 'Chess Board', - 'savables': { - 'GhostSnapSlotCollection': { - 'hash': 1823429789, - 'name': 'GhostSnapSlotCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Chess_White_Bishop': { - 'hash': 17162, - 'name': 'Chess White Bishop', - 'embedded': { - 'Chess_White_Bishop_42198': { - 'hash': 42198, - 'name': 'Chess White Bishop', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Chess_White_Checker': { - 'hash': 16326, - 'name': 'Chess White Checker', - 'embedded': { - 'Chess_White_Checker_42196': { - 'hash': 42196, - 'name': 'Chess White Checker', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Chess_White_King': { - 'hash': 16276, - 'name': 'Chess White King', - 'embedded': { - 'Chess_White_King_42194': { - 'hash': 42194, - 'name': 'Chess White King', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Chess_White_Knight': { - 'hash': 17038, - 'name': 'Chess White Knight', - 'embedded': { - 'Chess_White_Knight_42200': { - 'hash': 42200, - 'name': 'Chess White Knight', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Chess_White_Pawn': { - 'hash': 17240, - 'name': 'Chess White Pawn', - 'embedded': { - 'Chess_White_Pawn_42202': { - 'hash': 42202, - 'name': 'Chess White Pawn', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Chess_White_Queen': { - 'hash': 16246, - 'name': 'Chess White Queen', - 'embedded': { - 'Chess_White_Queen_42192': { - 'hash': 42192, - 'name': 'Chess White Queen', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Chess_White_Rook': { - 'hash': 17084, - 'name': 'Chess White Rook', - 'embedded': { - 'Chess_White_Rook_42196': { - 'hash': 42196, - 'name': 'Chess White Rook', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Chisel': { - 'hash': 44380, - 'name': 'Chisel', - 'embedded': { - 'Chisel_48634': { - 'hash': 48634, - 'name': 'Chisel', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_64518': { - 'hash': 64518, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_SwordType_25524': { - 'hash': 25524, - 'name': 'Insert SwordType', - 'savables': {} - }, - 'metal_chisel_blade_full_geo_LOD0_48424': { - 'hash': 48424, - 'name': 'metal_chisel_blade_full_geo_LOD0', - 'savables': {} - } - } - }, - 'ChiselDeck': { - 'hash': 37398, - 'name': 'ChiselDeck', - 'embedded': { - 'ChiselDeck_50854': { - 'hash': 50854, - 'name': 'ChiselDeck', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - }, - 'ChisellingDeck': { - 'hash': 3236280681, - 'name': 'ChisellingDeck' - }, - 'Landmark': { - 'hash': 2590537994, - 'name': 'Landmark' - }, - 'LandmarkDiscoverZone': { - 'hash': 4095875831, - 'name': 'LandmarkDiscoverZone' - } - } - }, - 'ChiselDeck_SetBlock_grp_63040': { - 'hash': 63040, - 'name': 'ChiselDeck_SetBlock_grp', - 'savables': {} - }, - 'Docker_11728': { - 'hash': 11728, - 'name': 'Docker', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'leftHandle_grip_41084': { - 'hash': 41084, - 'name': 'leftHandle_grip', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'panelSwivel_slotFrame_29114': { - 'hash': 29114, - 'name': 'panelSwivel_slotFrame', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'rightHandle_grip_41080': { - 'hash': 41080, - 'name': 'rightHandle_grip', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'rotateHandleGrip_22918': { - 'hash': 22918, - 'name': 'rotateHandleGrip', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Chocolate_Easter_Egg': { - 'hash': 30164, - 'name': 'Chocolate Easter Egg', - 'embedded': { - 'Chocolate_Easter_Egg_30160': { - 'hash': 30160, - 'name': 'Chocolate Easter Egg', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Christmas_Gift_Box': { - 'hash': 17920, - 'name': 'Christmas Gift Box', - 'embedded': { - 'Christmas_Gift_Box_17050': { - 'hash': 17050, - 'name': 'Christmas Gift Box', - 'savables': { - 'MultiHandPickup': { - 'hash': 1556697998, - 'name': 'MultiHandPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Spawn_Content_40226': { - 'hash': 40226, - 'name': 'Spawn Content', - 'savables': {} - } - } - }, - 'Christmas_Gift_Box_Spawner': { - 'hash': 63174, - 'name': 'Christmas Gift Box Spawner', - 'embedded': { - 'Christmas_Gift_Box_Spawner_42278': { - 'hash': 42278, - 'name': 'Christmas Gift Box Spawner', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - } - } - }, - 'Christmas_Gift_Box_Special': { - 'hash': 18144, - 'name': 'Christmas Gift Box Special', - 'embedded': { - 'Christmas_Gift_Box_Special_17050': { - 'hash': 17050, - 'name': 'Christmas Gift Box Special', - 'savables': { - 'MultiHandPickup': { - 'hash': 1556697998, - 'name': 'MultiHandPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Spawn_Content_40226': { - 'hash': 40226, - 'name': 'Spawn Content', - 'savables': {} - } - } - }, - 'Christmas_Gift_Mail_Box_01': { - 'hash': 24764, - 'name': 'Christmas Gift Mail Box 01', - 'embedded': { - 'Christmas_Gift_Mail_Box_01_17050': { - 'hash': 17050, - 'name': 'Christmas Gift Mail Box 01', - 'savables': { - 'MultiHandPickup': { - 'hash': 1556697998, - 'name': 'MultiHandPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'SentGift': { - 'hash': 661497638, - 'name': 'SentGift' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Christmas_Gift_Mail_Box_02': { - 'hash': 16494, - 'name': 'Christmas Gift Mail Box 02', - 'embedded': { - 'Christmas_Gift_Mail_Box_02_17050': { - 'hash': 17050, - 'name': 'Christmas Gift Mail Box 02', - 'savables': { - 'MultiHandPickup': { - 'hash': 1556697998, - 'name': 'MultiHandPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'SentGift': { - 'hash': 661497638, - 'name': 'SentGift' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Christmas_Gift_Mail_Box_03': { - 'hash': 1080, - 'name': 'Christmas Gift Mail Box 03', - 'embedded': { - 'Christmas_Gift_Mail_Box_03_17050': { - 'hash': 17050, - 'name': 'Christmas Gift Mail Box 03', - 'savables': { - 'MultiHandPickup': { - 'hash': 1556697998, - 'name': 'MultiHandPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'SentGift': { - 'hash': 661497638, - 'name': 'SentGift' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Christmas_Tree': { - 'hash': 56318, - 'name': 'Christmas Tree', - 'embedded': { - 'Christmas_Tree_15640': { - 'hash': 15640, - 'name': 'Christmas Tree', - 'savables': {} - } - } - }, - 'Chunk_Directional_Surface': { - 'hash': 47534, - 'name': 'Chunk_Directional_Surface', - 'embedded': {} - }, - 'Chunk_Spherical_Surface': { - 'hash': 47614, - 'name': 'Chunk_Spherical_Surface', - 'embedded': {} - }, - 'Chute_Gcore_Dynamic': { - 'hash': 60246, - 'name': 'Chute Gcore Dynamic', - 'embedded': { - 'Chute_Gcore_Dynamic_53304': { - 'hash': 53304, - 'name': 'Chute Gcore Dynamic', - 'savables': {} - }, - 'Complete_63570': { - 'hash': 63570, - 'name': 'Complete', - 'savables': {} - }, - 'Diggable_4216': { - 'hash': 4216, - 'name': 'Diggable', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'SpawnArea': { - 'hash': 2617495528, - 'name': 'SpawnArea' - } - } - }, - 'Enemy_Spawn_12232': { - 'hash': 12232, - 'name': 'Enemy Spawn', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'SpawnArea': { - 'hash': 2617495528, - 'name': 'SpawnArea' - } - } - }, - 'Erupt_Area_19858': { - 'hash': 19858, - 'name': 'Erupt Area', - 'savables': {} - }, - 'Erupt_Area_2920': { - 'hash': 2920, - 'name': 'Erupt Area', - 'savables': {} - }, - 'Erupt_Area_3280': { - 'hash': 3280, - 'name': 'Erupt Area', - 'savables': {} - }, - 'Erupt_Area_3286': { - 'hash': 3286, - 'name': 'Erupt Area', - 'savables': {} - }, - 'Erupt_Area_3486': { - 'hash': 3486, - 'name': 'Erupt Area', - 'savables': {} - }, - 'Geyser_AI_2664': { - 'hash': 2664, - 'name': 'Geyser AI', - 'savables': {} - }, - 'Geyser_AI_2944': { - 'hash': 2944, - 'name': 'Geyser AI', - 'savables': {} - }, - 'Geyser_AI_2946': { - 'hash': 2946, - 'name': 'Geyser AI', - 'savables': {} - }, - 'Geyser_AI_29794': { - 'hash': 29794, - 'name': 'Geyser AI', - 'savables': {} - }, - 'Geyser_AI_3258': { - 'hash': 3258, - 'name': 'Geyser AI', - 'savables': {} - }, - 'Reset_63566': { - 'hash': 63566, - 'name': 'Reset', - 'savables': {} - }, - 'Targeted_Geyser_(1)_27232': { - 'hash': 27232, - 'name': 'Targeted Geyser (1)', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Targeted_Geyser_(2)_27100': { - 'hash': 27100, - 'name': 'Targeted Geyser (2)', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Targeted_Geyser_(3)_26416': { - 'hash': 26416, - 'name': 'Targeted Geyser (3)', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Targeted_Geyser_(4)_26284': { - 'hash': 26284, - 'name': 'Targeted Geyser (4)', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Targeted_Geyser_(5)_25600': { - 'hash': 25600, - 'name': 'Targeted Geyser (5)', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Top_Enemy_Spawn_12202': { - 'hash': 12202, - 'name': 'Top Enemy Spawn', - 'savables': { - 'DirectionalBoundsSurface': { - 'hash': 1962842866, - 'name': 'DirectionalBoundsSurface' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - } - } - }, - 'CircleSpawner': { - 'hash': 49642, - 'name': 'CircleSpawner', - 'embedded': { - 'CircleSpawner_52610': { - 'hash': 52610, - 'name': 'CircleSpawner', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'SpawnInCircle': { - 'hash': 1714180166, - 'name': 'SpawnInCircle' - } - } - } - } - }, - 'CircleSpawner(ExplosiveSpike)': { - 'hash': 31046, - 'name': 'CircleSpawner(ExplosiveSpike)', - 'embedded': { - 'CircleSpawner(ExplosiveSpike)_52620': { - 'hash': 52620, - 'name': 'CircleSpawner(ExplosiveSpike)', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'SpawnInCircle': { - 'hash': 1714180166, - 'name': 'SpawnInCircle' - } - } - } - } - }, - 'CircleSpawner_ExplosiveSpike': { - 'hash': 31046, - 'name': 'CircleSpawner_ExplosiveSpike', - 'embedded': {} - }, - 'Climbing_Tower_Progression_Visualizer': { - 'hash': 44244, - 'name': 'Climbing Tower Progression Visualizer', - 'embedded': { - 'Climbing_Tower_Progression_Visualizer_43852': { - 'hash': 43852, - 'name': 'Climbing Tower Progression Visualizer', - 'savables': { - 'ClimbingTowerProgressionVisualizer': { - 'hash': 623957243, - 'name': 'ClimbingTowerProgressionVisualizer' - } - } - }, - 'Ruins_Hand_Touch_Activator_20982': { - 'hash': 20982, - 'name': 'Ruins Hand Touch Activator', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - } - } - } - } - }, - 'Climbing_Unlock_Orb_Pedestal': { - 'hash': 51594, - 'name': 'Climbing Unlock Orb Pedestal', - 'embedded': { - 'Climbing_Unlock_Orb_Pedestal_51198': { - 'hash': 51198, - 'name': 'Climbing Unlock Orb Pedestal', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - }, - 'Hand_Touch_46540': { - 'hash': 46540, - 'name': 'Hand Touch', - 'savables': { - 'AddUnlockToPlayer': { - 'hash': 1756836969, - 'name': 'AddUnlockToPlayer' - }, - 'ClimbingTowerTeleporterNode': { - 'hash': 392234266, - 'name': 'ClimbingTowerTeleporterNode' - }, - 'OrbBasinVfxController': { - 'hash': 715394364, - 'name': 'OrbBasinVfxController' - }, - 'PlayerUnlockStation': { - 'hash': 2912807649, - 'name': 'PlayerUnlockStation' - } - } - } - } - }, - 'Coal': { - 'hash': 19658, - 'name': 'Coal', - 'embedded': { - 'Coal_19542': { - 'hash': 19542, - 'name': 'Coal', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Coal_Ash': { - 'hash': 2792, - 'name': 'Coal Ash', - 'embedded': { - 'Coal_Ash_2796': { - 'hash': 2796, - 'name': 'Coal Ash', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Coal_Boulder_01': { - 'hash': 23502, - 'name': 'Coal Boulder 01', - 'embedded': { - 'Coal_Boulder_01_23506': { - 'hash': 23506, - 'name': 'Coal Boulder 01', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Coal_Boulder_02': { - 'hash': 57382, - 'name': 'Coal Boulder 02', - 'embedded': { - 'Coal_Boulder_02_57386': { - 'hash': 57386, - 'name': 'Coal Boulder 02', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Coal_Boulder_03': { - 'hash': 23788, - 'name': 'Coal Boulder 03', - 'embedded': { - 'Coal_Boulder_03_23792': { - 'hash': 23792, - 'name': 'Coal Boulder 03', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Coal_Training': { - 'hash': 51610, - 'name': 'Coal Training', - 'embedded': { - 'Coal_Training_51606': { - 'hash': 51606, - 'name': 'Coal Training', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Coin_Press': { - 'hash': 31306, - 'name': 'Coin Press', - 'embedded': { - 'Coin_Press_65312': { - 'hash': 65312, - 'name': 'Coin Press', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - }, - 'Input_36080': { - 'hash': 36080, - 'name': 'Input', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Lever_Physics_45996': { - 'hash': 45996, - 'name': 'Lever Physics', - 'savables': { - 'Lever': { - 'hash': 1594932294, - 'name': 'Lever' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Output_52720': { - 'hash': 52720, - 'name': 'Output', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - } - } - }, - 'Concoction_Crate': { - 'hash': 23304, - 'name': 'Concoction Crate', - 'embedded': { - 'Concoction_Crate_21538': { - 'hash': 21538, - 'name': 'Concoction Crate', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - }, - 'LiquidContainer': { - 'hash': 4179293747, - 'name': 'LiquidContainer' - } - } - }, - 'Heat_Area_15578': { - 'hash': 15578, - 'name': 'Heat Area', - 'savables': {} - } - } - }, - 'Constant': { - 'hash': 42424, - 'name': 'Constant', - 'embedded': {} - }, - 'Cooking_Stand': { - 'hash': 6742, - 'name': 'Cooking Stand', - 'embedded': { - 'Cooking_Stand_51236': { - 'hash': 51236, - 'name': 'Cooking Stand', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - }, - 'Crank_19094': { - 'hash': 19094, - 'name': 'Crank', - 'savables': {} - }, - 'Handle_16064': { - 'hash': 16064, - 'name': 'Handle', - 'savables': { - 'Crank': { - 'hash': 1588536425, - 'name': 'Crank' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Hangable_Dock_5626': { - 'hash': 5626, - 'name': 'Hangable Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Long_S_Hook_17940': { - 'hash': 17940, - 'name': 'Long S Hook', - 'savables': {} - } - } - }, - 'Copper_Boulder': { - 'hash': 65380, - 'name': 'Copper Boulder', - 'embedded': { - 'Copper_Boulder_5600': { - 'hash': 5600, - 'name': 'Copper Boulder', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Spawn_Origin_38012': { - 'hash': 38012, - 'name': 'Spawn Origin', - 'savables': {} - } - } - }, - 'Copper_Boulder_Parts': { - 'hash': 46024, - 'name': 'Copper_Boulder_Parts', - 'embedded': { - 'Copper_Boulder_Parts_4828': { - 'hash': 4828, - 'name': 'Copper_Boulder_Parts', - 'savables': {} - }, - 'Copper_Boulder_part_01_4846': { - 'hash': 4846, - 'name': 'Copper_Boulder_part_01', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Copper_Boulder_part_02_13706': { - 'hash': 13706, - 'name': 'Copper_Boulder_part_02', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Copper_Boulder_part_03_13714': { - 'hash': 13714, - 'name': 'Copper_Boulder_part_03', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Copper_Boulder_part_04_13722': { - 'hash': 13722, - 'name': 'Copper_Boulder_part_04', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Copper_Boulder_part_05_13718': { - 'hash': 13718, - 'name': 'Copper_Boulder_part_05', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Copper_Cluster': { - 'hash': 20646, - 'name': 'Copper Cluster', - 'embedded': { - 'Copper_Cluster_20644': { - 'hash': 20644, - 'name': 'Copper Cluster', - 'savables': {} - } - } - }, - 'Copper_Ingot': { - 'hash': 32850, - 'name': 'Copper Ingot', - 'embedded': { - 'Copper_Ingot_32738': { - 'hash': 32738, - 'name': 'Copper Ingot', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_12806': { - 'hash': 12806, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Copper_Ore': { - 'hash': 2484, - 'name': 'Copper Ore', - 'embedded': { - 'Copper_Ore_24090': { - 'hash': 24090, - 'name': 'Copper Ore', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Craft_Piece_SideFlat_2Way': { - 'hash': 26748, - 'name': 'Craft Piece SideFlat 2Way', - 'embedded': { - 'Craft_Piece_SideFlat_2Way_24176': { - 'hash': 24176, - 'name': 'Craft Piece SideFlat 2Way', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_5256': { - 'hash': 5256, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_Edgetype_Craft_57508': { - 'hash': 57508, - 'name': 'Insert Edgetype Craft', - 'savables': {} - }, - 'Slot_EdgeType_39368': { - 'hash': 39368, - 'name': 'Slot EdgeType', - 'savables': {} - }, - 'Slot_EdgeType_51672': { - 'hash': 51672, - 'name': 'Slot EdgeType', - 'savables': {} - }, - 'Slot_EdgeType_51674': { - 'hash': 51674, - 'name': 'Slot EdgeType', - 'savables': {} - }, - 'Slot_EdgeType_57506': { - 'hash': 57506, - 'name': 'Slot EdgeType', - 'savables': {} - } - } - }, - 'Craft_Piece_Side_1Way': { - 'hash': 1274, - 'name': 'Craft Piece Side 1Way', - 'embedded': { - 'Craft_Piece_Side_1Way_58156': { - 'hash': 58156, - 'name': 'Craft Piece Side 1Way', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_3876': { - 'hash': 3876, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_AxeType_Craft_39368': { - 'hash': 39368, - 'name': 'Insert AxeType Craft', - 'savables': {} - }, - 'Slot_AxeType_7170': { - 'hash': 7170, - 'name': 'Slot AxeType', - 'savables': {} - } - } - }, - 'Craft_Piece_Side_2Way': { - 'hash': 24046, - 'name': 'Craft Piece Side 2Way', - 'embedded': { - 'Craft_Piece_Side_2Way_21146': { - 'hash': 21146, - 'name': 'Craft Piece Side 2Way', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_4164': { - 'hash': 4164, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_AxeType_Craft_39368': { - 'hash': 39368, - 'name': 'Insert AxeType Craft', - 'savables': {} - }, - 'Slot_AxeType_15316': { - 'hash': 15316, - 'name': 'Slot AxeType', - 'savables': {} - }, - 'Slot_AxeType_15318': { - 'hash': 15318, - 'name': 'Slot AxeType', - 'savables': {} - } - } - }, - 'Craft_Piece_Side_4Way': { - 'hash': 32160, - 'name': 'Craft Piece Side 4Way', - 'embedded': { - 'Craft_Piece_Side_4Way_30046': { - 'hash': 30046, - 'name': 'Craft Piece Side 4Way', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_4512': { - 'hash': 4512, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_AxeType_Craft_15432': { - 'hash': 15432, - 'name': 'Insert AxeType Craft', - 'savables': {} - }, - 'Slot_AxeType_17932': { - 'hash': 17932, - 'name': 'Slot AxeType', - 'savables': {} - }, - 'Slot_AxeType_18636': { - 'hash': 18636, - 'name': 'Slot AxeType', - 'savables': {} - }, - 'Slot_AxeType_19782': { - 'hash': 19782, - 'name': 'Slot AxeType', - 'savables': {} - }, - 'Slot_AxeType_40654': { - 'hash': 40654, - 'name': 'Slot AxeType', - 'savables': {} - } - } - }, - 'Craft_Piece_Side_Flat_1Way': { - 'hash': 38606, - 'name': 'Craft Piece Side Flat 1Way', - 'embedded': { - 'Craft_Piece_Side_Flat_1Way_36346': { - 'hash': 36346, - 'name': 'Craft Piece Side Flat 1Way', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_4868': { - 'hash': 4868, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_Edgetype_Craft_15580': { - 'hash': 15580, - 'name': 'Insert Edgetype Craft', - 'savables': {} - }, - 'Slot_EdgeType_38338': { - 'hash': 38338, - 'name': 'Slot EdgeType', - 'savables': {} - }, - 'Slot_EdgeType_39368': { - 'hash': 39368, - 'name': 'Slot EdgeType', - 'savables': {} - } - } - }, - 'Crafting_Deck': { - 'hash': 28396, - 'name': 'Crafting Deck', - 'embedded': { - 'Crafting_Deck_64040': { - 'hash': 64040, - 'name': 'Crafting Deck', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - }, - 'GenericCraftingStation': { - 'hash': 766675725, - 'name': 'GenericCraftingStation' - } - } - }, - 'Crafting_Deck_Crank_Handle_01_16064': { - 'hash': 16064, - 'name': 'Crafting_Deck_Crank_Handle_01', - 'savables': { - 'Crank': { - 'hash': 1588536425, - 'name': 'Crank' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Crafting_Deck_Crank_Handle_02_19132': { - 'hash': 19132, - 'name': 'Crafting_Deck_Crank_Handle_02', - 'savables': { - 'Crank': { - 'hash': 1588536425, - 'name': 'Crank' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Crafting_Deck_Top_MOVE_25974': { - 'hash': 25974, - 'name': 'Crafting_Deck_Top_MOVE', - 'savables': {} - }, - 'Crafting_Deck_top_ROTATE_21724': { - 'hash': 21724, - 'name': 'Crafting_Deck_top_ROTATE', - 'savables': {} - }, - 'GameObject_47008': { - 'hash': 47008, - 'name': 'GameObject', - 'savables': {} - }, - 'Page_Slot_29114': { - 'hash': 29114, - 'name': 'Page Slot', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - } - } - }, - 'Crane_Center_Piece': { - 'hash': 25456, - 'name': 'Crane Center Piece', - 'embedded': { - 'Crane_Center_Piece_6864': { - 'hash': 6864, - 'name': 'Crane Center Piece', - 'savables': {} - } - } - }, - 'Crank': { - 'hash': 15392, - 'name': 'Crank', - 'embedded': {} - }, - 'Crate': { - 'hash': 36180, - 'name': 'Crate', - 'embedded': { - 'Crate_14764': { - 'hash': 14764, - 'name': 'Crate', - 'savables': { - 'GeneratedLoot': { - 'hash': 3642863935, - 'name': 'GeneratedLoot' - } - } - }, - 'Dock_1_2780': { - 'hash': 2780, - 'name': 'Dock 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_2_31842': { - 'hash': 31842, - 'name': 'Dock 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_3_31266': { - 'hash': 31266, - 'name': 'Dock 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_4_30878': { - 'hash': 30878, - 'name': 'Dock 4', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - } - } - }, - 'Crate_Stack_Spawner': { - 'hash': 38974, - 'name': 'Crate Stack Spawner', - 'embedded': { - 'Crate_Stack_Spawner_14614': { - 'hash': 14614, - 'name': 'Crate Stack Spawner', - 'savables': {} - } - } - }, - 'Crater_Gcore_Dynamic': { - 'hash': 21218, - 'name': 'Crater Gcore Dynamic', - 'embedded': { - 'Crater_Gcore_Dynamic_53304': { - 'hash': 53304, - 'name': 'Crater Gcore Dynamic', - 'savables': {} - }, - 'Enemy_Spawn_30256': { - 'hash': 30256, - 'name': 'Enemy Spawn', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'SpawnArea': { - 'hash': 2617495528, - 'name': 'SpawnArea' - } - } - } - } - }, - 'Cross_Slash': { - 'hash': 38008, - 'name': 'Cross Slash', - 'embedded': { - 'Cross_Slash_34552': { - 'hash': 34552, - 'name': 'Cross Slash', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Crystal_Blue': { - 'hash': 38178, - 'name': 'Crystal Blue', - 'embedded': { - 'Crystal_Blue_40232': { - 'hash': 40232, - 'name': 'Crystal Blue', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Crystal_Blue_NoLight': { - 'hash': 14778, - 'name': 'Crystal Blue NoLight', - 'embedded': { - 'Crystal_Blue_NoLight_40232': { - 'hash': 40232, - 'name': 'Crystal Blue NoLight', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Crystal_Cluster_Blue': { - 'hash': 18096, - 'name': 'Crystal Cluster Blue', - 'embedded': { - 'Crystal_Cluster_Blue_24556': { - 'hash': 24556, - 'name': 'Crystal Cluster Blue', - 'savables': {} - } - } - }, - 'Crystal_Gem_Blue': { - 'hash': 8002, - 'name': 'Crystal Gem Blue', - 'embedded': { - 'Crystal_Gem_Blue_11514': { - 'hash': 11514, - 'name': 'Crystal Gem Blue', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Crystal_Lance_Blue': { - 'hash': 23400, - 'name': 'Crystal Lance Blue', - 'embedded': { - 'Crystal_Lance_Blue_26000': { - 'hash': 26000, - 'name': 'Crystal Lance Blue', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Crystal_Pick_Blue': { - 'hash': 2924, - 'name': 'Crystal Pick Blue', - 'embedded': { - 'Crystal_Pick_Blue_5368': { - 'hash': 5368, - 'name': 'Crystal Pick Blue', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Crystal_Shard_Blue': { - 'hash': 7092, - 'name': 'Crystal Shard Blue', - 'embedded': { - 'Crystal_Shard_Blue_9072': { - 'hash': 9072, - 'name': 'Crystal Shard Blue', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Insert_Deco_112': { - 'hash': 112, - 'name': 'Insert Deco', - 'savables': {} - } - } - }, - 'Crystal_Structure_Blue': { - 'hash': 51128, - 'name': 'Crystal Structure Blue', - 'embedded': { - 'Crystal_Structure_Blue_54360': { - 'hash': 54360, - 'name': 'Crystal Structure Blue', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Crystal_Structure_Rocks': { - 'hash': 34144, - 'name': 'Crystal Structure Rocks', - 'embedded': { - 'Crystal_Structure_Rocks_54772': { - 'hash': 54772, - 'name': 'Crystal Structure Rocks', - 'savables': {} - } - } - }, - 'Crystal_Sword_Blue': { - 'hash': 56894, - 'name': 'Crystal Sword Blue', - 'embedded': { - 'Crystal_Sword_Blue_59644': { - 'hash': 59644, - 'name': 'Crystal Sword Blue', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Crystal_Wyrm': { - 'hash': 37392, - 'name': 'Crystal Wyrm', - 'embedded': { - 'Animation_6144': { - 'hash': 6144, - 'name': 'Animation', - 'savables': {} - }, - 'Body_1052': { - 'hash': 1052, - 'name': 'Body', - 'savables': {} - }, - 'Crystal_Wyrm_37044': { - 'hash': 37044, - 'name': 'Crystal Wyrm', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Crystal_Wyrm_AI_46146': { - 'hash': 46146, - 'name': 'Crystal Wyrm AI', - 'savables': {} - }, - 'Gameplay_42330': { - 'hash': 42330, - 'name': 'Gameplay', - 'savables': {} - }, - 'Ground_58968': { - 'hash': 58968, - 'name': 'Ground', - 'savables': {} - }, - 'SlashDamage_L_57358': { - 'hash': 57358, - 'name': 'SlashDamage L', - 'savables': {} - }, - 'SlashDamage_R_59218': { - 'hash': 59218, - 'name': 'SlashDamage R', - 'savables': {} - }, - 'Spawner_240': { - 'hash': 240, - 'name': 'Spawner', - 'savables': {} - }, - 'scythe_l_jnt_544': { - 'hash': 544, - 'name': 'scythe_l_jnt', - 'savables': {} - }, - 'scythe_r_jnt_542': { - 'hash': 542, - 'name': 'scythe_r_jnt', - 'savables': {} - } - } - }, - 'Crystal_Wyrm_(Trial)': { - 'hash': 48128, - 'name': 'Crystal Wyrm (Trial)', - 'embedded': { - 'Animation_6144': { - 'hash': 6144, - 'name': 'Animation', - 'savables': {} - }, - 'Body_1052': { - 'hash': 1052, - 'name': 'Body', - 'savables': {} - }, - 'Crystal_Wyrm_(Trial)_37044': { - 'hash': 37044, - 'name': 'Crystal Wyrm (Trial)', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Crystal_Wyrm_AI_46146': { - 'hash': 46146, - 'name': 'Crystal Wyrm AI', - 'savables': {} - }, - 'Gameplay_42330': { - 'hash': 42330, - 'name': 'Gameplay', - 'savables': {} - }, - 'Ground_58968': { - 'hash': 58968, - 'name': 'Ground', - 'savables': {} - }, - 'SlashDamage_L_57358': { - 'hash': 57358, - 'name': 'SlashDamage L', - 'savables': {} - }, - 'SlashDamage_R_59218': { - 'hash': 59218, - 'name': 'SlashDamage R', - 'savables': {} - }, - 'Spawner_240': { - 'hash': 240, - 'name': 'Spawner', - 'savables': {} - }, - 'scythe_l_jnt_544': { - 'hash': 544, - 'name': 'scythe_l_jnt', - 'savables': {} - }, - 'scythe_r_jnt_542': { - 'hash': 542, - 'name': 'scythe_r_jnt', - 'savables': {} - } - } - }, - 'Cube': { - 'hash': 5262, - 'name': 'Cube', - 'embedded': { - 'Cube_5268': { - 'hash': 5268, - 'name': 'Cube', - 'savables': {} - } - } - }, - 'Curled_Wooden_Handle': { - 'hash': 64172, - 'name': 'Curled Wooden Handle', - 'embedded': { - 'Curled_Wooden_Handle_63962': { - 'hash': 63962, - 'name': 'Curled Wooden Handle', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Dock_32818': { - 'hash': 32818, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Slot_Multi_(1)_2108': { - 'hash': 2108, - 'name': 'Slot Multi (1)', - 'savables': {} - }, - 'Slot_Multi_34270': { - 'hash': 34270, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_Multi_34272': { - 'hash': 34272, - 'name': 'Slot Multi', - 'savables': {} - } - } - }, - 'Customization_Controller': { - 'hash': 5526, - 'name': 'Customization_Controller', - 'embedded': {} - }, - 'Dagger_Blade_Curved': { - 'hash': 9704, - 'name': 'Dagger Blade Curved', - 'embedded': { - 'Dagger_Blade_Curved_35392': { - 'hash': 35392, - 'name': 'Dagger Blade Curved', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_64976': { - 'hash': 64976, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_Straight_Short_SwordType_7796': { - 'hash': 7796, - 'name': 'Insert Straight Short SwordType', - 'savables': {} - }, - 'metal_blade_dagger_curved_LOD0_13424': { - 'hash': 13424, - 'name': 'metal_blade_dagger_curved_LOD0', - 'savables': {} - } - } - }, - 'Dagger_Blade_Edgy': { - 'hash': 49402, - 'name': 'Dagger Blade Edgy', - 'embedded': { - 'Dagger_Blade_Edgy_35392': { - 'hash': 35392, - 'name': 'Dagger Blade Edgy', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_65480': { - 'hash': 65480, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_Straight_Short_SwordType_7796': { - 'hash': 7796, - 'name': 'Insert Straight Short SwordType', - 'savables': {} - }, - 'metal_blade_dagger_edgy_geo_LOD0_6500': { - 'hash': 6500, - 'name': 'metal_blade_dagger_edgy_geo_LOD0', - 'savables': {} - } - } - }, - 'Dagger_Blade_Round': { - 'hash': 56720, - 'name': 'Dagger Blade Round', - 'embedded': { - 'Dagger_Blade_Round_35392': { - 'hash': 35392, - 'name': 'Dagger Blade Round', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_442': { - 'hash': 442, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_Straight_Short_SwordType_7796': { - 'hash': 7796, - 'name': 'Insert Straight Short SwordType', - 'savables': {} - }, - 'metal_blade_dagger_round_full_geo_LOD0_22702': { - 'hash': 22702, - 'name': 'metal_blade_dagger_round_full_geo_LOD0', - 'savables': {} - } - } - }, - 'Dagger_Blade_Wide': { - 'hash': 54482, - 'name': 'Dagger Blade Wide', - 'embedded': { - 'Dagger_Blade_Wide_54484': { - 'hash': 54484, - 'name': 'Dagger Blade Wide', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_926': { - 'hash': 926, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_Straight_Short_SwordType_7796': { - 'hash': 7796, - 'name': 'Insert Straight Short SwordType', - 'savables': {} - }, - 'metal_blade_dagger_wide_full_geo_LOD0_53410': { - 'hash': 53410, - 'name': 'metal_blade_dagger_wide_full_geo_LOD0', - 'savables': {} - } - } - }, - 'Dais_Antler_Red_Variant': { - 'hash': 18358, - 'name': 'Dais Antler Red Variant', - 'embedded': { - 'Dais_AI_22350': { - 'hash': 22350, - 'name': 'Dais AI', - 'savables': {} - }, - 'Dais_Antler_Red_Variant_38050': { - 'hash': 38050, - 'name': 'Dais Antler Red Variant', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Dais_Body_12508': { - 'hash': 12508, - 'name': 'Dais Body', - 'savables': {} - }, - 'Rare_Spawner_53168': { - 'hash': 53168, - 'name': 'Rare Spawner', - 'savables': {} - } - } - }, - 'Dais_Antler_Variant': { - 'hash': 30180, - 'name': 'Dais Antler Variant', - 'embedded': { - 'Dais_AI_22350': { - 'hash': 22350, - 'name': 'Dais AI', - 'savables': {} - }, - 'Dais_Antler_Variant_38050': { - 'hash': 38050, - 'name': 'Dais Antler Variant', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Dais_Body_12508': { - 'hash': 12508, - 'name': 'Dais Body', - 'savables': {} - }, - 'Rare_Spawner_53168': { - 'hash': 53168, - 'name': 'Rare Spawner', - 'savables': {} - } - } - }, - 'Dais_Child_Red_Variant': { - 'hash': 13444, - 'name': 'Dais Child Red Variant', - 'embedded': { - 'Dais_AI_22350': { - 'hash': 22350, - 'name': 'Dais AI', - 'savables': {} - }, - 'Dais_Body_12508': { - 'hash': 12508, - 'name': 'Dais Body', - 'savables': {} - }, - 'Dais_Child_Red_Variant_38050': { - 'hash': 38050, - 'name': 'Dais Child Red Variant', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Rare_Spawner_53168': { - 'hash': 53168, - 'name': 'Rare Spawner', - 'savables': {} - } - } - }, - 'Dais_Child_Variant': { - 'hash': 31838, - 'name': 'Dais Child Variant', - 'embedded': { - 'Dais_AI_22350': { - 'hash': 22350, - 'name': 'Dais AI', - 'savables': {} - }, - 'Dais_Body_12508': { - 'hash': 12508, - 'name': 'Dais Body', - 'savables': {} - }, - 'Dais_Child_Variant_38050': { - 'hash': 38050, - 'name': 'Dais Child Variant', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Rare_Spawner_53168': { - 'hash': 53168, - 'name': 'Rare Spawner', - 'savables': {} - } - } - }, - 'Dais_Meat_Full_Burnt': { - 'hash': 41870, - 'name': 'Dais Meat Full Burnt', - 'embedded': { - 'Cooking_24500': { - 'hash': 24500, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Dais_Meat_Full_Burnt_47410': { - 'hash': 47410, - 'name': 'Dais Meat Full Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Dais_Meat_Full_Cooked': { - 'hash': 43452, - 'name': 'Dais Meat Full Cooked', - 'embedded': { - 'Cooking_24500': { - 'hash': 24500, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Dais_Meat_Full_Cooked_47410': { - 'hash': 47410, - 'name': 'Dais Meat Full Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Dais_Meat_Full_Ripe': { - 'hash': 47394, - 'name': 'Dais Meat Full Ripe', - 'embedded': { - 'Cooking_24500': { - 'hash': 24500, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Dais_Meat_Full_Ripe_42392': { - 'hash': 42392, - 'name': 'Dais Meat Full Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Dais_Meat_Half_Burnt': { - 'hash': 43674, - 'name': 'Dais Meat Half Burnt', - 'embedded': { - 'Cooking_24500': { - 'hash': 24500, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Dais_Meat_Half_Burnt_47410': { - 'hash': 47410, - 'name': 'Dais Meat Half Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Dais_Meat_Half_Cooked': { - 'hash': 43502, - 'name': 'Dais Meat Half Cooked', - 'embedded': { - 'Cooking_24500': { - 'hash': 24500, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Dais_Meat_Half_Cooked_47410': { - 'hash': 47410, - 'name': 'Dais Meat Half Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Dais_Meat_Half_Ripe': { - 'hash': 43294, - 'name': 'Dais Meat Half Ripe', - 'embedded': { - 'Cooking_24500': { - 'hash': 24500, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Dais_Meat_Half_Ripe_47410': { - 'hash': 47410, - 'name': 'Dais Meat Half Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Dais_Red_Variant': { - 'hash': 8530, - 'name': 'Dais Red Variant', - 'embedded': { - 'Dais_AI_22350': { - 'hash': 22350, - 'name': 'Dais AI', - 'savables': {} - }, - 'Dais_Body_12508': { - 'hash': 12508, - 'name': 'Dais Body', - 'savables': {} - }, - 'Dais_Red_Variant_38050': { - 'hash': 38050, - 'name': 'Dais Red Variant', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Rare_Spawner_53168': { - 'hash': 53168, - 'name': 'Rare Spawner', - 'savables': {} - } - } - }, - 'Dais_Variant': { - 'hash': 42430, - 'name': 'Dais Variant', - 'embedded': { - 'Dais_AI_22350': { - 'hash': 22350, - 'name': 'Dais AI', - 'savables': {} - }, - 'Dais_Body_12508': { - 'hash': 12508, - 'name': 'Dais Body', - 'savables': {} - }, - 'Dais_Variant_38050': { - 'hash': 38050, - 'name': 'Dais Variant', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Rare_Spawner_53168': { - 'hash': 53168, - 'name': 'Rare Spawner', - 'savables': {} - } - } - }, - 'Darksteel_Ingot': { - 'hash': 57556, - 'name': 'Darksteel_Ingot', - 'embedded': {} - }, - 'Death_Fern': { - 'hash': 37642, - 'name': 'Death Fern', - 'embedded': { - 'Death_Fern_37626': { - 'hash': 37626, - 'name': 'Death Fern', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Death_Fern_AI_29794': { - 'hash': 29794, - 'name': 'Death Fern AI', - 'savables': {} - }, - 'Emit_Gas_Spawner_16984': { - 'hash': 16984, - 'name': 'Emit Gas Spawner', - 'savables': {} - } - } - }, - 'Death_Fern_Poison_Cloud': { - 'hash': 39240, - 'name': 'Death Fern Poison Cloud', - 'embedded': { - 'Death_Fern_Poison_Cloud_50236': { - 'hash': 50236, - 'name': 'Death Fern Poison Cloud', - 'savables': {} - } - } - }, - 'Death_Fern_Seed_Planted': { - 'hash': 40824, - 'name': 'Death Fern Seed Planted', - 'embedded': { - 'Death_Fern_Seed_Planted_40780': { - 'hash': 40780, - 'name': 'Death Fern Seed Planted', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'DebugArrow': { - 'hash': 34892, - 'name': 'DebugArrow', - 'embedded': { - 'Arrow_Tip_59378': { - 'hash': 59378, - 'name': 'Arrow Tip', - 'savables': {} - }, - 'DebugArrow_43746': { - 'hash': 43746, - 'name': 'DebugArrow', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'Embeddable': { - 'hash': 22446553, - 'name': 'Embeddable' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'DebugNet': { - 'hash': 12632, - 'name': 'DebugNet', - 'embedded': {} - }, - 'DebugPlayerStone': { - 'hash': 62120, - 'name': 'DebugPlayerStone', - 'embedded': { - 'DebugPlayerStone_30920': { - 'hash': 30920, - 'name': 'DebugPlayerStone', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Insert_Primitive_SwordType_7796': { - 'hash': 7796, - 'name': 'Insert Primitive SwordType', - 'savables': {} - } - } - }, - 'DebugTool': { - 'hash': 16078, - 'name': 'DebugTool', - 'embedded': {} - }, - 'Decrafting_Deck': { - 'hash': 62244, - 'name': 'Decrafting Deck', - 'embedded': { - 'Decrafting_Deck_13304': { - 'hash': 13304, - 'name': 'Decrafting Deck', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - }, - 'Lever_Physics_45996': { - 'hash': 45996, - 'name': 'Lever Physics', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'TwoStepLever': { - 'hash': 2213531414, - 'name': 'TwoStepLever' - } - } - }, - 'Pickup_Holder_65018': { - 'hash': 65018, - 'name': 'Pickup Holder', - 'savables': {} - } - } - }, - 'Default_Burnt_Stew': { - 'hash': 20108, - 'name': 'Default_Burnt_Stew', - 'embedded': {} - }, - 'Default_Cooked_Stew': { - 'hash': 19398, - 'name': 'Default_Cooked_Stew', - 'embedded': {} - }, - 'Default_Raw_Stew': { - 'hash': 43078, - 'name': 'Default_Raw_Stew', - 'embedded': {} - }, - 'Descent_Shaft_Gcore_Elevator_Dynamic': { - 'hash': 52804, - 'name': 'Descent Shaft Gcore Elevator Dynamic', - 'embedded': { - 'Crafting_Deck_Crank_Handle_01_16064': { - 'hash': 16064, - 'name': 'Crafting_Deck_Crank_Handle_01', - 'savables': { - 'Crank': { - 'hash': 1588536425, - 'name': 'Crank' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Crafting_Deck_Crank_Handle_01_46520': { - 'hash': 46520, - 'name': 'Crafting_Deck_Crank_Handle_01', - 'savables': { - 'Crank': { - 'hash': 1588536425, - 'name': 'Crank' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Crafting_Deck_Crank_Handle_01_60092': { - 'hash': 60092, - 'name': 'Crafting_Deck_Crank_Handle_01', - 'savables': { - 'Crank': { - 'hash': 1588536425, - 'name': 'Crank' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Descent_Shaft_Gcore_Elevator_Dynamic_26570': { - 'hash': 26570, - 'name': 'Descent Shaft Gcore Elevator Dynamic', - 'savables': {} - }, - 'Elevator_61068': { - 'hash': 61068, - 'name': 'Elevator', - 'savables': { - 'NetworkedFloatStream': { - 'hash': 2127962967, - 'name': 'NetworkedFloatStream' - } - } - } - } - }, - 'Descent_Shaft_Gcore_Floor_Diggable_Dynamic': { - 'hash': 18120, - 'name': 'Descent Shaft Gcore Floor Diggable Dynamic', - 'embedded': { - 'Descent_Shaft_Gcore_Floor_Diggable_Dynamic_26570': { - 'hash': 26570, - 'name': 'Descent Shaft Gcore Floor Diggable Dynamic', - 'savables': {} - }, - 'Diggable_Spawner_2456': { - 'hash': 2456, - 'name': 'Diggable Spawner', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'SpawnArea': { - 'hash': 2617495528, - 'name': 'SpawnArea' - } - } - } - } - }, - 'Descent_Shaft_Gcore_Floor_Mining_Boulder_Dynamic': { - 'hash': 6308, - 'name': 'Descent Shaft Gcore Floor Mining Boulder Dynamic', - 'embedded': { - 'Descent_Shaft_Gcore_Floor_Mining_Boulder_Dynamic_26570': { - 'hash': 26570, - 'name': 'Descent Shaft Gcore Floor Mining Boulder Dynamic', - 'savables': {} - }, - 'Spawner_2456': { - 'hash': 2456, - 'name': 'Spawner', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'SpawnArea': { - 'hash': 2617495528, - 'name': 'SpawnArea' - } - } - } - } - }, - 'Descent_Shaft_Gcore_Wall_Wyrm_Dynamic': { - 'hash': 33338, - 'name': 'Descent Shaft Gcore Wall Wyrm Dynamic', - 'embedded': { - 'Descent_Shaft_Gcore_Wall_Wyrm_Dynamic_26570': { - 'hash': 26570, - 'name': 'Descent Shaft Gcore Wall Wyrm Dynamic', - 'savables': {} - }, - 'Spawner_36350': { - 'hash': 36350, - 'name': 'Spawner', - 'savables': { - 'CylindricalBoundsSurface': { - 'hash': 34507654, - 'name': 'CylindricalBoundsSurface' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - } - } - }, - 'Digging_Box_Hebios': { - 'hash': 42226, - 'name': 'Digging Box Hebios', - 'embedded': { - 'Destroy_Effect_Spawner_61034': { - 'hash': 61034, - 'name': 'Destroy Effect Spawner', - 'savables': {} - }, - 'Digging_Box_Hebios_43820': { - 'hash': 43820, - 'name': 'Digging Box Hebios', - 'savables': { - 'HealthBasedDigable': { - 'hash': 2126500253, - 'name': 'HealthBasedDigable' - } - } - }, - 'Spawn_Point_42650': { - 'hash': 42650, - 'name': 'Spawn Point', - 'savables': {} - } - } - }, - 'Digging_Dirt_Mound': { - 'hash': 43924, - 'name': 'Digging Dirt Mound', - 'embedded': { - 'Destroy_Effect_Spawner_61034': { - 'hash': 61034, - 'name': 'Destroy Effect Spawner', - 'savables': {} - }, - 'Destroy_Gravestone_Spawner_40844': { - 'hash': 40844, - 'name': 'Destroy Gravestone Spawner', - 'savables': {} - }, - 'Digging_Dirt_Mound_43820': { - 'hash': 43820, - 'name': 'Digging Dirt Mound', - 'savables': { - 'HealthBasedDigable': { - 'hash': 2126500253, - 'name': 'HealthBasedDigable' - } - } - }, - 'Spawn_Point_42650': { - 'hash': 42650, - 'name': 'Spawn Point', - 'savables': {} - }, - 'Stone_Spawner_6570': { - 'hash': 6570, - 'name': 'Stone Spawner', - 'savables': {} - } - } - }, - 'Digging_Dirt_Mound_Hebios': { - 'hash': 33570, - 'name': 'Digging Dirt Mound Hebios', - 'embedded': { - 'Destroy_Effect_Spawner_61034': { - 'hash': 61034, - 'name': 'Destroy Effect Spawner', - 'savables': {} - }, - 'Destroy_Gravestone_Spawner_40844': { - 'hash': 40844, - 'name': 'Destroy Gravestone Spawner', - 'savables': {} - }, - 'Digging_Dirt_Mound_Hebios_43820': { - 'hash': 43820, - 'name': 'Digging Dirt Mound Hebios', - 'savables': { - 'HealthBasedDigable': { - 'hash': 2126500253, - 'name': 'HealthBasedDigable' - } - } - }, - 'Spawn_Point_42650': { - 'hash': 42650, - 'name': 'Spawn Point', - 'savables': {} - }, - 'Stone_Spawner_6570': { - 'hash': 6570, - 'name': 'Stone Spawner', - 'savables': {} - } - } - }, - 'Digging_Dirt_Parts': { - 'hash': 2538, - 'name': 'Digging Dirt Parts', - 'embedded': { - 'Digging_Dirt_Parts_2554': { - 'hash': 2554, - 'name': 'Digging Dirt Parts', - 'savables': {} - }, - 'digging_chunk_01_LOD0_2158': { - 'hash': 2158, - 'name': 'digging_chunk_01_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'digging_chunk_02_LOD0_2166': { - 'hash': 2166, - 'name': 'digging_chunk_02_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'digging_chunk_03_LOD0_2182': { - 'hash': 2182, - 'name': 'digging_chunk_03_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'digging_chunk_04_LOD0_2164': { - 'hash': 2164, - 'name': 'digging_chunk_04_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'digging_chunk_05_LOD0_2180': { - 'hash': 2180, - 'name': 'digging_chunk_05_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'digging_chunk_06_LOD0_2178': { - 'hash': 2178, - 'name': 'digging_chunk_06_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'digging_chunk_07_LOD0_2170': { - 'hash': 2170, - 'name': 'digging_chunk_07_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'digging_chunk_08_LOD0_2168': { - 'hash': 2168, - 'name': 'digging_chunk_08_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'digging_chunk_09_LOD0_2176': { - 'hash': 2176, - 'name': 'digging_chunk_09_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'digging_chunk_10_LOD0_2174': { - 'hash': 2174, - 'name': 'digging_chunk_10_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'digging_chunk_11_LOD0_2162': { - 'hash': 2162, - 'name': 'digging_chunk_11_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'digging_chunk_12_LOD0_2160': { - 'hash': 2160, - 'name': 'digging_chunk_12_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'digging_chunk_13_LOD0_2172': { - 'hash': 2172, - 'name': 'digging_chunk_13_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Digging_Geode': { - 'hash': 55696, - 'name': 'Digging Geode', - 'embedded': { - 'Destroy_Effect_Spawner_61034': { - 'hash': 61034, - 'name': 'Destroy Effect Spawner', - 'savables': {} - }, - 'Digging_Geode_43820': { - 'hash': 43820, - 'name': 'Digging Geode', - 'savables': { - 'HealthBasedDigable': { - 'hash': 2126500253, - 'name': 'HealthBasedDigable' - } - } - }, - 'Spawn_Point_42650': { - 'hash': 42650, - 'name': 'Spawn Point', - 'savables': {} - } - } - }, - 'Digging_Material_Box': { - 'hash': 35612, - 'name': 'Digging Material Box', - 'embedded': { - 'Destroy_Effect_Spawner_61034': { - 'hash': 61034, - 'name': 'Destroy Effect Spawner', - 'savables': {} - }, - 'Digging_Material_Box_43820': { - 'hash': 43820, - 'name': 'Digging Material Box', - 'savables': { - 'HealthBasedDigable': { - 'hash': 2126500253, - 'name': 'HealthBasedDigable' - } - } - }, - 'Spawn_Point_42650': { - 'hash': 42650, - 'name': 'Spawn Point', - 'savables': {} - } - } - }, - 'Directional_Encounter': { - 'hash': 23796, - 'name': 'Directional_Encounter', - 'embedded': {} - }, - 'Discovery_Landmark': { - 'hash': 37940, - 'name': 'Discovery_Landmark', - 'embedded': {} - }, - 'Disk_Encounter': { - 'hash': 65062, - 'name': 'Disk_Encounter', - 'embedded': {} - }, - 'Dragonfly': { - 'hash': 54404, - 'name': 'Dragonfly', - 'embedded': { - 'Dragonfly_38050': { - 'hash': 38050, - 'name': 'Dragonfly', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Dragonfly_AI_22350': { - 'hash': 22350, - 'name': 'Dragonfly AI', - 'savables': {} - }, - 'Dragonfly_Body_7558': { - 'hash': 7558, - 'name': 'Dragonfly Body', - 'savables': {} - } - } - }, - 'Dragonfly_Corpse': { - 'hash': 43552, - 'name': 'Dragonfly Corpse', - 'embedded': { - 'Dragonfly_Corpse_43536': { - 'hash': 43536, - 'name': 'Dragonfly Corpse', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Drawbridge_Puzzle_Range': { - 'hash': 40692, - 'name': 'Drawbridge Puzzle Range', - 'embedded': { - 'Drawbridge_44588': { - 'hash': 44588, - 'name': 'Drawbridge', - 'savables': { - 'DrawBridgeRangeLogic': { - 'hash': 2801168996, - 'name': 'DrawBridgeRangeLogic' - } - } - }, - 'Drawbridge_Puzzle_Range_48230': { - 'hash': 48230, - 'name': 'Drawbridge Puzzle Range', - 'savables': { - 'LogicFloatReceiver': { - 'hash': 3188272159, - 'name': 'LogicFloatReceiver' - } - } - } - } - }, - 'Drawbridge_Puzzle_Range_long': { - 'hash': 58514, - 'name': 'Drawbridge Puzzle Range long', - 'embedded': { - 'Drawbridge_Puzzle_Range_long_62878': { - 'hash': 62878, - 'name': 'Drawbridge Puzzle Range long', - 'savables': { - 'DrawBridgeRangeLogic': { - 'hash': 2801168996, - 'name': 'DrawBridgeRangeLogic' - }, - 'LinearPartCloner': { - 'hash': 566175523, - 'name': 'LinearPartCloner' - }, - 'LogicFloatReceiver': { - 'hash': 3188272159, - 'name': 'LogicFloatReceiver' - } - } - } - } - }, - 'Drawbridge_Puzzle_Toggle': { - 'hash': 24580, - 'name': 'Drawbridge Puzzle Toggle', - 'embedded': { - 'Drawbridge_Puzzle_Toggle_41872': { - 'hash': 41872, - 'name': 'Drawbridge Puzzle Toggle', - 'savables': { - 'DrawBridgeLogic': { - 'hash': 2978042925, - 'name': 'DrawBridgeLogic' - }, - 'DrawBridgeRangeLogic': { - 'hash': 2801168996, - 'name': 'DrawBridgeRangeLogic' - }, - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - } - } - } - } - }, - 'Dried_Grass_Bush': { - 'hash': 24480, - 'name': 'Dried Grass Bush', - 'embedded': { - 'Dried_Grass_Bush_24440': { - 'hash': 24440, - 'name': 'Dried Grass Bush', - 'savables': {} - } - } - }, - 'Dummy_Shelf_Short': { - 'hash': 62404, - 'name': 'Dummy Shelf Short', - 'embedded': { - 'Dock_58090': { - 'hash': 58090, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dummy_Shelf_Short_60158': { - 'hash': 60158, - 'name': 'Dummy Shelf Short', - 'savables': {} - } - } - }, - 'Duplicate_Paper_Variant': { - 'hash': 11048, - 'name': 'Duplicate_Paper_Variant', - 'embedded': {} - }, - 'Dynamite': { - 'hash': 31326, - 'name': 'Dynamite', - 'embedded': { - 'Dynamite_40522': { - 'hash': 40522, - 'name': 'Dynamite', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Explosion_58370': { - 'hash': 58370, - 'name': 'Explosion', - 'savables': {} - }, - 'Fuse_15214': { - 'hash': 15214, - 'name': 'Fuse', - 'savables': { - 'Fire': { - 'hash': 3457519710, - 'name': 'Fire' - }, - 'Fuse': { - 'hash': 3665939353, - 'name': 'Fuse' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Easter_Egg_01': { - 'hash': 55462, - 'name': 'Easter Egg 01', - 'embedded': { - 'Easter_Egg_01_21224': { - 'hash': 21224, - 'name': 'Easter Egg 01', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Easter_Egg_02': { - 'hash': 57998, - 'name': 'Easter Egg 02', - 'embedded': { - 'Easter_Egg_02_28794': { - 'hash': 28794, - 'name': 'Easter Egg 02', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Easter_Egg_03': { - 'hash': 20128, - 'name': 'Easter Egg 03', - 'embedded': { - 'Easter_Egg_03_28794': { - 'hash': 28794, - 'name': 'Easter Egg 03', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Easter_Egg_04': { - 'hash': 21558, - 'name': 'Easter Egg 04', - 'embedded': { - 'Easter_Egg_04_28794': { - 'hash': 28794, - 'name': 'Easter Egg 04', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Edge_Blade_Long_Curve': { - 'hash': 17478, - 'name': 'Edge Blade Long Curve', - 'embedded': { - 'Edge_Blade_Long_Curve_15172': { - 'hash': 15172, - 'name': 'Edge Blade Long Curve', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_5674': { - 'hash': 5674, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_Edgetype_7796': { - 'hash': 7796, - 'name': 'Insert Edgetype', - 'savables': {} - }, - 'edge_blade_longCurve_LOD0_22044': { - 'hash': 22044, - 'name': 'edge_blade_longCurve_LOD0', - 'savables': {} - } - } - }, - 'Edge_Curved_Blade': { - 'hash': 11938, - 'name': 'Edge Curved Blade', - 'embedded': { - 'Edge_Curved_Blade_9684': { - 'hash': 9684, - 'name': 'Edge Curved Blade', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_6064': { - 'hash': 6064, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_Edgetype_7796': { - 'hash': 7796, - 'name': 'Insert Edgetype', - 'savables': {} - }, - 'edge_blade_curved_LOD0_8062': { - 'hash': 8062, - 'name': 'edge_blade_curved_LOD0', - 'savables': {} - } - } - }, - 'Edge_Short_Curve_Blade': { - 'hash': 20892, - 'name': 'Edge Short Curve Blade', - 'embedded': { - 'Edge_Short_Curve_Blade_18048': { - 'hash': 18048, - 'name': 'Edge Short Curve Blade', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_6416': { - 'hash': 6416, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_Edgetype_7796': { - 'hash': 7796, - 'name': 'Insert Edgetype', - 'savables': {} - }, - 'edge_blade_shortCurve_LOD0_64382': { - 'hash': 64382, - 'name': 'edge_blade_shortCurve_LOD0', - 'savables': {} - } - } - }, - 'Edge_Straight_Blade': { - 'hash': 30124, - 'name': 'Edge Straight Blade', - 'embedded': { - 'Edge_Straight_Blade_27748': { - 'hash': 27748, - 'name': 'Edge Straight Blade', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_6764': { - 'hash': 6764, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_Edgetype_7796': { - 'hash': 7796, - 'name': 'Insert Edgetype', - 'savables': {} - }, - 'edge_blade_straight_LOD0_35880': { - 'hash': 35880, - 'name': 'edge_blade_straight_LOD0', - 'savables': {} - } - } - }, - 'Eggplant_Flower_Bloom': { - 'hash': 27848, - 'name': 'Eggplant Flower Bloom', - 'embedded': { - 'Eggplant_Flower_Bloom_42092': { - 'hash': 42092, - 'name': 'Eggplant Flower Bloom', - 'savables': {} - } - } - }, - 'Eggplant_Flower_Bud': { - 'hash': 27850, - 'name': 'Eggplant Flower Bud', - 'embedded': { - 'Eggplant_Flower_Bud_42164': { - 'hash': 42164, - 'name': 'Eggplant Flower Bud', - 'savables': {} - } - } - }, - 'Eggplant_Full_Burnt': { - 'hash': 55030, - 'name': 'Eggplant Full Burnt', - 'embedded': { - 'Cooking_29582': { - 'hash': 29582, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Eggplant_Full_Burnt_54596': { - 'hash': 54596, - 'name': 'Eggplant Full Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Eggplant_Full_Cooked': { - 'hash': 54506, - 'name': 'Eggplant Full Cooked', - 'embedded': { - 'Cooking_29092': { - 'hash': 29092, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Eggplant_Full_Cooked_54072': { - 'hash': 54072, - 'name': 'Eggplant Full Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Eggplant_Full_Ripe': { - 'hash': 53982, - 'name': 'Eggplant Full Ripe', - 'embedded': { - 'Cooking_28602': { - 'hash': 28602, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Eggplant_Full_Ripe_53548': { - 'hash': 53548, - 'name': 'Eggplant Full Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Eggplant_Full_Unripe': { - 'hash': 53458, - 'name': 'Eggplant Full Unripe', - 'embedded': { - 'Cooking_28112': { - 'hash': 28112, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Eggplant_Full_Unripe_53024': { - 'hash': 53024, - 'name': 'Eggplant Full Unripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Eggplant_Growth': { - 'hash': 19304, - 'name': 'Eggplant Growth', - 'embedded': { - 'Eggplant_Growth_33458': { - 'hash': 33458, - 'name': 'Eggplant Growth', - 'savables': { - 'GrowerComponent': { - 'hash': 3402094521, - 'name': 'GrowerComponent' - } - } - } - } - }, - 'Eggplant_Half_Burnt': { - 'hash': 62546, - 'name': 'Eggplant Half Burnt', - 'embedded': { - 'Cooking_37586': { - 'hash': 37586, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Eggplant_Half_Burnt_62208': { - 'hash': 62208, - 'name': 'Eggplant Half Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Eggplant_Half_Cooked': { - 'hash': 62142, - 'name': 'Eggplant Half Cooked', - 'embedded': { - 'Cooking_37240': { - 'hash': 37240, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Eggplant_Half_Cooked_61804': { - 'hash': 61804, - 'name': 'Eggplant Half Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Eggplant_Half_Ripe': { - 'hash': 61738, - 'name': 'Eggplant Half Ripe', - 'embedded': { - 'Cooking_36894': { - 'hash': 36894, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Eggplant_Half_Ripe_61400': { - 'hash': 61400, - 'name': 'Eggplant Half Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Eggplant_Half_Unripe': { - 'hash': 61334, - 'name': 'Eggplant Half Unripe', - 'embedded': { - 'Cooking_36548': { - 'hash': 36548, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Eggplant_Half_Unripe_60996': { - 'hash': 60996, - 'name': 'Eggplant Half Unripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'RaycastCrafter': { - 'hash': 2815374842, - 'name': 'RaycastCrafter' - } - } - } - } - }, - 'Eggplant_Potato_Recipe_Burnt_Stew': { - 'hash': 57688, - 'name': 'Eggplant_Potato_Recipe_Burnt_Stew', - 'embedded': {} - }, - 'Eggplant_Potato_Recipe_Cooked_Stew': { - 'hash': 57712, - 'name': 'Eggplant_Potato_Recipe_Cooked_Stew', - 'embedded': {} - }, - 'Eggplant_Potato_Recipe_Raw_Stew': { - 'hash': 57736, - 'name': 'Eggplant_Potato_Recipe_Raw_Stew', - 'embedded': {} - }, - 'Eggplant_Tree': { - 'hash': 27004, - 'name': 'Eggplant Tree', - 'embedded': { - 'Eggplant_Tree_24994': { - 'hash': 24994, - 'name': 'Eggplant Tree', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Eggplant_Tree_Growth': { - 'hash': 15090, - 'name': 'Eggplant Tree Growth', - 'embedded': { - 'Eggplant_Tree_Growth_33458': { - 'hash': 33458, - 'name': 'Eggplant Tree Growth', - 'savables': { - 'GrowerComponent': { - 'hash': 3402094521, - 'name': 'GrowerComponent' - } - } - } - } - }, - 'Eggplant_Tree_Separated': { - 'hash': 17770, - 'name': 'Eggplant_Tree_Separated', - 'embedded': {} - }, - 'Eggplant_Tree_Stage_1': { - 'hash': 14282, - 'name': 'Eggplant Tree Stage 1', - 'embedded': { - 'Eggplant_Tree_Stage_1_63514': { - 'hash': 63514, - 'name': 'Eggplant Tree Stage 1', - 'savables': {} - } - } - }, - 'Eggplant_Tree_Stage_2': { - 'hash': 14440, - 'name': 'Eggplant Tree Stage 2', - 'embedded': { - 'Eggplant_Tree_Stage_2_26756': { - 'hash': 26756, - 'name': 'Eggplant Tree Stage 2', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Eggplant_Tree_Stage_3': { - 'hash': 16154, - 'name': 'Eggplant Tree Stage 3', - 'embedded': { - 'Eggplant_Tree_Stage_3_22270': { - 'hash': 22270, - 'name': 'Eggplant Tree Stage 3', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Elevator': { - 'hash': 44898, - 'name': 'Elevator', - 'embedded': { - 'Crafting_Deck_Crank_Handle_01_16064': { - 'hash': 16064, - 'name': 'Crafting_Deck_Crank_Handle_01', - 'savables': { - 'Crank': { - 'hash': 1588536425, - 'name': 'Crank' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Crafting_Deck_Crank_Handle_01_46520': { - 'hash': 46520, - 'name': 'Crafting_Deck_Crank_Handle_01', - 'savables': { - 'Crank': { - 'hash': 1588536425, - 'name': 'Crank' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Elevator_26570': { - 'hash': 26570, - 'name': 'Elevator', - 'savables': { - 'WayPointPath': { - 'hash': 1063725326, - 'name': 'WayPointPath' - } - } - } - } - }, - 'Elevator_Puzzle_Crank': { - 'hash': 64134, - 'name': 'Elevator Puzzle Crank', - 'embedded': { - 'Crafting_Deck_Crank_Handle_01_16064': { - 'hash': 16064, - 'name': 'Crafting_Deck_Crank_Handle_01', - 'savables': { - 'Crank': { - 'hash': 1588536425, - 'name': 'Crank' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Crafting_Deck_Crank_Handle_01_46520': { - 'hash': 46520, - 'name': 'Crafting_Deck_Crank_Handle_01', - 'savables': { - 'Crank': { - 'hash': 1588536425, - 'name': 'Crank' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Elevator_26570': { - 'hash': 26570, - 'name': 'Elevator', - 'savables': { - 'WayPointPath': { - 'hash': 1063725326, - 'name': 'WayPointPath' - } - } - }, - 'Elevator_Puzzle_Crank_52968': { - 'hash': 52968, - 'name': 'Elevator Puzzle Crank', - 'savables': { - 'LogicFloatReceiver': { - 'hash': 3188272159, - 'name': 'LogicFloatReceiver' - } - } - } - } - }, - 'Elevator_Puzzle_Rope': { - 'hash': 20484, - 'name': 'Elevator Puzzle Rope', - 'embedded': { - 'Elevator_26570': { - 'hash': 26570, - 'name': 'Elevator', - 'savables': { - 'WayPointPath': { - 'hash': 1063725326, - 'name': 'WayPointPath' - } - } - }, - 'Elevator_Puzzle_Rope_27070': { - 'hash': 27070, - 'name': 'Elevator Puzzle Rope', - 'savables': { - 'LogicFloatReceiver': { - 'hash': 3188272159, - 'name': 'LogicFloatReceiver' - } - } - } - } - }, - 'Empty': { - 'hash': 40954, - 'name': 'Empty', - 'embedded': {} - }, - 'Etheral_Arrow': { - 'hash': 52366, - 'name': 'Etheral Arrow', - 'embedded': { - 'Etheral_Arrow_43746': { - 'hash': 43746, - 'name': 'Etheral Arrow', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Spike_grp_58940': { - 'hash': 58940, - 'name': 'Spike_grp', - 'savables': {} - } - } - }, - 'Evinon_Steel_Ingot': { - 'hash': 32198, - 'name': 'Evinon Steel Ingot', - 'embedded': { - 'Evinon_Steel_Ingot_32738': { - 'hash': 32738, - 'name': 'Evinon Steel Ingot', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_12930': { - 'hash': 12930, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Explosion_Boulder': { - 'hash': 44162, - 'name': 'Explosion Boulder', - 'embedded': { - 'Explosion_Boulder_13178': { - 'hash': 13178, - 'name': 'Explosion Boulder', - 'savables': { - 'ModifiableAdditionalStaticContent': { - 'hash': 159391088, - 'name': 'ModifiableAdditionalStaticContent' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Explosion_Boulder_Large': { - 'hash': 30854, - 'name': 'Explosion Boulder Large', - 'embedded': { - 'Explosion_Boulder_Large_30852': { - 'hash': 30852, - 'name': 'Explosion Boulder Large', - 'savables': { - 'ModifiableAdditionalStaticContent': { - 'hash': 159391088, - 'name': 'ModifiableAdditionalStaticContent' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Explosive_Spike': { - 'hash': 50412, - 'name': 'Explosive Spike', - 'embedded': { - 'Explosion_58370': { - 'hash': 58370, - 'name': 'Explosion', - 'savables': {} - }, - 'Explosive_Spike_15532': { - 'hash': 15532, - 'name': 'Explosive Spike', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Insert_Deco_112': { - 'hash': 112, - 'name': 'Insert Deco', - 'savables': {} - } - } - }, - 'Fake_Player_combat_dummy': { - 'hash': 45454, - 'name': 'Fake Player combat_dummy', - 'embedded': { - 'Fake_Player_combat_dummy_57314': { - 'hash': 57314, - 'name': 'Fake Player combat_dummy', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'dummy_arm_l_01_jnt_46272': { - 'hash': 46272, - 'name': 'dummy_arm_l_01_jnt', - 'savables': {} - }, - 'dummy_arm_l_02_jnt_46248': { - 'hash': 46248, - 'name': 'dummy_arm_l_02_jnt', - 'savables': {} - }, - 'dummy_arm_l_03_jnt_46250': { - 'hash': 46250, - 'name': 'dummy_arm_l_03_jnt', - 'savables': {} - }, - 'dummy_arm_r_01_jnt_46246': { - 'hash': 46246, - 'name': 'dummy_arm_r_01_jnt', - 'savables': {} - }, - 'dummy_arm_r_02_jnt_46254': { - 'hash': 46254, - 'name': 'dummy_arm_r_02_jnt', - 'savables': {} - }, - 'dummy_arm_r_03_jnt_46256': { - 'hash': 46256, - 'name': 'dummy_arm_r_03_jnt', - 'savables': {} - }, - 'dummy_head_01_jnt_46270': { - 'hash': 46270, - 'name': 'dummy_head_01_jnt', - 'savables': {} - }, - 'dummy_head_02_jnt_46264': { - 'hash': 46264, - 'name': 'dummy_head_02_jnt', - 'savables': {} - }, - 'dummy_head_03_jnt_46262': { - 'hash': 46262, - 'name': 'dummy_head_03_jnt', - 'savables': {} - }, - 'dummy_neck_jnt_46268': { - 'hash': 46268, - 'name': 'dummy_neck_jnt', - 'savables': {} - }, - 'dummy_spineMid_jnt_46274': { - 'hash': 46274, - 'name': 'dummy_spineMid_jnt', - 'savables': {} - }, - 'dummy_spine_01_jnt_46258': { - 'hash': 46258, - 'name': 'dummy_spine_01_jnt', - 'savables': {} - }, - 'dummy_spine_02_jnt_46260': { - 'hash': 46260, - 'name': 'dummy_spine_02_jnt', - 'savables': {} - }, - 'dummy_spine_03_jnt_46266': { - 'hash': 46266, - 'name': 'dummy_spine_03_jnt', - 'savables': {} - }, - 'dummy_sternum_jnt_46252': { - 'hash': 46252, - 'name': 'dummy_sternum_jnt', - 'savables': {} - } - } - }, - 'Feather_Red_Training': { - 'hash': 80, - 'name': 'Feather Red Training', - 'embedded': { - 'Feather_Red_Training_74': { - 'hash': 74, - 'name': 'Feather Red Training', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Firebug': { - 'hash': 40478, - 'name': 'Firebug', - 'embedded': { - 'Firebug_38050': { - 'hash': 38050, - 'name': 'Firebug', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Firebug_AI_22350': { - 'hash': 22350, - 'name': 'Firebug AI', - 'savables': {} - }, - 'firebug_7558': { - 'hash': 7558, - 'name': 'firebug', - 'savables': {} - } - } - }, - 'Firework': { - 'hash': 40748, - 'name': 'Firework', - 'embedded': { - 'Explosion_58370': { - 'hash': 58370, - 'name': 'Explosion', - 'savables': { - 'ColoredExplosive': { - 'hash': 3920618075, - 'name': 'ColoredExplosive' - } - } - }, - 'Firework_40732': { - 'hash': 40732, - 'name': 'Firework', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'RaycastCrafter': { - 'hash': 2815374842, - 'name': 'RaycastCrafter' - } - } - }, - 'Fuse__15214': { - 'hash': 15214, - 'name': 'Fuse ', - 'savables': { - 'Fire': { - 'hash': 3457519710, - 'name': 'Fire' - }, - 'Fuse': { - 'hash': 3665939353, - 'name': 'Fuse' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Fixed_Light_Bag_Attachment': { - 'hash': 1056, - 'name': 'Fixed Light Bag Attachment', - 'embedded': { - 'Dock_62078': { - 'hash': 62078, - 'name': 'Dock', - 'savables': { - 'AdditionalOwnedDock': { - 'hash': 2592242915, - 'name': 'AdditionalOwnedDock' - } - } - }, - 'Fixed_Light_Bag_Attachment_7868': { - 'hash': 7868, - 'name': 'Fixed Light Bag Attachment', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Insert_Bag_Tool_Attachment_7796': { - 'hash': 7796, - 'name': 'Insert Bag Tool Attachment', - 'savables': {} - }, - 'Storage_38218': { - 'hash': 38218, - 'name': 'Storage', - 'savables': {} - }, - 'bag_lighting_attachment_pin_49786': { - 'hash': 49786, - 'name': 'bag_lighting_attachment_pin', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'bag_lighting_attachment_ropeWrap_01_49802': { - 'hash': 49802, - 'name': 'bag_lighting_attachment_ropeWrap_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'bag_lighting_attachment_ropeWrap_02_49798': { - 'hash': 49798, - 'name': 'bag_lighting_attachment_ropeWrap_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'bag_lighting_attachment_rope_01_49778': { - 'hash': 49778, - 'name': 'bag_lighting_attachment_rope_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'bag_lighting_attachment_rope_02_49774': { - 'hash': 49774, - 'name': 'bag_lighting_attachment_rope_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'bag_lighting_attachment_rope_03_49770': { - 'hash': 49770, - 'name': 'bag_lighting_attachment_rope_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'bag_lighting_attachment_stick_01_49794': { - 'hash': 49794, - 'name': 'bag_lighting_attachment_stick_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'bag_lighting_attachment_stick_02_49790': { - 'hash': 49790, - 'name': 'bag_lighting_attachment_stick_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'bag_lighting_attachment_stick_03_49782': { - 'hash': 49782, - 'name': 'bag_lighting_attachment_stick_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Flame_Step_Effect_Proto': { - 'hash': 24020, - 'name': 'Flame Step Effect Proto', - 'embedded': { - 'Flame_Step_Effect_Proto_26204': { - 'hash': 26204, - 'name': 'Flame Step Effect Proto', - 'savables': {} - }, - 'Heating_Bit_26176': { - 'hash': 26176, - 'name': 'Heating Bit', - 'savables': {} - }, - 'Hurting_Bit_26178': { - 'hash': 26178, - 'name': 'Hurting Bit', - 'savables': {} - } - } - }, - 'Flame_Step_Effect_Proto_Lava_Test_Long_Variant': { - 'hash': 54460, - 'name': 'Flame Step Effect Proto Lava Test Long Variant', - 'embedded': { - 'Flame_Step_Effect_Proto_Lava_Test_Long_Variant_63786': { - 'hash': 63786, - 'name': 'Flame Step Effect Proto Lava Test Long Variant', - 'savables': {} - }, - 'Heating_Bit_26176': { - 'hash': 26176, - 'name': 'Heating Bit', - 'savables': {} - }, - 'Hurting_Bit_26178': { - 'hash': 26178, - 'name': 'Hurting Bit', - 'savables': {} - } - } - }, - 'Flame_Step_Effect_Proto_Lava_Test_Variant': { - 'hash': 41226, - 'name': 'Flame Step Effect Proto Lava Test Variant', - 'embedded': { - 'Flame_Step_Effect_Proto_Lava_Test_Variant_63786': { - 'hash': 63786, - 'name': 'Flame Step Effect Proto Lava Test Variant', - 'savables': {} - }, - 'Heating_Bit_26176': { - 'hash': 26176, - 'name': 'Heating Bit', - 'savables': {} - }, - 'Hurting_Bit_26178': { - 'hash': 26178, - 'name': 'Hurting Bit', - 'savables': {} - } - } - }, - 'Flame_Step_Effect_Proto_Vent_test': { - 'hash': 5142, - 'name': 'Flame Step Effect Proto Vent test', - 'embedded': { - 'Flame_Step_Effect_Proto_Vent_test_10768': { - 'hash': 10768, - 'name': 'Flame Step Effect Proto Vent test', - 'savables': {} - }, - 'Heating_Bit_26176': { - 'hash': 26176, - 'name': 'Heating Bit', - 'savables': {} - }, - 'Hurting_Bit_26178': { - 'hash': 26178, - 'name': 'Hurting Bit', - 'savables': {} - } - } - }, - 'Flaming_Coalbed': { - 'hash': 13480, - 'name': 'Flaming Coalbed', - 'embedded': { - 'Flaming_Coalbed_26204': { - 'hash': 26204, - 'name': 'Flaming Coalbed', - 'savables': {} - }, - 'Heating_Bit_26176': { - 'hash': 26176, - 'name': 'Heating Bit', - 'savables': {} - }, - 'Hurting_Bit_26178': { - 'hash': 26178, - 'name': 'Hurting Bit', - 'savables': {} - } - } - }, - 'Flashlight_Lantern': { - 'hash': 23642, - 'name': 'Flashlight Lantern', - 'embedded': { - 'Fire_54948': { - 'hash': 54948, - 'name': 'Fire', - 'savables': { - 'Fire': { - 'hash': 3457519710, - 'name': 'Fire' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Flashlight_Lantern_23664': { - 'hash': 23664, - 'name': 'Flashlight Lantern', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Fuel_Dock_63110': { - 'hash': 63110, - 'name': 'Fuel Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'flashlight_body_63430': { - 'hash': 63430, - 'name': 'flashlight_body', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'flashlight_body_pin_01_63422': { - 'hash': 63422, - 'name': 'flashlight_body_pin_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'flashlight_body_pin_02_63418': { - 'hash': 63418, - 'name': 'flashlight_body_pin_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'flashlight_body_pin_03_63414': { - 'hash': 63414, - 'name': 'flashlight_body_pin_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'flashlight_focusCylinder_63410': { - 'hash': 63410, - 'name': 'flashlight_focusCylinder', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'flashlight_fuelDoor_axel_63402': { - 'hash': 63402, - 'name': 'flashlight_fuelDoor_axel', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'flashlight_fuelDoor_body_63398': { - 'hash': 63398, - 'name': 'flashlight_fuelDoor_body', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'flashlight_handle_body_63394': { - 'hash': 63394, - 'name': 'flashlight_handle_body', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'flashlight_handle_pin_01_63390': { - 'hash': 63390, - 'name': 'flashlight_handle_pin_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'flashlight_handle_pin_02_63426': { - 'hash': 63426, - 'name': 'flashlight_handle_pin_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'flashlight_handle_wraps_63406': { - 'hash': 63406, - 'name': 'flashlight_handle_wraps', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Flint': { - 'hash': 39484, - 'name': 'Flint', - 'embedded': { - 'Flint_39368': { - 'hash': 39368, - 'name': 'Flint', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Insert_Primitive_SwordType_7796': { - 'hash': 7796, - 'name': 'Insert Primitive SwordType', - 'savables': {} - } - } - }, - 'Flint_Training': { - 'hash': 2356, - 'name': 'Flint Training', - 'embedded': { - 'Flint_Training_2350': { - 'hash': 2350, - 'name': 'Flint Training', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Float_Range_Operator': { - 'hash': 50768, - 'name': 'Float Range Operator', - 'embedded': { - 'Float_Range_Operator_13344': { - 'hash': 13344, - 'name': 'Float Range Operator', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'LogicFloatRangeReceiver': { - 'hash': 2700376822, - 'name': 'LogicFloatRangeReceiver' - } - } - } - } - }, - 'Flower_Blue': { - 'hash': 23514, - 'name': 'Flower Blue', - 'embedded': { - 'Flower_Blue_28136': { - 'hash': 28136, - 'name': 'Flower Blue', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Flower_Red': { - 'hash': 61634, - 'name': 'Flower Red', - 'embedded': { - 'Flower_Red_27280': { - 'hash': 27280, - 'name': 'Flower Red', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'FlyCam_Player': { - 'hash': 44058, - 'name': 'FlyCam_Player', - 'embedded': {} - }, - 'Forage_Basket_Bag': { - 'hash': 39880, - 'name': 'Forage Basket Bag', - 'embedded': { - 'Bag_Body_42972': { - 'hash': 42972, - 'name': 'Bag Body', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Dock_BL_42978': { - 'hash': 42978, - 'name': 'Dock BL', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_BM_42976': { - 'hash': 42976, - 'name': 'Dock BM', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_BR_42974': { - 'hash': 42974, - 'name': 'Dock BR', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_ML_42984': { - 'hash': 42984, - 'name': 'Dock ML', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_MM_42982': { - 'hash': 42982, - 'name': 'Dock MM', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_MR_42980': { - 'hash': 42980, - 'name': 'Dock MR', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_TL_42990': { - 'hash': 42990, - 'name': 'Dock TL', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_TM_42988': { - 'hash': 42988, - 'name': 'Dock TM', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_TR_42986': { - 'hash': 42986, - 'name': 'Dock TR', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Forage_Basket_Bag_43012': { - 'hash': 43012, - 'name': 'Forage Basket Bag', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_Bag_Attach_30776': { - 'hash': 30776, - 'name': 'Slot Bag Attach', - 'savables': {} - }, - 'Slot_Bag_Attach_55164': { - 'hash': 55164, - 'name': 'Slot Bag Attach', - 'savables': {} - }, - 'basket_bag_handle_wraps_56574': { - 'hash': 56574, - 'name': 'basket_bag_handle_wraps', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_bottomStick_01_56570': { - 'hash': 56570, - 'name': 'basket_bottomStick_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_bottomStick_02_56610': { - 'hash': 56610, - 'name': 'basket_bottomStick_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_bottomStick_03_56558': { - 'hash': 56558, - 'name': 'basket_bottomStick_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_bottomStick_04_56618': { - 'hash': 56618, - 'name': 'basket_bottomStick_04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_bottomStick_05_56614': { - 'hash': 56614, - 'name': 'basket_bottomStick_05', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_handle_56602': { - 'hash': 56602, - 'name': 'basket_handle', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_outerPillar_01_56554': { - 'hash': 56554, - 'name': 'basket_outerPillar_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_outerPillar_02_56566': { - 'hash': 56566, - 'name': 'basket_outerPillar_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_outerPillar_03_56622': { - 'hash': 56622, - 'name': 'basket_outerPillar_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_outerPillar_04_56550': { - 'hash': 56550, - 'name': 'basket_outerPillar_04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_outerPillar_05_56590': { - 'hash': 56590, - 'name': 'basket_outerPillar_05', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_rim_01_56598': { - 'hash': 56598, - 'name': 'basket_rim_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_rim_02_56578': { - 'hash': 56578, - 'name': 'basket_rim_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_rim_03_56562': { - 'hash': 56562, - 'name': 'basket_rim_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_thatch_body_56594': { - 'hash': 56594, - 'name': 'basket_thatch_body', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_topStick_01_56546': { - 'hash': 56546, - 'name': 'basket_topStick_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_topStick_02_56606': { - 'hash': 56606, - 'name': 'basket_topStick_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_topStick_03_56534': { - 'hash': 56534, - 'name': 'basket_topStick_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_topStick_04_56586': { - 'hash': 56586, - 'name': 'basket_topStick_04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_topStick_05_56538': { - 'hash': 56538, - 'name': 'basket_topStick_05', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_topStick_06_56582': { - 'hash': 56582, - 'name': 'basket_topStick_06', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_top_rim_56542': { - 'hash': 56542, - 'name': 'basket_top_rim', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Forage_Side_Pouch_Attachment': { - 'hash': 32874, - 'name': 'Forage Side Pouch Attachment', - 'embedded': { - 'Dock_45700': { - 'hash': 45700, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62078': { - 'hash': 62078, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Forage_Side_Pouch_Attachment_7868': { - 'hash': 7868, - 'name': 'Forage Side Pouch Attachment', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Insert_Bag_Attach_7796': { - 'hash': 7796, - 'name': 'Insert Bag Attach', - 'savables': {} - }, - 'Storage_62414': { - 'hash': 62414, - 'name': 'Storage', - 'savables': {} - }, - 'forage_basket_attachment_cover_27470': { - 'hash': 27470, - 'name': 'forage_basket_attachment_cover', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'forage_basket_attachment_knot_01_27466': { - 'hash': 27466, - 'name': 'forage_basket_attachment_knot_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'forage_basket_attachment_stick_01_30790': { - 'hash': 30790, - 'name': 'forage_basket_attachment_stick_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'forage_basket_attachment_stick_02_30786': { - 'hash': 30786, - 'name': 'forage_basket_attachment_stick_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'forage_basket_rim_01_30798': { - 'hash': 30798, - 'name': 'forage_basket_rim_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'forage_basket_rim_02_30794': { - 'hash': 30794, - 'name': 'forage_basket_rim_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Forest_Chunk_Point_Generator': { - 'hash': 45732, - 'name': 'Forest Chunk Point Generator', - 'embedded': { - 'Forest_Chunk_Point_Generator_16642': { - 'hash': 16642, - 'name': 'Forest Chunk Point Generator', - 'savables': {} - } - } - }, - 'Forest_Population': { - 'hash': 18818, - 'name': 'Forest Population', - 'embedded': { - 'Forest_Population_16642': { - 'hash': 16642, - 'name': 'Forest Population', - 'savables': { - 'BasicPopulationFolder': { - 'hash': 1931537627, - 'name': 'BasicPopulationFolder' - } - } - } - } - }, - 'Forge': { - 'hash': 11872, - 'name': 'Forge', - 'embedded': { - 'Fire_30100': { - 'hash': 30100, - 'name': 'Fire', - 'savables': { - 'Fire': { - 'hash': 3457519710, - 'name': 'Fire' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Forge_61848': { - 'hash': 61848, - 'name': 'Forge', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - }, - 'Forge_Area_43486': { - 'hash': 43486, - 'name': 'Forge_Area', - 'savables': {} - } - } - }, - 'Forge_Training': { - 'hash': 33628, - 'name': 'Forge Training', - 'embedded': { - 'Forge_Training_31154': { - 'hash': 31154, - 'name': 'Forge Training', - 'savables': {} - }, - 'Heat_Area_43486': { - 'hash': 43486, - 'name': 'Heat Area', - 'savables': {} - } - } - }, - 'Friend_Request_Token': { - 'hash': 15314, - 'name': 'Friend_Request_Token', - 'embedded': {} - }, - 'Fruit_Tree_Path': { - 'hash': 40982, - 'name': 'Fruit Tree Path', - 'embedded': { - 'Fruit_Tree_Path_54338': { - 'hash': 54338, - 'name': 'Fruit Tree Path', - 'savables': { - 'PopulationPath': { - 'hash': 7704646, - 'name': 'PopulationPath' - } - } - } - } - }, - 'Gacha_Handle_': { - 'hash': 34422, - 'name': 'Gacha Handle ', - 'embedded': { - 'Gacha_Handle__58484': { - 'hash': 58484, - 'name': 'Gacha Handle ', - 'savables': {} - }, - 'Handle_Pickup_13422': { - 'hash': 13422, - 'name': 'Handle Pickup', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Garlic_Full_Burnt': { - 'hash': 52934, - 'name': 'Garlic Full Burnt', - 'embedded': { - 'Cooking_64222': { - 'hash': 64222, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Garlic_Full_Burnt_52596': { - 'hash': 52596, - 'name': 'Garlic Full Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Garlic_Full_Cooked': { - 'hash': 52530, - 'name': 'Garlic Full Cooked', - 'embedded': { - 'Cooking_63850': { - 'hash': 63850, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Garlic_Full_Cooked_52192': { - 'hash': 52192, - 'name': 'Garlic Full Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Garlic_Full_Ripe': { - 'hash': 52126, - 'name': 'Garlic Full Ripe', - 'embedded': { - 'Cooking_61942': { - 'hash': 61942, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Garlic_Full_Ripe_49740': { - 'hash': 49740, - 'name': 'Garlic Full Ripe', - 'savables': { - 'BuildupPickup': { - 'hash': 3373651539, - 'name': 'BuildupPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Leaves_Parent_41624': { - 'hash': 41624, - 'name': 'Leaves Parent', - 'savables': {} - }, - 'Root_Parent_41626': { - 'hash': 41626, - 'name': 'Root Parent', - 'savables': {} - } - } - }, - 'Garlic_Full_Unripe': { - 'hash': 49162, - 'name': 'Garlic Full Unripe', - 'embedded': { - 'Cooking_61546': { - 'hash': 61546, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Garlic_Full_Unripe_48792': { - 'hash': 48792, - 'name': 'Garlic Full Unripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Garlic_Half_Burnt': { - 'hash': 60930, - 'name': 'Garlic Half Burnt', - 'embedded': { - 'Cooking_36210': { - 'hash': 36210, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Garlic_Half_Burnt_60592': { - 'hash': 60592, - 'name': 'Garlic Half Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Garlic_Half_Cooked': { - 'hash': 60526, - 'name': 'Garlic Half Cooked', - 'embedded': { - 'Cooking_35152': { - 'hash': 35152, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Garlic_Half_Cooked_60188': { - 'hash': 60188, - 'name': 'Garlic Half Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Garlic_Half_Ripe': { - 'hash': 60122, - 'name': 'Garlic Half Ripe', - 'embedded': { - 'Cooking_34454': { - 'hash': 34454, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Garlic_Half_Ripe_59784': { - 'hash': 59784, - 'name': 'Garlic Half Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Garlic_Half_Unripe': { - 'hash': 59718, - 'name': 'Garlic Half Unripe', - 'embedded': { - 'Cooking_34116': { - 'hash': 34116, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Garlic_Half_Unripe_59380': { - 'hash': 59380, - 'name': 'Garlic Half Unripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Garlic_Leaves': { - 'hash': 1266, - 'name': 'Garlic Leaves', - 'embedded': { - 'Garlic_Leaves_57126': { - 'hash': 57126, - 'name': 'Garlic Leaves', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'PullPickup_32134': { - 'hash': 32134, - 'name': 'PullPickup', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Garlic_Roots': { - 'hash': 57564, - 'name': 'Garlic Roots', - 'embedded': { - 'Garlic_Roots_34536': { - 'hash': 34536, - 'name': 'Garlic Roots', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'PullPickup_32134': { - 'hash': 32134, - 'name': 'PullPickup', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Geode_Tier_1': { - 'hash': 59336, - 'name': 'Geode Tier 1', - 'embedded': { - 'Geode_Tier_1_56136': { - 'hash': 56136, - 'name': 'Geode Tier 1', - 'savables': { - 'MultiHandPickup': { - 'hash': 1556697998, - 'name': 'MultiHandPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Geode_Tier_1_Half_01': { - 'hash': 29678, - 'name': 'Geode Tier 1 Half 01', - 'embedded': { - 'Geode_Tier_1_Half_01_26864': { - 'hash': 26864, - 'name': 'Geode Tier 1 Half 01', - 'savables': { - 'MultiHandPickup': { - 'hash': 1556697998, - 'name': 'MultiHandPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Geode_Tier_1_Half_02': { - 'hash': 38512, - 'name': 'Geode Tier 1 Half 02', - 'embedded': { - 'Geode_Tier_1_Half_02_35456': { - 'hash': 35456, - 'name': 'Geode Tier 1 Half 02', - 'savables': { - 'MultiHandPickup': { - 'hash': 1556697998, - 'name': 'MultiHandPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Gift_Mail_Box': { - 'hash': 56348, - 'name': 'Gift Mail Box', - 'embedded': { - 'Gift_Mail_Box_17050': { - 'hash': 17050, - 'name': 'Gift Mail Box', - 'savables': { - 'MultiHandPickup': { - 'hash': 1556697998, - 'name': 'MultiHandPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'SentGift': { - 'hash': 661497638, - 'name': 'SentGift' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Glowing_Mushroom_Recipe_Burnt_Stew': { - 'hash': 47384, - 'name': 'Glowing_Mushroom_Recipe_Burnt_Stew', - 'embedded': {} - }, - 'Glowing_Mushroom_Recipe_Cooked_Stew': { - 'hash': 47362, - 'name': 'Glowing_Mushroom_Recipe_Cooked_Stew', - 'embedded': {} - }, - 'Glowing_Mushroom_Recipe_Raw_Stew': { - 'hash': 44774, - 'name': 'Glowing_Mushroom_Recipe_Raw_Stew', - 'embedded': {} - }, - 'GoldCoin': { - 'hash': 61648, - 'name': 'GoldCoin', - 'embedded': { - 'GoldCoin_39174': { - 'hash': 39174, - 'name': 'GoldCoin', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_12524': { - 'hash': 12524, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Gold_Boulder': { - 'hash': 2584, - 'name': 'Gold Boulder', - 'embedded': { - 'Gold_Boulder_3932': { - 'hash': 3932, - 'name': 'Gold Boulder', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Spawn_Origin_7418': { - 'hash': 7418, - 'name': 'Spawn Origin', - 'savables': {} - } - } - }, - 'Gold_Boulder_Parts': { - 'hash': 47738, - 'name': 'Gold_Boulder_Parts', - 'embedded': { - 'Gold_Boulder_Part_01_52930': { - 'hash': 52930, - 'name': 'Gold_Boulder_Part_01', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Gold_Boulder_Part_02_52926': { - 'hash': 52926, - 'name': 'Gold_Boulder_Part_02', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Gold_Boulder_Part_03_52922': { - 'hash': 52922, - 'name': 'Gold_Boulder_Part_03', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Gold_Boulder_Part_04_52934': { - 'hash': 52934, - 'name': 'Gold_Boulder_Part_04', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Gold_Boulder_Parts_52902': { - 'hash': 52902, - 'name': 'Gold_Boulder_Parts', - 'savables': {} - } - } - }, - 'Gold_Ingot': { - 'hash': 30092, - 'name': 'Gold Ingot', - 'embedded': { - 'Gold_Ingot_29980': { - 'hash': 29980, - 'name': 'Gold Ingot', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_13048': { - 'hash': 13048, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - } - } - }, - 'Gold_Ore': { - 'hash': 61650, - 'name': 'Gold Ore', - 'embedded': { - 'Gold_Ore_39896': { - 'hash': 39896, - 'name': 'Gold Ore', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Gotera': { - 'hash': 9466, - 'name': 'Gotera', - 'embedded': { - 'Dart_Shooter_56642': { - 'hash': 56642, - 'name': 'Dart Shooter', - 'savables': {} - }, - 'Erupt_Area_19858': { - 'hash': 19858, - 'name': 'Erupt Area', - 'savables': {} - }, - 'Gotera_7278': { - 'hash': 7278, - 'name': 'Gotera', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Gotera_AI_22350': { - 'hash': 22350, - 'name': 'Gotera AI', - 'savables': {} - }, - 'Gotera_Body_10036': { - 'hash': 10036, - 'name': 'Gotera Body', - 'savables': {} - }, - 'Impactor_63610': { - 'hash': 63610, - 'name': 'Impactor', - 'savables': {} - }, - 'Physical_Torso_8164': { - 'hash': 8164, - 'name': 'Physical Torso', - 'savables': {} - }, - 'Seed_Spray_1172': { - 'hash': 1172, - 'name': 'Seed Spray', - 'savables': {} - }, - 'Spawn_Drop_16220': { - 'hash': 16220, - 'name': 'Spawn Drop', - 'savables': {} - }, - 'root_jnt_17218': { - 'hash': 17218, - 'name': 'root_jnt', - 'savables': {} - } - } - }, - 'Gotera_Ash_Bomb': { - 'hash': 56764, - 'name': 'Gotera Ash Bomb', - 'embedded': { - 'AI_16472': { - 'hash': 16472, - 'name': 'AI', - 'savables': {} - }, - 'Explosion_7834': { - 'hash': 7834, - 'name': 'Explosion', - 'savables': {} - }, - 'Gotera_Ash_Bomb_40780': { - 'hash': 40780, - 'name': 'Gotera Ash Bomb', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Gotera_Ash_Variant': { - 'hash': 61448, - 'name': 'Gotera Ash Variant', - 'embedded': { - 'Dart_Shooter_6022': { - 'hash': 6022, - 'name': 'Dart Shooter', - 'savables': {} - }, - 'Erupt_Area_19858': { - 'hash': 19858, - 'name': 'Erupt Area', - 'savables': {} - }, - 'Gotera_AI_22350': { - 'hash': 22350, - 'name': 'Gotera AI', - 'savables': {} - }, - 'Gotera_Ash_Variant_7278': { - 'hash': 7278, - 'name': 'Gotera Ash Variant', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Gotera_Body_10036': { - 'hash': 10036, - 'name': 'Gotera Body', - 'savables': {} - }, - 'Impactor_63610': { - 'hash': 63610, - 'name': 'Impactor', - 'savables': {} - }, - 'Physical_Torso_8164': { - 'hash': 8164, - 'name': 'Physical Torso', - 'savables': {} - }, - 'Seed_Spray_1172': { - 'hash': 1172, - 'name': 'Seed Spray', - 'savables': {} - }, - 'Spawn_Drop_16220': { - 'hash': 16220, - 'name': 'Spawn Drop', - 'savables': {} - }, - 'root_jnt_17218': { - 'hash': 17218, - 'name': 'root_jnt', - 'savables': {} - } - } - }, - 'Gotera_Big_Dart': { - 'hash': 26780, - 'name': 'Gotera Big Dart', - 'embedded': { - 'Dart_62940': { - 'hash': 62940, - 'name': 'Dart', - 'savables': {} - }, - 'Gotera_Big_Dart_3092': { - 'hash': 3092, - 'name': 'Gotera Big Dart', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Gotera_Big_Seed_Spray': { - 'hash': 18468, - 'name': 'Gotera Big Seed Spray', - 'embedded': { - 'Gotera_Big_Seed_Spray_44772': { - 'hash': 44772, - 'name': 'Gotera Big Seed Spray', - 'savables': {} - } - } - }, - 'Gotera_Birch_Variant': { - 'hash': 2370, - 'name': 'Gotera Birch Variant', - 'embedded': { - 'Dart_Shooter_6022': { - 'hash': 6022, - 'name': 'Dart Shooter', - 'savables': {} - }, - 'Erupt_Area_19858': { - 'hash': 19858, - 'name': 'Erupt Area', - 'savables': {} - }, - 'Gotera_AI_22350': { - 'hash': 22350, - 'name': 'Gotera AI', - 'savables': {} - }, - 'Gotera_Birch_Variant_7278': { - 'hash': 7278, - 'name': 'Gotera Birch Variant', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Gotera_Body_10036': { - 'hash': 10036, - 'name': 'Gotera Body', - 'savables': {} - }, - 'Impactor_63610': { - 'hash': 63610, - 'name': 'Impactor', - 'savables': {} - }, - 'Physical_Torso_8164': { - 'hash': 8164, - 'name': 'Physical Torso', - 'savables': {} - }, - 'Seed_Spray_1172': { - 'hash': 1172, - 'name': 'Seed Spray', - 'savables': {} - }, - 'Spawn_Drop_16220': { - 'hash': 16220, - 'name': 'Spawn Drop', - 'savables': {} - }, - 'root_jnt_17218': { - 'hash': 17218, - 'name': 'root_jnt', - 'savables': {} - } - } - }, - 'Gotera_Dart': { - 'hash': 3088, - 'name': 'Gotera Dart', - 'embedded': { - 'Dart_62940': { - 'hash': 62940, - 'name': 'Dart', - 'savables': {} - }, - 'Gotera_Dart_3092': { - 'hash': 3092, - 'name': 'Gotera Dart', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Gotera_Redwood_Variant': { - 'hash': 27128, - 'name': 'Gotera Redwood Variant', - 'embedded': { - 'Dart_Shooter_56642': { - 'hash': 56642, - 'name': 'Dart Shooter', - 'savables': {} - }, - 'Erupt_Area_19858': { - 'hash': 19858, - 'name': 'Erupt Area', - 'savables': {} - }, - 'Gotera_AI_22350': { - 'hash': 22350, - 'name': 'Gotera AI', - 'savables': {} - }, - 'Gotera_Body_10036': { - 'hash': 10036, - 'name': 'Gotera Body', - 'savables': {} - }, - 'Gotera_Redwood_Variant_7278': { - 'hash': 7278, - 'name': 'Gotera Redwood Variant', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Impactor_19042': { - 'hash': 19042, - 'name': 'Impactor', - 'savables': {} - }, - 'Impactor_19160': { - 'hash': 19160, - 'name': 'Impactor', - 'savables': {} - }, - 'Impactor_63610': { - 'hash': 63610, - 'name': 'Impactor', - 'savables': {} - }, - 'Physical_Torso_8164': { - 'hash': 8164, - 'name': 'Physical Torso', - 'savables': {} - }, - 'Seed_Spray_1172': { - 'hash': 1172, - 'name': 'Seed Spray', - 'savables': {} - }, - 'Spawn_Drop_16220': { - 'hash': 16220, - 'name': 'Spawn Drop', - 'savables': {} - }, - 'root_jnt_17218': { - 'hash': 17218, - 'name': 'root_jnt', - 'savables': {} - } - } - }, - 'Gotera_Seed_Spray': { - 'hash': 31540, - 'name': 'Gotera Seed Spray', - 'embedded': { - 'Gotera_Seed_Spray_44772': { - 'hash': 44772, - 'name': 'Gotera Seed Spray', - 'savables': {} - } - } - }, - 'Gotera_Seedling_Orb': { - 'hash': 59342, - 'name': 'Gotera Seedling Orb', - 'embedded': { - 'Gotera_Seedling_Orb_59268': { - 'hash': 59268, - 'name': 'Gotera Seedling Orb', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Stun_Explosion_58370': { - 'hash': 58370, - 'name': 'Stun Explosion', - 'savables': {} - } - } - }, - 'Gotera_Walnut_Bomb': { - 'hash': 35174, - 'name': 'Gotera Walnut Bomb', - 'embedded': { - 'Explosion_7834': { - 'hash': 7834, - 'name': 'Explosion', - 'savables': {} - }, - 'Gotera_Walnut_Bomb_40780': { - 'hash': 40780, - 'name': 'Gotera Walnut Bomb', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Gotera_Walnut_Variant': { - 'hash': 38096, - 'name': 'Gotera Walnut Variant', - 'embedded': { - 'Big_Dart_Shooter_(1)_4010': { - 'hash': 4010, - 'name': 'Big Dart Shooter (1)', - 'savables': {} - }, - 'Big_Dart_Shooter_(2)_4572': { - 'hash': 4572, - 'name': 'Big Dart Shooter (2)', - 'savables': {} - }, - 'Big_Dart_Shooter_5974': { - 'hash': 5974, - 'name': 'Big Dart Shooter', - 'savables': {} - }, - 'Dart_Shooter_(1)_37542': { - 'hash': 37542, - 'name': 'Dart Shooter (1)', - 'savables': {} - }, - 'Dart_Shooter_56642': { - 'hash': 56642, - 'name': 'Dart Shooter', - 'savables': {} - }, - 'Dart_Shooter_5986': { - 'hash': 5986, - 'name': 'Dart Shooter', - 'savables': {} - }, - 'Dart_Shooter_5998': { - 'hash': 5998, - 'name': 'Dart Shooter', - 'savables': {} - }, - 'Dart_Shooter_6010': { - 'hash': 6010, - 'name': 'Dart Shooter', - 'savables': {} - }, - 'Dart_Shooter_6022': { - 'hash': 6022, - 'name': 'Dart Shooter', - 'savables': {} - }, - 'Erupt_Area_19858': { - 'hash': 19858, - 'name': 'Erupt Area', - 'savables': {} - }, - 'Gotera_AI_22350': { - 'hash': 22350, - 'name': 'Gotera AI', - 'savables': {} - }, - 'Gotera_Body_10036': { - 'hash': 10036, - 'name': 'Gotera Body', - 'savables': {} - }, - 'Gotera_Walnut_Variant_7278': { - 'hash': 7278, - 'name': 'Gotera Walnut Variant', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Impactor_63610': { - 'hash': 63610, - 'name': 'Impactor', - 'savables': {} - }, - 'Physical_Torso_8164': { - 'hash': 8164, - 'name': 'Physical Torso', - 'savables': {} - }, - 'Seed_Spray_1172': { - 'hash': 1172, - 'name': 'Seed Spray', - 'savables': {} - }, - 'Spawn_Drop_16220': { - 'hash': 16220, - 'name': 'Spawn Drop', - 'savables': {} - }, - 'root_jnt_17218': { - 'hash': 17218, - 'name': 'root_jnt', - 'savables': {} - } - } - }, - 'Gourd_Canteen': { - 'hash': 29032, - 'name': 'Gourd Canteen', - 'embedded': { - 'Gourd_Canteen_26784': { - 'hash': 26784, - 'name': 'Gourd Canteen', - 'savables': { - 'LiquidContainer': { - 'hash': 4179293747, - 'name': 'LiquidContainer' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Lid_Pickup_27480': { - 'hash': 27480, - 'name': 'Lid Pickup', - 'savables': { - 'CapPickup': { - 'hash': 3082855726, - 'name': 'CapPickup' - } - } - } - } - }, - 'Grass_Clump': { - 'hash': 57872, - 'name': 'Grass Clump', - 'embedded': { - 'Fire_30100': { - 'hash': 30100, - 'name': 'Fire', - 'savables': { - 'Fire': { - 'hash': 3457519710, - 'name': 'Fire' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Grass_Clump_12138': { - 'hash': 12138, - 'name': 'Grass Clump', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'RaycastCrafter': { - 'hash': 2815374842, - 'name': 'RaycastCrafter' - } - } - }, - 'Insert_Grass_7796': { - 'hash': 7796, - 'name': 'Insert Grass', - 'savables': {} - } - } - }, - 'Gravestone_Parts': { - 'hash': 2596, - 'name': 'Gravestone Parts', - 'embedded': { - 'Gravestone_Parts_37752': { - 'hash': 37752, - 'name': 'Gravestone Parts', - 'savables': {} - }, - 'gravestone_base_LOD0_1602': { - 'hash': 1602, - 'name': 'gravestone_base_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'gravestone_brick_type1_LOD0_1578': { - 'hash': 1578, - 'name': 'gravestone_brick_type1_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'gravestone_brick_type1_LOD0_1596': { - 'hash': 1596, - 'name': 'gravestone_brick_type1_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'gravestone_brick_type1_LOD0_1604': { - 'hash': 1604, - 'name': 'gravestone_brick_type1_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'gravestone_brick_type1_LOD0_1608': { - 'hash': 1608, - 'name': 'gravestone_brick_type1_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'gravestone_brick_type2_LOD0_1590': { - 'hash': 1590, - 'name': 'gravestone_brick_type2_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'gravestone_brick_type2_LOD0_1606': { - 'hash': 1606, - 'name': 'gravestone_brick_type2_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'gravestone_brick_type2_LOD0_1610': { - 'hash': 1610, - 'name': 'gravestone_brick_type2_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'gravestone_brick_type2_LOD0_1614': { - 'hash': 1614, - 'name': 'gravestone_brick_type2_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'gravestone_brick_type3_LOD0_1572': { - 'hash': 1572, - 'name': 'gravestone_brick_type3_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'gravestone_brick_type3_LOD0_1594': { - 'hash': 1594, - 'name': 'gravestone_brick_type3_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'gravestone_brick_type3_LOD0_1600': { - 'hash': 1600, - 'name': 'gravestone_brick_type3_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'gravestone_brick_type3_LOD0_1612': { - 'hash': 1612, - 'name': 'gravestone_brick_type3_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'gravestone_brick_type4_LOD0_1576': { - 'hash': 1576, - 'name': 'gravestone_brick_type4_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'gravestone_brick_type4_LOD0_1582': { - 'hash': 1582, - 'name': 'gravestone_brick_type4_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'gravestone_brick_type4_LOD0_1586': { - 'hash': 1586, - 'name': 'gravestone_brick_type4_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'gravestone_spike_large_LOD0_1580': { - 'hash': 1580, - 'name': 'gravestone_spike_large_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'gravestone_spike_large_LOD0_1588': { - 'hash': 1588, - 'name': 'gravestone_spike_large_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'gravestone_spike_large_LOD0_1598': { - 'hash': 1598, - 'name': 'gravestone_spike_large_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'gravestone_spike_small_LOD0_1584': { - 'hash': 1584, - 'name': 'gravestone_spike_small_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'gravestone_spike_small_LOD0_1592': { - 'hash': 1592, - 'name': 'gravestone_spike_small_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'gravestone_torus_LOD0_1574': { - 'hash': 1574, - 'name': 'gravestone_torus_LOD0', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Great_Sword_Blade': { - 'hash': 63886, - 'name': 'Great Sword Blade', - 'embedded': { - 'Great_Sword_Blade_84': { - 'hash': 84, - 'name': 'Great Sword Blade', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_62004': { - 'hash': 62004, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_Large_SwordType_7796': { - 'hash': 7796, - 'name': 'Insert Large SwordType', - 'savables': {} - }, - 'metal_blade_greatsword_full_geo_LOD0_60392': { - 'hash': 60392, - 'name': 'metal_blade_greatsword_full_geo_LOD0', - 'savables': {} - } - } - }, - 'Greater_Gotera_Charge_Explosion': { - 'hash': 5316, - 'name': 'Greater Gotera Charge Explosion', - 'embedded': { - 'Greater_Gotera_Charge_Explosion_58370': { - 'hash': 58370, - 'name': 'Greater Gotera Charge Explosion', - 'savables': {} - } - } - }, - 'Greater_Gotera_Seed_Spray': { - 'hash': 13476, - 'name': 'Greater Gotera Seed Spray', - 'embedded': { - 'Greater_Gotera_Seed_Spray_44772': { - 'hash': 44772, - 'name': 'Greater Gotera Seed Spray', - 'savables': {} - } - } - }, - 'Green_Crystal_cluster_03': { - 'hash': 23836, - 'name': 'Green_Crystal_cluster_03', - 'embedded': { - 'Green_Crystal_cluster_03_54542': { - 'hash': 54542, - 'name': 'Green_Crystal_cluster_03', - 'savables': {} - } - } - }, - 'Guard': { - 'hash': 51672, - 'name': 'Guard', - 'embedded': { - 'Guard_51546': { - 'hash': 51546, - 'name': 'Guard', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_56294': { - 'hash': 56294, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_SwordType_Craft_39368': { - 'hash': 39368, - 'name': 'Insert SwordType Craft', - 'savables': {} - }, - 'Slot_SwordType_39370': { - 'hash': 39370, - 'name': 'Slot SwordType', - 'savables': {} - } - } - }, - 'Guard_Fancy': { - 'hash': 62140, - 'name': 'Guard Fancy', - 'embedded': { - 'Guard_Fancy_51546': { - 'hash': 51546, - 'name': 'Guard Fancy', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_56592': { - 'hash': 56592, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_SwordType_Deco_39368': { - 'hash': 39368, - 'name': 'Insert SwordType Deco', - 'savables': {} - }, - 'Slot_SwordType_39370': { - 'hash': 39370, - 'name': 'Slot SwordType', - 'savables': {} - } - } - }, - 'Guard_Handle': { - 'hash': 43186, - 'name': 'Guard Handle', - 'embedded': { - 'Guard_Handle_51546': { - 'hash': 51546, - 'name': 'Guard Handle', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Insert_Mid_39368': { - 'hash': 39368, - 'name': 'Insert Mid', - 'savables': {} - }, - 'Slot_End_39370': { - 'hash': 39370, - 'name': 'Slot End', - 'savables': {} - } - } - }, - 'Guard_Hemisphere': { - 'hash': 34428, - 'name': 'Guard Hemisphere', - 'embedded': { - 'Guard_Hemisphere_51546': { - 'hash': 51546, - 'name': 'Guard Hemisphere', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_56886': { - 'hash': 56886, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_SwordType_Deco_39368': { - 'hash': 39368, - 'name': 'Insert SwordType Deco', - 'savables': {} - }, - 'Slot_SwordType_39370': { - 'hash': 39370, - 'name': 'Slot SwordType', - 'savables': {} - } - } - }, - 'Guard_Pointy_Ends': { - 'hash': 28160, - 'name': 'Guard Pointy Ends', - 'embedded': { - 'Guard_Pointy_Ends_51546': { - 'hash': 51546, - 'name': 'Guard Pointy Ends', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_57188': { - 'hash': 57188, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_SwordType_Craft_39368': { - 'hash': 39368, - 'name': 'Insert SwordType Craft', - 'savables': {} - }, - 'Slot_Multi_31108': { - 'hash': 31108, - 'name': 'Slot Multi', - 'savables': {} - } - } - }, - 'Guard_Round_Ends': { - 'hash': 21776, - 'name': 'Guard Round Ends', - 'embedded': { - 'Guard_Round_Ends_51546': { - 'hash': 51546, - 'name': 'Guard Round Ends', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Insert_Mid_39368': { - 'hash': 39368, - 'name': 'Insert Mid', - 'savables': {} - }, - 'Slot_End_39370': { - 'hash': 39370, - 'name': 'Slot End', - 'savables': {} - } - } - }, - 'Guard_Straight_Ends': { - 'hash': 17348, - 'name': 'Guard Straight Ends', - 'embedded': { - 'Guard_Straight_Ends_51546': { - 'hash': 51546, - 'name': 'Guard Straight Ends', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_57430': { - 'hash': 57430, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_SwordType_Craft_39368': { - 'hash': 39368, - 'name': 'Insert SwordType Craft', - 'savables': {} - }, - 'Slot_Multi_30024': { - 'hash': 30024, - 'name': 'Slot Multi', - 'savables': {} - } - } - }, - 'Gymnasium_Prefab_Spawner': { - 'hash': 25312, - 'name': 'Gymnasium Prefab Spawner', - 'embedded': { - 'Gymnasium_Prefab_Spawner_25334': { - 'hash': 25334, - 'name': 'Gymnasium Prefab Spawner', - 'savables': { - 'GymnasiumOnDemandPrefabSpawner': { - 'hash': 701033518, - 'name': 'GymnasiumOnDemandPrefabSpawner' - } - } - }, - 'Spawn_Area_4162': { - 'hash': 4162, - 'name': 'Spawn Area', - 'savables': { - 'SpawnArea': { - 'hash': 2617495528, - 'name': 'SpawnArea' - } - } - } - } - }, - 'Gymnasium_Teleport_Tablet': { - 'hash': 2718, - 'name': 'Gymnasium Teleport Tablet', - 'embedded': { - 'Collision_27112': { - 'hash': 27112, - 'name': 'Collision', - 'savables': {} - }, - 'Gymnasium_Teleport_Tablet_2062': { - 'hash': 2062, - 'name': 'Gymnasium Teleport Tablet', - 'savables': {} - } - } - }, - 'Gymnasium_Xp_Display_View': { - 'hash': 57304, - 'name': 'Gymnasium Xp Display View', - 'embedded': { - 'Back_Button_17050': { - 'hash': 17050, - 'name': 'Back Button', - 'savables': {} - }, - 'Forward_Button_17050': { - 'hash': 17050, - 'name': 'Forward Button', - 'savables': {} - }, - 'Gymnasium_Xp_Display_View_57232': { - 'hash': 57232, - 'name': 'Gymnasium Xp Display View', - 'savables': {} - }, - 'Increase_Button_17050': { - 'hash': 17050, - 'name': 'Increase Button', - 'savables': {} - }, - 'Increase_Max_Button_17050': { - 'hash': 17050, - 'name': 'Increase Max Button', - 'savables': {} - }, - 'Reset_Button_17050': { - 'hash': 17050, - 'name': 'Reset Button', - 'savables': {} - } - } - }, - 'Hammer': { - 'hash': 61660, - 'name': 'Hammer', - 'embedded': {} - }, - 'Hammer_Head': { - 'hash': 43146, - 'name': 'Hammer Head', - 'embedded': { - 'Hammer_Head_42978': { - 'hash': 42978, - 'name': 'Hammer Head', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_10366': { - 'hash': 10366, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_HammerType_End_Cap_52192': { - 'hash': 52192, - 'name': 'Insert HammerType End Cap', - 'savables': {} - } - } - }, - 'Hammer_Head_Small': { - 'hash': 15476, - 'name': 'Hammer Head Small', - 'embedded': { - 'Hammer_Head_Small_18788': { - 'hash': 18788, - 'name': 'Hammer Head Small', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_10670': { - 'hash': 10670, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_HammerType_End_Cap_18784': { - 'hash': 18784, - 'name': 'Insert HammerType End Cap', - 'savables': {} - } - } - }, - 'Hammer_Training': { - 'hash': 47018, - 'name': 'Hammer Training', - 'embedded': { - 'Hammer_Training_44084': { - 'hash': 44084, - 'name': 'Hammer Training', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Hand_Camera': { - 'hash': 59806, - 'name': 'Hand_Camera', - 'embedded': {} - }, - 'Handle_Bow': { - 'hash': 64410, - 'name': 'Handle Bow', - 'embedded': { - 'Handle_Bow_1188': { - 'hash': 1188, - 'name': 'Handle Bow', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_Grass_11474': { - 'hash': 11474, - 'name': 'Slot Grass', - 'savables': {} - }, - 'Slot_Grass_29036': { - 'hash': 29036, - 'name': 'Slot Grass', - 'savables': {} - } - } - }, - 'Handle_Fist': { - 'hash': 22988, - 'name': 'Handle Fist', - 'embedded': { - 'Handle_Fist_45004': { - 'hash': 45004, - 'name': 'Handle Fist', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_7356': { - 'hash': 7356, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Slot_Deco_22982': { - 'hash': 22982, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_22992': { - 'hash': 22992, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_23002': { - 'hash': 23002, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_54114': { - 'hash': 54114, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Multi_22990': { - 'hash': 22990, - 'name': 'Slot Multi', - 'savables': {} - } - } - }, - 'Handle_Large_Branch': { - 'hash': 61098, - 'name': 'Handle Large Branch', - 'embedded': { - 'Handle_Large_Branch_61094': { - 'hash': 61094, - 'name': 'Handle Large Branch', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_Multi_20330': { - 'hash': 20330, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_Primitive_AxeType_55026': { - 'hash': 55026, - 'name': 'Slot Primitive AxeType', - 'savables': {} - } - } - }, - 'Handle_Large_Cool': { - 'hash': 25290, - 'name': 'Handle Large Cool', - 'embedded': { - 'Handle_Large_Cool_25294': { - 'hash': 25294, - 'name': 'Handle Large Cool', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_37768': { - 'hash': 37768, - 'name': 'Heat Point', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Slot_EdgeType_Craft_43172': { - 'hash': 43172, - 'name': 'Slot EdgeType Craft', - 'savables': {} - }, - 'Slot_EdgeType_Craft_64610': { - 'hash': 64610, - 'name': 'Slot EdgeType Craft', - 'savables': {} - }, - 'Slot_Multi_29320': { - 'hash': 29320, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_Multi_43166': { - 'hash': 43166, - 'name': 'Slot Multi', - 'savables': {} - } - } - }, - 'Handle_Large_Standard': { - 'hash': 43252, - 'name': 'Handle_Large_Standard', - 'embedded': {} - }, - 'Handle_Long_Straight': { - 'hash': 20300, - 'name': 'Handle Long Straight', - 'embedded': { - 'Dock_32818': { - 'hash': 32818, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Handle_Long_Straight_25294': { - 'hash': 25294, - 'name': 'Handle Long Straight', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_EdgeType_Craft_53492': { - 'hash': 53492, - 'name': 'Slot EdgeType Craft', - 'savables': {} - }, - 'Slot_EdgeType_Craft_53692': { - 'hash': 53692, - 'name': 'Slot EdgeType Craft', - 'savables': {} - }, - 'Slot_Multi_(1)_63178': { - 'hash': 63178, - 'name': 'Slot Multi (1)', - 'savables': {} - }, - 'Slot_Multi_53060': { - 'hash': 53060, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_Multi_53074': { - 'hash': 53074, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_Multi_63218': { - 'hash': 63218, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_Straight_Short_Sword_Type_63270': { - 'hash': 63270, - 'name': 'Slot Straight Short Sword Type', - 'savables': {} - }, - 'Slot_Straight_Short_Sword_Type_63318': { - 'hash': 63318, - 'name': 'Slot Straight Short Sword Type', - 'savables': {} - } - } - }, - 'Handle_Medium_Branch': { - 'hash': 61400, - 'name': 'Handle Medium Branch', - 'embedded': { - 'Handle_Medium_Branch_61404': { - 'hash': 61404, - 'name': 'Handle Medium Branch', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_EdgeType_Craft_45470': { - 'hash': 45470, - 'name': 'Slot EdgeType Craft', - 'savables': {} - }, - 'Slot_Multi_15462': { - 'hash': 15462, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_Multi_29458': { - 'hash': 29458, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_Multi_52880': { - 'hash': 52880, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_PommelType_55836': { - 'hash': 55836, - 'name': 'Slot PommelType', - 'savables': {} - } - } - }, - 'Handle_Medium_Cool': { - 'hash': 61856, - 'name': 'Handle Medium Cool', - 'embedded': { - 'Handle_Medium_Cool_61852': { - 'hash': 61852, - 'name': 'Handle Medium Cool', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_8548': { - 'hash': 8548, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Slot_EdgeType_Craft_57058': { - 'hash': 57058, - 'name': 'Slot EdgeType Craft', - 'savables': {} - }, - 'Slot_EdgeType_Craft_59436': { - 'hash': 59436, - 'name': 'Slot EdgeType Craft', - 'savables': {} - }, - 'Slot_Multi_3558': { - 'hash': 3558, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_Multi_59224': { - 'hash': 59224, - 'name': 'Slot Multi', - 'savables': {} - } - } - }, - 'Handle_Medium_Curved': { - 'hash': 19316, - 'name': 'Handle Medium Curved', - 'embedded': { - 'Handle_Medium_Curved_19318': { - 'hash': 19318, - 'name': 'Handle Medium Curved', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_9036': { - 'hash': 9036, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Slot_EdgeType_Craft_51182': { - 'hash': 51182, - 'name': 'Slot EdgeType Craft', - 'savables': {} - }, - 'Slot_Multi_7860': { - 'hash': 7860, - 'name': 'Slot Multi', - 'savables': {} - } - } - }, - 'Handle_Medium_Ridged': { - 'hash': 60598, - 'name': 'Handle Medium Ridged', - 'embedded': { - 'Handle_Medium_Ridged_44084': { - 'hash': 44084, - 'name': 'Handle Medium Ridged', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_Pole_19996': { - 'hash': 19996, - 'name': 'Slot Pole', - 'savables': {} - }, - 'Slot_Pole_64914': { - 'hash': 64914, - 'name': 'Slot Pole', - 'savables': {} - } - } - }, - 'Handle_Medium_Standard': { - 'hash': 41438, - 'name': 'Handle Medium Standard', - 'embedded': { - 'Handle_Medium_Standard_44084': { - 'hash': 44084, - 'name': 'Handle Medium Standard', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_Pole_20070': { - 'hash': 20070, - 'name': 'Slot Pole', - 'savables': {} - }, - 'Slot_Pole_64914': { - 'hash': 64914, - 'name': 'Slot Pole', - 'savables': {} - } - } - }, - 'Handle_Medium_Straight': { - 'hash': 19180, - 'name': 'Handle Medium Straight', - 'embedded': { - 'Dock_39120': { - 'hash': 39120, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Handle_Medium_Straight_19154': { - 'hash': 19154, - 'name': 'Handle Medium Straight', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_EdgeType_Craft_53492': { - 'hash': 53492, - 'name': 'Slot EdgeType Craft', - 'savables': {} - }, - 'Slot_EdgeType_Craft_53692': { - 'hash': 53692, - 'name': 'Slot EdgeType Craft', - 'savables': {} - }, - 'Slot_Multi_(1)_63178': { - 'hash': 63178, - 'name': 'Slot Multi (1)', - 'savables': {} - }, - 'Slot_Multi_53060': { - 'hash': 53060, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_Multi_53074': { - 'hash': 53074, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_Multi_63218': { - 'hash': 63218, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_Straight_Short_Sword_Type_63270': { - 'hash': 63270, - 'name': 'Slot Straight Short Sword Type', - 'savables': {} - }, - 'Slot_Straight_Short_Sword_Type_63318': { - 'hash': 63318, - 'name': 'Slot Straight Short Sword Type', - 'savables': {} - } - } - }, - 'Handle_Round_Fist': { - 'hash': 3506, - 'name': 'Handle Round Fist', - 'embedded': { - 'Handle_Round_Fist_3514': { - 'hash': 3514, - 'name': 'Handle Round Fist', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_Deco_31482': { - 'hash': 31482, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_38156': { - 'hash': 38156, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_50738': { - 'hash': 50738, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_57746': { - 'hash': 57746, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Multi_54114': { - 'hash': 54114, - 'name': 'Slot Multi', - 'savables': {} - } - } - }, - 'Handle_Short': { - 'hash': 42230, - 'name': 'Handle Short', - 'embedded': { - 'Handle_Short_42104': { - 'hash': 42104, - 'name': 'Handle Short', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_Large_SwordType_Craft_54356': { - 'hash': 54356, - 'name': 'Slot Large SwordType Craft', - 'savables': {} - }, - 'Slot_Large_SwordType_Craft_6134': { - 'hash': 6134, - 'name': 'Slot Large SwordType Craft', - 'savables': {} - }, - 'Slot_Multi_6136': { - 'hash': 6136, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_Multi_6138': { - 'hash': 6138, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_PommelType_20654': { - 'hash': 20654, - 'name': 'Slot PommelType', - 'savables': {} - }, - 'Slot_PommelType_30776': { - 'hash': 30776, - 'name': 'Slot PommelType', - 'savables': {} - } - } - }, - 'Handle_Short_C_Curve': { - 'hash': 34898, - 'name': 'Handle Short C Curve', - 'embedded': { - 'Handle_Short_C_Curve_44084': { - 'hash': 44084, - 'name': 'Handle Short C Curve', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_9524': { - 'hash': 9524, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Slot_Large_SwordType_Craft_5628': { - 'hash': 5628, - 'name': 'Slot Large SwordType Craft', - 'savables': {} - }, - 'Slot_Large_SwordType_Craft_5714': { - 'hash': 5714, - 'name': 'Slot Large SwordType Craft', - 'savables': {} - }, - 'Slot_Multi_5624': { - 'hash': 5624, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_Multi_5626': { - 'hash': 5626, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_PommelType_5686': { - 'hash': 5686, - 'name': 'Slot PommelType', - 'savables': {} - }, - 'Slot_PommelType_5700': { - 'hash': 5700, - 'name': 'Slot PommelType', - 'savables': {} - } - } - }, - 'Handle_Short_Cool': { - 'hash': 5920, - 'name': 'Handle Short Cool', - 'embedded': { - 'Handle_Short_Cool_5922': { - 'hash': 5922, - 'name': 'Handle Short Cool', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_51674': { - 'hash': 51674, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Slot_EdgeType_Craft_43890': { - 'hash': 43890, - 'name': 'Slot EdgeType Craft', - 'savables': {} - }, - 'Slot_Large_SwordType_Craft_33946': { - 'hash': 33946, - 'name': 'Slot Large SwordType Craft', - 'savables': {} - }, - 'Slot_Multi_48480': { - 'hash': 48480, - 'name': 'Slot Multi', - 'savables': {} - } - } - }, - 'Handle_Short_Pointy_End': { - 'hash': 28636, - 'name': 'Handle Short Pointy End', - 'embedded': { - 'Handle_Short_Pointy_End_44084': { - 'hash': 44084, - 'name': 'Handle Short Pointy End', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Heat_Point_Collection_10000': { - 'hash': 10000, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Slot_EdgeType_Craft_14502': { - 'hash': 14502, - 'name': 'Slot EdgeType Craft', - 'savables': {} - }, - 'Slot_Large_SwordType_Craft_9736': { - 'hash': 9736, - 'name': 'Slot Large SwordType Craft', - 'savables': {} - }, - 'Slot_Multi_18472': { - 'hash': 18472, - 'name': 'Slot Multi', - 'savables': {} - } - } - }, - 'Handle_Short_S_Curve': { - 'hash': 27820, - 'name': 'Handle Short S Curve', - 'embedded': { - 'Handle_Short_S_Curve_44084': { - 'hash': 44084, - 'name': 'Handle Short S Curve', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_Mid_20238': { - 'hash': 20238, - 'name': 'Slot Mid', - 'savables': {} - }, - 'Slot_Mid_64914': { - 'hash': 64914, - 'name': 'Slot Mid', - 'savables': {} - } - } - }, - 'Handle_Short_Taper': { - 'hash': 24198, - 'name': 'Handle Short Taper', - 'embedded': { - 'Handle_Short_Taper_24200': { - 'hash': 24200, - 'name': 'Handle Short Taper', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_Mid_20296': { - 'hash': 20296, - 'name': 'Slot Mid', - 'savables': {} - }, - 'Slot_Mid_64914': { - 'hash': 64914, - 'name': 'Slot Mid', - 'savables': {} - } - } - }, - 'Handle_Spear': { - 'hash': 20640, - 'name': 'Handle Spear', - 'embedded': { - 'Handle_Spear_24200': { - 'hash': 24200, - 'name': 'Handle Spear', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_Deco_4866': { - 'hash': 4866, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Pole_64914': { - 'hash': 64914, - 'name': 'Slot Pole', - 'savables': {} - } - } - }, - 'Handle_Tonfa': { - 'hash': 57838, - 'name': 'Handle Tonfa', - 'embedded': { - 'Handle_Tonfa_57844': { - 'hash': 57844, - 'name': 'Handle Tonfa', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_EdgeType_Craft_52822': { - 'hash': 52822, - 'name': 'Slot EdgeType Craft', - 'savables': {} - }, - 'Slot_HammerType_End_Cap_47874': { - 'hash': 47874, - 'name': 'Slot HammerType End Cap', - 'savables': {} - }, - 'Slot_Multi_64782': { - 'hash': 64782, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_Shield_37414': { - 'hash': 37414, - 'name': 'Slot Shield', - 'savables': {} - } - } - }, - 'Handy_Cam': { - 'hash': 13790, - 'name': 'Handy_Cam', - 'embedded': {} - }, - 'Hanging_Health_Vine_01': { - 'hash': 52952, - 'name': 'Hanging Health Vine 01', - 'embedded': { - 'Directional_Encounter_43896': { - 'hash': 43896, - 'name': 'Directional Encounter', - 'savables': { - 'CylindricalBoundsSurface': { - 'hash': 34507654, - 'name': 'CylindricalBoundsSurface' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - }, - 'Hanging_Health_Vine_01_6398': { - 'hash': 6398, - 'name': 'Hanging Health Vine 01', - 'savables': {} - } - } - }, - 'Hanging_Health_Vine_02': { - 'hash': 56796, - 'name': 'Hanging Health Vine 02', - 'embedded': { - 'Directional_Encounter_43896': { - 'hash': 43896, - 'name': 'Directional Encounter', - 'savables': { - 'CylindricalBoundsSurface': { - 'hash': 34507654, - 'name': 'CylindricalBoundsSurface' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - }, - 'Hanging_Health_Vine_02_6398': { - 'hash': 6398, - 'name': 'Hanging Health Vine 02', - 'savables': {} - } - } - }, - 'Hanging_Health_Vine_03': { - 'hash': 53496, - 'name': 'Hanging Health Vine 03', - 'embedded': { - 'Directional_Encounter_43896': { - 'hash': 43896, - 'name': 'Directional Encounter', - 'savables': { - 'CylindricalBoundsSurface': { - 'hash': 34507654, - 'name': 'CylindricalBoundsSurface' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - }, - 'Hanging_Health_Vine_03_6398': { - 'hash': 6398, - 'name': 'Hanging Health Vine 03', - 'savables': {} - } - } - }, - 'Hanging_Loot_Box_Platform': { - 'hash': 54462, - 'name': 'Hanging Loot Box Platform', - 'embedded': { - 'Hanging_Loot_Box_Platform_12670': { - 'hash': 12670, - 'name': 'Hanging Loot Box Platform', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Spawn_Boxes_(1)_18788': { - 'hash': 18788, - 'name': 'Spawn Boxes (1)', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'SpawnArea': { - 'hash': 2617495528, - 'name': 'SpawnArea' - } - } - }, - 'Spawn_Boxes_(2)_18856': { - 'hash': 18856, - 'name': 'Spawn Boxes (2)', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'SpawnArea': { - 'hash': 2617495528, - 'name': 'SpawnArea' - } - } - }, - 'Spawn_Boxes_(3)_18766': { - 'hash': 18766, - 'name': 'Spawn Boxes (3)', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'SpawnArea': { - 'hash': 2617495528, - 'name': 'SpawnArea' - } - } - }, - 'Spawn_Boxes_53424': { - 'hash': 53424, - 'name': 'Spawn Boxes', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'SpawnArea': { - 'hash': 2617495528, - 'name': 'SpawnArea' - } - } - } - } - }, - 'Hanging_Loot_Sack': { - 'hash': 49658, - 'name': 'Hanging Loot Sack', - 'embedded': { - 'Box_5934': { - 'hash': 5934, - 'name': 'Box', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Hanging_Loot_Sack_12670': { - 'hash': 12670, - 'name': 'Hanging Loot Sack', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Link_5938': { - 'hash': 5938, - 'name': 'Link', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Hard_Metal_Small_Bits': { - 'hash': 62594, - 'name': 'Hard Metal Small Bits', - 'embedded': { - 'Hard_Metal_Small_Bits_62578': { - 'hash': 62578, - 'name': 'Hard Metal Small Bits', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Hard_Plate_Metal_Medium_Square': { - 'hash': 50988, - 'name': 'Hard Plate Metal Medium Square', - 'embedded': { - 'Hard_Plate_Metal_Medium_Square_51004': { - 'hash': 51004, - 'name': 'Hard Plate Metal Medium Square', - 'savables': { - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Mesh_51176': { - 'hash': 51176, - 'name': 'Mesh', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'hardPlate_metal_medium_square_LOD0_52344': { - 'hash': 52344, - 'name': 'hardPlate_metal_medium_square_LOD0', - 'savables': {} - } - } - }, - 'Healing_Pod': { - 'hash': 44360, - 'name': 'Healing Pod', - 'embedded': { - 'Explosion_58370': { - 'hash': 58370, - 'name': 'Explosion', - 'savables': {} - }, - 'Healing_Pod_15532': { - 'hash': 15532, - 'name': 'Healing Pod', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Insert_Deco_112': { - 'hash': 112, - 'name': 'Insert Deco', - 'savables': {} - } - } - }, - 'Healing_Pod_Plant': { - 'hash': 48826, - 'name': 'Healing Pod Plant', - 'embedded': { - 'Healing_Pod_Plant_64192': { - 'hash': 64192, - 'name': 'Healing Pod Plant', - 'savables': {} - }, - 'PullPickup_51602': { - 'hash': 51602, - 'name': 'PullPickup', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Spawn_Buried_57238': { - 'hash': 57238, - 'name': 'Spawn Buried', - 'savables': { - 'SpawnBuried': { - 'hash': 654225716, - 'name': 'SpawnBuried' - } - } - } - } - }, - 'Heart_Receptacle': { - 'hash': 56090, - 'name': 'Heart Receptacle', - 'embedded': { - 'Fake_Interactable_64848': { - 'hash': 64848, - 'name': 'Fake Interactable', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Heart_Receptacle_37620': { - 'hash': 37620, - 'name': 'Heart Receptacle', - 'savables': {} - } - } - }, - 'Hebios_Buried_Spawn_Area': { - 'hash': 51290, - 'name': 'Hebios Buried Spawn Area', - 'embedded': { - 'Hebios_Buried_Spawn_Area_51274': { - 'hash': 51274, - 'name': 'Hebios Buried Spawn Area', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'SpawnArea': { - 'hash': 2617495528, - 'name': 'SpawnArea' - } - } - } - } - }, - 'Hebios_Camp_Barren': { - 'hash': 56012, - 'name': 'Hebios_Camp_Barren', - 'embedded': {} - }, - 'Hebios_Camp_Barren_Dynamic': { - 'hash': 56012, - 'name': 'Hebios Camp Barren Dynamic', - 'embedded': { - 'Closed_Crate_Spawner_26166': { - 'hash': 26166, - 'name': 'Closed Crate Spawner', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - }, - 'Enemy_Spawn_30256': { - 'hash': 30256, - 'name': 'Enemy Spawn', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'SpawnArea': { - 'hash': 2617495528, - 'name': 'SpawnArea' - } - } - }, - 'Hebios_Camp_Barren_Dynamic_53304': { - 'hash': 53304, - 'name': 'Hebios Camp Barren Dynamic', - 'savables': {} - }, - 'Hebios_Camp_Fire_Spawner_55752': { - 'hash': 55752, - 'name': 'Hebios Camp Fire Spawner', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - }, - 'Open_Crate_Spawner_48408': { - 'hash': 48408, - 'name': 'Open Crate Spawner', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - } - } - }, - 'Hebios_Camp_Spawner': { - 'hash': 43300, - 'name': 'Hebios_Camp_Spawner', - 'embedded': {} - }, - 'Hebios_Camp_Valley': { - 'hash': 42062, - 'name': 'Hebios Camp Valley', - 'embedded': { - 'Hebios_Camp_Valley_38962': { - 'hash': 38962, - 'name': 'Hebios Camp Valley', - 'savables': { - 'StaticGenerationParent': { - 'hash': 2975913730, - 'name': 'StaticGenerationParent' - } - } - } - } - }, - 'Hebios_Camp_Valley_Center_Section_NEW': { - 'hash': 5350, - 'name': 'Hebios_Camp_Valley_Center_Section_NEW', - 'embedded': {} - }, - 'Hebios_Camp_Valley_Center_Section_Pond': { - 'hash': 54680, - 'name': 'Hebios_Camp_Valley_Center_Section_Pond', - 'embedded': {} - }, - 'Hebios_Camp_Valley_Front_Section_Spike_Gate': { - 'hash': 42358, - 'name': 'Hebios_Camp_Valley_Front_Section_Spike_Gate', - 'embedded': {} - }, - 'Hebios_Camp_Valley_Front_Section_Stone_Cliff': { - 'hash': 19412, - 'name': 'Hebios_Camp_Valley_Front_Section_Stone_Cliff', - 'embedded': {} - }, - 'Hebios_Camp_Valley_Left_Section_Archway': { - 'hash': 40482, - 'name': 'Hebios_Camp_Valley_Left_Section_Archway', - 'embedded': {} - }, - 'Hebios_Camp_Valley_Left_Section_Hilly_Forest': { - 'hash': 37966, - 'name': 'Hebios_Camp_Valley_Left_Section_Hilly_Forest', - 'embedded': {} - }, - 'Hebios_Closed_Crate_Spawner': { - 'hash': 46524, - 'name': 'Hebios Closed Crate Spawner', - 'embedded': { - 'Hebios_Closed_Crate_Spawner_19058': { - 'hash': 19058, - 'name': 'Hebios Closed Crate Spawner', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - } - } - }, - 'Hebios_Crafted_Mould': { - 'hash': 22498, - 'name': 'Hebios Crafted Mould', - 'embedded': { - 'Hebios_Crafted_Mould_14710': { - 'hash': 14710, - 'name': 'Hebios Crafted Mould', - 'savables': { - 'Mould': { - 'hash': 391977879, - 'name': 'Mould' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'hebios_mould_centerFrame_grp_18498': { - 'hash': 18498, - 'name': 'hebios_mould_centerFrame_grp', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hebios_mould_emblem_grp_9986': { - 'hash': 9986, - 'name': 'hebios_mould_emblem_grp', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hebios_mould_frame_horizontal_grp_01_18458': { - 'hash': 18458, - 'name': 'hebios_mould_frame_horizontal_grp 01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hebios_mould_frame_horizontal_grp_02_18482': { - 'hash': 18482, - 'name': 'hebios_mould_frame_horizontal_grp 02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hebios_mould_frame_vertical_grp_01_18462': { - 'hash': 18462, - 'name': 'hebios_mould_frame_vertical_grp 01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hebios_mould_frame_vertical_grp_02_18486': { - 'hash': 18486, - 'name': 'hebios_mould_frame_vertical_grp 02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hebios_mould_grassKnot_grp_01_18450': { - 'hash': 18450, - 'name': 'hebios_mould_grassKnot_grp 01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hebios_mould_grassKnot_grp_02_18446': { - 'hash': 18446, - 'name': 'hebios_mould_grassKnot_grp 02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hebios_mould_grassKnot_grp_03_18502': { - 'hash': 18502, - 'name': 'hebios_mould_grassKnot_grp 03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hebios_mould_grassKnot_grp_04_18474': { - 'hash': 18474, - 'name': 'hebios_mould_grassKnot_grp 04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hebios_mould_ingotGraphic_grp_18494': { - 'hash': 18494, - 'name': 'hebios_mould_ingotGraphic_grp', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hebios_mould_railSlot_grp_01_18490': { - 'hash': 18490, - 'name': 'hebios_mould_railSlot_grp 01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hebios_mould_railSlot_grp_02_18454': { - 'hash': 18454, - 'name': 'hebios_mould_railSlot_grp 02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hebios_mould_railSlot_grp_03_18470': { - 'hash': 18470, - 'name': 'hebios_mould_railSlot_grp 03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hebios_mould_railSlot_grp_04_18466': { - 'hash': 18466, - 'name': 'hebios_mould_railSlot_grp 04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hebios_mould_timesGraphic_grp_18478': { - 'hash': 18478, - 'name': 'hebios_mould_timesGraphic_grp', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'katana_guard_grp_63702': { - 'hash': 63702, - 'name': 'katana_guard_grp', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'redwood_gotera_core_emblemPart_grp_52708': { - 'hash': 52708, - 'name': 'redwood_gotera_core_emblemPart_grp', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'redwood_gotera_core_leafPart_grp_52712': { - 'hash': 52712, - 'name': 'redwood_gotera_core_leafPart_grp', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Hebios_Guard': { - 'hash': 5144, - 'name': 'Hebios Guard', - 'embedded': { - 'Heat_Point_Collection_56294': { - 'hash': 56294, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Hebios_Guard_36330': { - 'hash': 36330, - 'name': 'Hebios Guard', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Insert_SwordType_Craft_39368': { - 'hash': 39368, - 'name': 'Insert SwordType Craft', - 'savables': {} - }, - 'Slot_SwordType_39370': { - 'hash': 39370, - 'name': 'Slot SwordType', - 'savables': {} - } - } - }, - 'Hebios_Handle_Katana': { - 'hash': 53200, - 'name': 'Hebios Handle Katana', - 'embedded': { - 'Hebios_Handle_Katana_40148': { - 'hash': 40148, - 'name': 'Hebios Handle Katana', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'Enchantable': { - 'hash': 4134534481, - 'name': 'Enchantable' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Joint_Group_SwordType_63178': { - 'hash': 63178, - 'name': 'Joint Group SwordType', - 'savables': {} - }, - 'Slot_EdgeType_Craft_53492': { - 'hash': 53492, - 'name': 'Slot EdgeType Craft', - 'savables': {} - }, - 'Slot_Straight_Short_Sword_Type_63318': { - 'hash': 63318, - 'name': 'Slot Straight Short Sword Type', - 'savables': {} - } - } - }, - 'Hebios_Handle_Kunai': { - 'hash': 18456, - 'name': 'Hebios Handle Kunai', - 'embedded': { - 'Hebios_Handle_Kunai_14986': { - 'hash': 14986, - 'name': 'Hebios Handle Kunai', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'Embeddable': { - 'hash': 22446553, - 'name': 'Embeddable' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_Multi_6136': { - 'hash': 6136, - 'name': 'Slot Multi', - 'savables': {} - } - } - }, - 'Hebios_Handle_Naginata': { - 'hash': 24220, - 'name': 'Hebios Handle Naginata', - 'embedded': { - 'Hebios_Handle_Naginata_26368': { - 'hash': 26368, - 'name': 'Hebios Handle Naginata', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'Enchantable': { - 'hash': 4134534481, - 'name': 'Enchantable' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_EdgeType_Craft_53692': { - 'hash': 53692, - 'name': 'Slot EdgeType Craft', - 'savables': {} - }, - 'Slot_Multi_53060': { - 'hash': 53060, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_Multi_63218': { - 'hash': 63218, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_Straight_Short_Sword_Type_63270': { - 'hash': 63270, - 'name': 'Slot Straight Short Sword Type', - 'savables': {} - } - } - }, - 'Hebios_Handle_Wakizashi': { - 'hash': 47662, - 'name': 'Hebios Handle Wakizashi', - 'embedded': { - 'Hebios_Handle_Wakizashi_47666': { - 'hash': 47666, - 'name': 'Hebios Handle Wakizashi', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'Enchantable': { - 'hash': 4134534481, - 'name': 'Enchantable' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Joint_Group_SwordType_63178': { - 'hash': 63178, - 'name': 'Joint Group SwordType', - 'savables': {} - }, - 'Slot_Straight_Short_Sword_Type_63318': { - 'hash': 63318, - 'name': 'Slot Straight Short Sword Type', - 'savables': {} - } - } - }, - 'Hebios_Katana_Blade_Part_01': { - 'hash': 12388, - 'name': 'Hebios Katana Blade Part 01', - 'embedded': { - 'Hebios_Katana_Blade_Part_01_46162': { - 'hash': 46162, - 'name': 'Hebios Katana Blade Part 01', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Hebios_Katana_Blade_Part_02': { - 'hash': 12386, - 'name': 'Hebios Katana Blade Part 02', - 'embedded': { - 'Hebios_Katana_Blade_Part_02_46162': { - 'hash': 46162, - 'name': 'Hebios Katana Blade Part 02', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Hebios_Katana_Blade_Part_Full': { - 'hash': 17266, - 'name': 'Hebios Katana Blade Part Full', - 'embedded': { - 'Hebios_Katana_Blade_Part_Full_40924': { - 'hash': 40924, - 'name': 'Hebios Katana Blade Part Full', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Insert_Straight_SwordType_7796': { - 'hash': 7796, - 'name': 'Insert Straight SwordType', - 'savables': {} - }, - 'hebios_katana_blade_part_01_56656': { - 'hash': 56656, - 'name': 'hebios_katana_blade_part_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hebios_katana_blade_part_02_56652': { - 'hash': 56652, - 'name': 'hebios_katana_blade_part_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Hebios_Naginata_Blade_Part_01': { - 'hash': 17238, - 'name': 'Hebios Naginata Blade Part 01', - 'embedded': { - 'Hebios_Naginata_Blade_Part_01_46162': { - 'hash': 46162, - 'name': 'Hebios Naginata Blade Part 01', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Hebios_Naginata_Blade_Part_02': { - 'hash': 42894, - 'name': 'Hebios Naginata Blade Part 02', - 'embedded': { - 'Hebios_Naginata_Blade_Part_02_46162': { - 'hash': 46162, - 'name': 'Hebios Naginata Blade Part 02', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Hebios_Naginata_Blade_Part_Full': { - 'hash': 17420, - 'name': 'Hebios Naginata Blade Part Full', - 'embedded': { - 'Hebios_Naginata_Blade_Part_Full_40924': { - 'hash': 40924, - 'name': 'Hebios Naginata Blade Part Full', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Insert_Straight_SwordType_7796': { - 'hash': 7796, - 'name': 'Insert Straight SwordType', - 'savables': {} - }, - 'naginata_blade_part_01_grp_21404': { - 'hash': 21404, - 'name': 'naginata_blade_part_01_grp', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'naginata_blade_part_02_grp_21408': { - 'hash': 21408, - 'name': 'naginata_blade_part_02_grp', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Hebios_Open_Crate_Spawner': { - 'hash': 46522, - 'name': 'Hebios Open Crate Spawner', - 'embedded': { - 'Hebios_Open_Crate_Spawner_19060': { - 'hash': 19060, - 'name': 'Hebios Open Crate Spawner', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - } - } - }, - 'Hebios_Sai_Blade_Part_01': { - 'hash': 57048, - 'name': 'Hebios Sai Blade Part 01', - 'embedded': { - 'Hebios_Sai_Blade_Part_01_46162': { - 'hash': 46162, - 'name': 'Hebios Sai Blade Part 01', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Hebios_Sai_Blade_Part_02': { - 'hash': 56830, - 'name': 'Hebios Sai Blade Part 02', - 'embedded': { - 'Hebios_Sai_Blade_Part_02_46162': { - 'hash': 46162, - 'name': 'Hebios Sai Blade Part 02', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Hebios_Sai_Blade_Part_Full': { - 'hash': 1600, - 'name': 'Hebios Sai Blade Part Full', - 'embedded': { - 'Hebios_Sai_Blade_Part_Full_40924': { - 'hash': 40924, - 'name': 'Hebios Sai Blade Part Full', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Insert_Straight_Short_SwordType_7796': { - 'hash': 7796, - 'name': 'Insert Straight Short SwordType', - 'savables': {} - }, - 'hebios_sai_blade_part_01_50732': { - 'hash': 50732, - 'name': 'hebios_sai_blade_part_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hebios_sai_blade_part_02_50728': { - 'hash': 50728, - 'name': 'hebios_sai_blade_part_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Hebios_Storage_Chest': { - 'hash': 44984, - 'name': 'Hebios Storage Chest', - 'embedded': { - 'Bottom_Dock_1_2780': { - 'hash': 2780, - 'name': 'Bottom Dock 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_2_2778': { - 'hash': 2778, - 'name': 'Bottom Dock 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_3_2776': { - 'hash': 2776, - 'name': 'Bottom Dock 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_4_2770': { - 'hash': 2770, - 'name': 'Bottom Dock 4', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_5_2772': { - 'hash': 2772, - 'name': 'Bottom Dock 5', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_6_2774': { - 'hash': 2774, - 'name': 'Bottom Dock 6', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Handle_Left_23970': { - 'hash': 23970, - 'name': 'Handle Left', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Handle_Right_23964': { - 'hash': 23964, - 'name': 'Handle Right', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Hebios_Storage_Chest_2788': { - 'hash': 2788, - 'name': 'Hebios Storage Chest', - 'savables': { - 'Chest': { - 'hash': 3598052397, - 'name': 'Chest' - } - } - }, - 'Lid_2768': { - 'hash': 2768, - 'name': 'Lid', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Loot_Module_27674': { - 'hash': 27674, - 'name': 'Loot Module', - 'savables': { - 'LootModule': { - 'hash': 634164392, - 'name': 'LootModule' - } - } - }, - 'Top_Dock_1_2766': { - 'hash': 2766, - 'name': 'Top Dock 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_2_2764': { - 'hash': 2764, - 'name': 'Top Dock 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_3_2762': { - 'hash': 2762, - 'name': 'Top Dock 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_4_2756': { - 'hash': 2756, - 'name': 'Top Dock 4', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_5_2758': { - 'hash': 2758, - 'name': 'Top Dock 5', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_6_2760': { - 'hash': 2760, - 'name': 'Top Dock 6', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - } - } - }, - 'Hebios_Storage_Chest_Climbing': { - 'hash': 35078, - 'name': 'Hebios Storage Chest Climbing', - 'embedded': { - 'Bottom_Dock_1_2780': { - 'hash': 2780, - 'name': 'Bottom Dock 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_2_2778': { - 'hash': 2778, - 'name': 'Bottom Dock 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_3_2776': { - 'hash': 2776, - 'name': 'Bottom Dock 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_4_2770': { - 'hash': 2770, - 'name': 'Bottom Dock 4', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_5_2772': { - 'hash': 2772, - 'name': 'Bottom Dock 5', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_6_2774': { - 'hash': 2774, - 'name': 'Bottom Dock 6', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Handle_Left_23970': { - 'hash': 23970, - 'name': 'Handle Left', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Handle_Right_23964': { - 'hash': 23964, - 'name': 'Handle Right', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Hebios_Storage_Chest_Climbing_35076': { - 'hash': 35076, - 'name': 'Hebios Storage Chest Climbing', - 'savables': { - 'Chest': { - 'hash': 3598052397, - 'name': 'Chest' - } - } - }, - 'Lid_2768': { - 'hash': 2768, - 'name': 'Lid', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Loot_Module_27674': { - 'hash': 27674, - 'name': 'Loot Module', - 'savables': { - 'LootModule': { - 'hash': 634164392, - 'name': 'LootModule' - } - } - }, - 'Top_Dock_1_2766': { - 'hash': 2766, - 'name': 'Top Dock 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_2_2764': { - 'hash': 2764, - 'name': 'Top Dock 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_3_2762': { - 'hash': 2762, - 'name': 'Top Dock 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_4_2756': { - 'hash': 2756, - 'name': 'Top Dock 4', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_5_2758': { - 'hash': 2758, - 'name': 'Top Dock 5', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_6_2760': { - 'hash': 2760, - 'name': 'Top Dock 6', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - } - } - }, - 'Hebios_Storage_Chest_Gcore': { - 'hash': 31618, - 'name': 'Hebios Storage Chest Gcore', - 'embedded': { - 'Bottom_Dock_1_2780': { - 'hash': 2780, - 'name': 'Bottom Dock 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_2_2778': { - 'hash': 2778, - 'name': 'Bottom Dock 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_3_2776': { - 'hash': 2776, - 'name': 'Bottom Dock 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_4_2770': { - 'hash': 2770, - 'name': 'Bottom Dock 4', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_5_2772': { - 'hash': 2772, - 'name': 'Bottom Dock 5', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_6_2774': { - 'hash': 2774, - 'name': 'Bottom Dock 6', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Handle_Left_23970': { - 'hash': 23970, - 'name': 'Handle Left', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Handle_Right_23964': { - 'hash': 23964, - 'name': 'Handle Right', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Hebios_Storage_Chest_Gcore_2788': { - 'hash': 2788, - 'name': 'Hebios Storage Chest Gcore', - 'savables': { - 'Chest': { - 'hash': 3598052397, - 'name': 'Chest' - } - } - }, - 'Lid_2768': { - 'hash': 2768, - 'name': 'Lid', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Loot_Module_27674': { - 'hash': 27674, - 'name': 'Loot Module', - 'savables': { - 'LootModule': { - 'hash': 634164392, - 'name': 'LootModule' - } - } - }, - 'Top_Dock_1_2766': { - 'hash': 2766, - 'name': 'Top Dock 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_2_2764': { - 'hash': 2764, - 'name': 'Top Dock 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_3_2762': { - 'hash': 2762, - 'name': 'Top Dock 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_4_2756': { - 'hash': 2756, - 'name': 'Top Dock 4', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_5_2758': { - 'hash': 2758, - 'name': 'Top Dock 5', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_6_2760': { - 'hash': 2760, - 'name': 'Top Dock 6', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - } - } - }, - 'Hebios_Wakizashi_Blade_Part_01': { - 'hash': 49774, - 'name': 'Hebios Wakizashi Blade Part 01', - 'embedded': { - 'Hebios_Wakizashi_Blade_Part_01_46162': { - 'hash': 46162, - 'name': 'Hebios Wakizashi Blade Part 01', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Hebios_Wakizashi_Blade_Part_02': { - 'hash': 50184, - 'name': 'Hebios Wakizashi Blade Part 02', - 'embedded': { - 'Hebios_Wakizashi_Blade_Part_02_46162': { - 'hash': 46162, - 'name': 'Hebios Wakizashi Blade Part 02', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Hebios_Wakizashi_Blade_Part_Full': { - 'hash': 9018, - 'name': 'Hebios Wakizashi Blade Part Full', - 'embedded': { - 'Hebios_Wakizashi_Blade_Part_Full_40924': { - 'hash': 40924, - 'name': 'Hebios Wakizashi Blade Part Full', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Insert_Straight_SwordType_7796': { - 'hash': 7796, - 'name': 'Insert Straight SwordType', - 'savables': {} - }, - 'wakizashi_blade_part_01_grp_31190': { - 'hash': 31190, - 'name': 'wakizashi_blade_part_01_grp', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'wakizashi_blade_part_02_grp_31194': { - 'hash': 31194, - 'name': 'wakizashi_blade_part_02_grp', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Hitting_Short_Sword_Training': { - 'hash': 55646, - 'name': 'Hitting Short Sword Training', - 'embedded': { - 'Blade_1152': { - 'hash': 1152, - 'name': 'Blade', - 'savables': {} - }, - 'Hitting_Short_Sword_Training_1152': { - 'hash': 1152, - 'name': 'Hitting Short Sword Training', - 'savables': {} - } - } - }, - 'Hoarder_Bag': { - 'hash': 54214, - 'name': 'Hoarder Bag', - 'embedded': { - 'Bag_Body_42972': { - 'hash': 42972, - 'name': 'Bag Body', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Dock_(1)_47074': { - 'hash': 47074, - 'name': 'Dock (1)', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_464': { - 'hash': 464, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_BL_(1)_1146': { - 'hash': 1146, - 'name': 'Dock BL (1)', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_BL_42978': { - 'hash': 42978, - 'name': 'Dock BL', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_BM_(1)_1148': { - 'hash': 1148, - 'name': 'Dock BM (1)', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_BM_42976': { - 'hash': 42976, - 'name': 'Dock BM', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_BR_(1)_1432': { - 'hash': 1432, - 'name': 'Dock BR (1)', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_BR_(2)_1240': { - 'hash': 1240, - 'name': 'Dock BR (2)', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_BR_(3)_1150': { - 'hash': 1150, - 'name': 'Dock BR (3)', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_BR_42974': { - 'hash': 42974, - 'name': 'Dock BR', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_ML_42984': { - 'hash': 42984, - 'name': 'Dock ML', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_MM_42982': { - 'hash': 42982, - 'name': 'Dock MM', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_MR_(1)_1430': { - 'hash': 1430, - 'name': 'Dock MR (1)', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_MR_42980': { - 'hash': 42980, - 'name': 'Dock MR', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_TL_42990': { - 'hash': 42990, - 'name': 'Dock TL', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_TM_42988': { - 'hash': 42988, - 'name': 'Dock TM', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_TR_(1)_1428': { - 'hash': 1428, - 'name': 'Dock TR (1)', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_TR_42986': { - 'hash': 42986, - 'name': 'Dock TR', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Hoarder_Bag_43012': { - 'hash': 43012, - 'name': 'Hoarder Bag', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_Bag_Attach_10614': { - 'hash': 10614, - 'name': 'Slot Bag Attach', - 'savables': {} - }, - 'Slot_Bag_Attach_10616': { - 'hash': 10616, - 'name': 'Slot Bag Attach', - 'savables': {} - }, - 'Slot_Bag_Attach_30776': { - 'hash': 30776, - 'name': 'Slot Bag Attach', - 'savables': {} - }, - 'Slot_Bag_Attach_55164': { - 'hash': 55164, - 'name': 'Slot Bag Attach', - 'savables': {} - }, - 'Slot_Bag_Pin_Collectible_Attach_59540': { - 'hash': 59540, - 'name': 'Slot Bag Pin Collectible Attach', - 'savables': {} - }, - 'Slot_Bag_Tool_Attachment_1020': { - 'hash': 1020, - 'name': 'Slot Bag Tool Attachment', - 'savables': {} - }, - 'Slot_Bag_Tool_Attachment_918': { - 'hash': 918, - 'name': 'Slot Bag Tool Attachment', - 'savables': {} - }, - 'hoarder_bag_body_39890': { - 'hash': 39890, - 'name': 'hoarder_bag_body', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_clasp_front_L_39810': { - 'hash': 39810, - 'name': 'hoarder_bag_clasp_front_L', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_clasp_front_R_39850': { - 'hash': 39850, - 'name': 'hoarder_bag_clasp_front_R', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_flap_39878': { - 'hash': 39878, - 'name': 'hoarder_bag_flap', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_flap_clasp_39886': { - 'hash': 39886, - 'name': 'hoarder_bag_flap_clasp', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_pin_L_01_39894': { - 'hash': 39894, - 'name': 'hoarder_bag_pin_L_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_pin_L_02_39882': { - 'hash': 39882, - 'name': 'hoarder_bag_pin_L_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_pin_L_03_39930': { - 'hash': 39930, - 'name': 'hoarder_bag_pin_L_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_pin_L_04_39826': { - 'hash': 39826, - 'name': 'hoarder_bag_pin_L_04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_pin_L_05_39898': { - 'hash': 39898, - 'name': 'hoarder_bag_pin_L_05', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_pin_L_06_39834': { - 'hash': 39834, - 'name': 'hoarder_bag_pin_L_06', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_pin_L_07_39902': { - 'hash': 39902, - 'name': 'hoarder_bag_pin_L_07', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_pin_R_01_39870': { - 'hash': 39870, - 'name': 'hoarder_bag_pin_R_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_pin_R_02_39858': { - 'hash': 39858, - 'name': 'hoarder_bag_pin_R_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_pin_R_03_39914': { - 'hash': 39914, - 'name': 'hoarder_bag_pin_R_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_pin_R_04_39926': { - 'hash': 39926, - 'name': 'hoarder_bag_pin_R_04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_pin_R_05_39806': { - 'hash': 39806, - 'name': 'hoarder_bag_pin_R_05', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_pin_R_06_39874': { - 'hash': 39874, - 'name': 'hoarder_bag_pin_R_06', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_pin_R_07_39814': { - 'hash': 39814, - 'name': 'hoarder_bag_pin_R_07', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_sideBuckle_L_01_39830': { - 'hash': 39830, - 'name': 'hoarder_bag_sideBuckle_L_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_sideBuckle_L_02_39802': { - 'hash': 39802, - 'name': 'hoarder_bag_sideBuckle_L_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_sideBuckle_R_01_39866': { - 'hash': 39866, - 'name': 'hoarder_bag_sideBuckle_R_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_sideBuckle_R_02_39906': { - 'hash': 39906, - 'name': 'hoarder_bag_sideBuckle_R_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_strap_body_39822': { - 'hash': 39822, - 'name': 'hoarder_bag_strap_body', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_strap_bottom_L_39854': { - 'hash': 39854, - 'name': 'hoarder_bag_strap_bottom_L', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_strap_bottom_R_39798': { - 'hash': 39798, - 'name': 'hoarder_bag_strap_bottom_R', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_strap_front_L_39838': { - 'hash': 39838, - 'name': 'hoarder_bag_strap_front_L', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_strap_front_R_39818': { - 'hash': 39818, - 'name': 'hoarder_bag_strap_front_R', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_strap_slot_L_39862': { - 'hash': 39862, - 'name': 'hoarder_bag_strap_slot_L', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_strap_slot_R_39846': { - 'hash': 39846, - 'name': 'hoarder_bag_strap_slot_R', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_strap_top_buckle_L_39922': { - 'hash': 39922, - 'name': 'hoarder_bag_strap_top_buckle_L', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_strap_top_buckle_R_39918': { - 'hash': 39918, - 'name': 'hoarder_bag_strap_top_buckle_R', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_topDetail_01_39910': { - 'hash': 39910, - 'name': 'hoarder_bag_topDetail_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'hoarder_bag_topDetail_02_39842': { - 'hash': 39842, - 'name': 'hoarder_bag_topDetail_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_handle_body_14308': { - 'hash': 14308, - 'name': 'standard_bag_handle_body', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_handle_wraps_14304': { - 'hash': 14304, - 'name': 'standard_bag_handle_wraps', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'HolidayRewardDisplay': { - 'hash': 32158, - 'name': 'HolidayRewardDisplay', - 'embedded': { - 'HolidayRewardDisplay_32140': { - 'hash': 32140, - 'name': 'HolidayRewardDisplay', - 'savables': {} - } - } - }, - 'Hot_Coalbed': { - 'hash': 41234, - 'name': 'Hot Coalbed', - 'embedded': { - 'Heating_Bit_26176': { - 'hash': 26176, - 'name': 'Heating Bit', - 'savables': {} - }, - 'Hot_Coalbed_26204': { - 'hash': 26204, - 'name': 'Hot Coalbed', - 'savables': {} - }, - 'Hurting_Bit_26178': { - 'hash': 26178, - 'name': 'Hurting Bit', - 'savables': {} - } - } - }, - 'Hover_Piece': { - 'hash': 50934, - 'name': 'Hover Piece', - 'embedded': { - 'Hover_Piece_5676': { - 'hash': 5676, - 'name': 'Hover Piece', - 'savables': {} - } - } - }, - 'Infinite_Fire': { - 'hash': 5172, - 'name': 'Infinite Fire', - 'embedded': { - 'Fire_8488': { - 'hash': 8488, - 'name': 'Fire', - 'savables': { - 'Fire': { - 'hash': 3457519710, - 'name': 'Fire' - } - } - }, - 'Infinite_Fire_24372': { - 'hash': 24372, - 'name': 'Infinite Fire', - 'savables': { - 'BasicDecay': { - 'hash': 3801256786, - 'name': 'BasicDecay' - } - } - }, - 'Spawner_49628': { - 'hash': 49628, - 'name': 'Spawner', - 'savables': {} - } - } - }, - 'Info_Board': { - 'hash': 51114, - 'name': 'Info Board', - 'embedded': { - 'Info_Board_63822': { - 'hash': 63822, - 'name': 'Info Board', - 'savables': { - 'InfoBoard': { - 'hash': 3431876266, - 'name': 'InfoBoard' - } - } - } - } - }, - 'Ingredient_Generator_Shelf': { - 'hash': 51096, - 'name': 'Ingredient Generator Shelf', - 'embedded': { - 'Dock_2780': { - 'hash': 2780, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_58082': { - 'hash': 58082, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_58084': { - 'hash': 58084, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_58086': { - 'hash': 58086, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_58088': { - 'hash': 58088, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_58090': { - 'hash': 58090, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_58092': { - 'hash': 58092, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_58094': { - 'hash': 58094, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_58096': { - 'hash': 58096, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_58098': { - 'hash': 58098, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Ingredient_Generator_Shelf_51098': { - 'hash': 51098, - 'name': 'Ingredient Generator Shelf', - 'savables': {} - }, - 'Recipe_Dock_60388': { - 'hash': 60388, - 'name': 'Recipe Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - } - } - }, - 'Int_Range_Operator': { - 'hash': 55740, - 'name': 'Int Range Operator', - 'embedded': { - 'Int_Range_Operator_13344': { - 'hash': 13344, - 'name': 'Int Range Operator', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'LogicIntRangeReceiver': { - 'hash': 2610542999, - 'name': 'LogicIntRangeReceiver' - } - } - } - } - }, - 'Iron_Boulder': { - 'hash': 45344, - 'name': 'Iron Boulder', - 'embedded': { - 'Iron_Boulder_49644': { - 'hash': 49644, - 'name': 'Iron Boulder', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Spawn_Origin_48914': { - 'hash': 48914, - 'name': 'Spawn Origin', - 'savables': {} - } - } - }, - 'Iron_Boulder_Parts': { - 'hash': 18070, - 'name': 'Iron_Boulder_Parts', - 'embedded': { - 'Iron_Boulder_Part_01_64822': { - 'hash': 64822, - 'name': 'Iron_Boulder_Part_01', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Iron_Boulder_Part_02_64818': { - 'hash': 64818, - 'name': 'Iron_Boulder_Part_02', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Iron_Boulder_Part_03_64806': { - 'hash': 64806, - 'name': 'Iron_Boulder_Part_03', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Iron_Boulder_Part_04_64814': { - 'hash': 64814, - 'name': 'Iron_Boulder_Part_04', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Iron_Boulder_Part_05_64810': { - 'hash': 64810, - 'name': 'Iron_Boulder_Part_05', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Iron_Boulder_Part_06_64826': { - 'hash': 64826, - 'name': 'Iron_Boulder_Part_06', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Iron_Boulder_Parts_64778': { - 'hash': 64778, - 'name': 'Iron_Boulder_Parts', - 'savables': {} - } - } - }, - 'Iron_Boulder_Training': { - 'hash': 10140, - 'name': 'Iron Boulder Training', - 'embedded': { - 'Iron_Boulder_Training_10130': { - 'hash': 10130, - 'name': 'Iron Boulder Training', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Spawn_Origin_48914': { - 'hash': 48914, - 'name': 'Spawn Origin', - 'savables': {} - } - } - }, - 'Iron_Cluster': { - 'hash': 28272, - 'name': 'Iron Cluster', - 'embedded': { - 'Iron_Cluster_18314': { - 'hash': 18314, - 'name': 'Iron Cluster', - 'savables': {} - } - } - }, - 'Iron_Ingot': { - 'hash': 23012, - 'name': 'Iron Ingot', - 'embedded': { - 'Heat_Point_Collection_13170': { - 'hash': 13170, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Iron_Ingot_22900': { - 'hash': 22900, - 'name': 'Iron Ingot', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Iron_Ore': { - 'hash': 61652, - 'name': 'Iron Ore', - 'embedded': { - 'Iron_Ore_37686': { - 'hash': 37686, - 'name': 'Iron Ore', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Ka_Karimata_Arrow': { - 'hash': 960, - 'name': 'Ka Karimata Arrow', - 'embedded': { - 'Ka_Karimata_Arrow_43746': { - 'hash': 43746, - 'name': 'Ka Karimata Arrow', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'Embeddable': { - 'hash': 22446553, - 'name': 'Embeddable' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Tip_58698': { - 'hash': 58698, - 'name': 'Tip', - 'savables': {} - } - } - }, - 'Katana': { - 'hash': 34994, - 'name': 'Katana', - 'embedded': { - 'Katana_36330': { - 'hash': 36330, - 'name': 'Katana', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'Enchantable': { - 'hash': 4134534481, - 'name': 'Enchantable' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Key_Standard': { - 'hash': 39744, - 'name': 'Key Standard', - 'embedded': { - 'Key_Standard_26420': { - 'hash': 26420, - 'name': 'Key Standard', - 'savables': { - 'KeyItem': { - 'hash': 414036426, - 'name': 'KeyItem' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Kunai': { - 'hash': 32002, - 'name': 'Kunai', - 'embedded': { - 'Kunai_36330': { - 'hash': 36330, - 'name': 'Kunai', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'Embeddable': { - 'hash': 22446553, - 'name': 'Embeddable' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Ladder': { - 'hash': 56168, - 'name': 'Ladder', - 'embedded': { - 'Ladder_53890': { - 'hash': 53890, - 'name': 'Ladder', - 'savables': {} - } - } - }, - 'Lantern': { - 'hash': 41760, - 'name': 'Lantern', - 'embedded': { - 'Fire_54948': { - 'hash': 54948, - 'name': 'Fire', - 'savables': { - 'Fire': { - 'hash': 3457519710, - 'name': 'Fire' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Fuel_Dock_63110': { - 'hash': 63110, - 'name': 'Fuel Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Lantern_56450': { - 'hash': 56450, - 'name': 'Lantern', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'lantern_arm_28726': { - 'hash': 28726, - 'name': 'lantern_arm', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'lantern_bar_01_28734': { - 'hash': 28734, - 'name': 'lantern_bar_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'lantern_bar_02_28742': { - 'hash': 28742, - 'name': 'lantern_bar_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'lantern_bar_03_28770': { - 'hash': 28770, - 'name': 'lantern_bar_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'lantern_bar_04_28766': { - 'hash': 28766, - 'name': 'lantern_bar_04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'lantern_bar_05_28738': { - 'hash': 28738, - 'name': 'lantern_bar_05', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'lantern_bar_06_28778': { - 'hash': 28778, - 'name': 'lantern_bar_06', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'lantern_bar_07_28750': { - 'hash': 28750, - 'name': 'lantern_bar_07', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'lantern_base_28746': { - 'hash': 28746, - 'name': 'lantern_base', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'lantern_face_28754': { - 'hash': 28754, - 'name': 'lantern_face', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'lantern_handle_28758': { - 'hash': 28758, - 'name': 'lantern_handle', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'lantern_topCap_28762': { - 'hash': 28762, - 'name': 'lantern_topCap', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'lantern_topSwivel_28774': { - 'hash': 28774, - 'name': 'lantern_topSwivel', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'lantern_visor_28730': { - 'hash': 28730, - 'name': 'lantern_visor', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Large_Cave_Mushroom': { - 'hash': 29690, - 'name': 'Large Cave Mushroom', - 'embedded': { - 'Large_Cave_Mushroom_30160': { - 'hash': 30160, - 'name': 'Large Cave Mushroom', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Large_Cave_Mushroom_Body_30160': { - 'hash': 30160, - 'name': 'Large Cave Mushroom Body', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Spawner_26386': { - 'hash': 26386, - 'name': 'Spawner', - 'savables': {} - }, - 'cave_mushroom_headEnd_jnt_22906': { - 'hash': 22906, - 'name': 'cave_mushroom_headEnd_jnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'cave_mushroom_spine_jnt_27926': { - 'hash': 27926, - 'name': 'cave_mushroom_spine_jnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Large_Cave_Mushroom_Cluster': { - 'hash': 2422, - 'name': 'Large Cave Mushroom Cluster', - 'embedded': { - 'Large_Cave_Mushroom_Cluster_61380': { - 'hash': 61380, - 'name': 'Large Cave Mushroom Cluster', - 'savables': {} - } - } - }, - 'Large_Cave_Mushroom_OLD': { - 'hash': 36866, - 'name': 'Large Cave Mushroom OLD', - 'embedded': { - 'Large_Cave_Mushroom_OLD_30160': { - 'hash': 30160, - 'name': 'Large Cave Mushroom OLD', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Spawner_26386': { - 'hash': 26386, - 'name': 'Spawner', - 'savables': {} - }, - 'cave_mushroom_headEnd_jnt_22906': { - 'hash': 22906, - 'name': 'cave_mushroom_headEnd_jnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'cave_mushroom_spine_jnt_27926': { - 'hash': 27926, - 'name': 'cave_mushroom_spine_jnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Large_Guard_Rectangle': { - 'hash': 9304, - 'name': 'Large Guard Rectangle', - 'embedded': { - 'Heat_Point_Collection_57820': { - 'hash': 57820, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_Large_SwordType_Craft_51894': { - 'hash': 51894, - 'name': 'Insert Large SwordType Craft', - 'savables': {} - }, - 'Large_Guard_Rectangle_51938': { - 'hash': 51938, - 'name': 'Large Guard Rectangle', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_Large_SwordType_51896': { - 'hash': 51896, - 'name': 'Slot Large SwordType', - 'savables': {} - } - } - }, - 'Large_Guard_TShape': { - 'hash': 23552, - 'name': 'Large Guard TShape', - 'embedded': { - 'Heat_Point_Collection_58132': { - 'hash': 58132, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_Large_SwordType_Craft_23506': { - 'hash': 23506, - 'name': 'Insert Large SwordType Craft', - 'savables': {} - }, - 'Large_Guard_TShape_23550': { - 'hash': 23550, - 'name': 'Large Guard TShape', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_Large_SwordType_23508': { - 'hash': 23508, - 'name': 'Slot Large SwordType', - 'savables': {} - } - } - }, - 'Large_Guard_Wedge': { - 'hash': 39010, - 'name': 'Large Guard Wedge', - 'embedded': { - 'Heat_Point_Collection_58440': { - 'hash': 58440, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_Large_SwordType_Craft_38964': { - 'hash': 38964, - 'name': 'Insert Large SwordType Craft', - 'savables': {} - }, - 'Large_Guard_Wedge_39008': { - 'hash': 39008, - 'name': 'Large Guard Wedge', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_Large_SwordType_38966': { - 'hash': 38966, - 'name': 'Slot Large SwordType', - 'savables': {} - } - } - }, - 'Large_Longsword_Blade': { - 'hash': 56124, - 'name': 'Large Longsword Blade', - 'embedded': { - 'Heat_Point_Collection_62508': { - 'hash': 62508, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_Large_SwordType_31944': { - 'hash': 31944, - 'name': 'Insert Large SwordType', - 'savables': {} - }, - 'Large_Longsword_Blade_53840': { - 'hash': 53840, - 'name': 'Large Longsword Blade', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'large_longsword_LOD0_45786': { - 'hash': 45786, - 'name': 'large_longsword_LOD0', - 'savables': {} - } - } - }, - 'Large_Mythril_Boulder': { - 'hash': 53902, - 'name': 'Large Mythril Boulder', - 'embedded': { - 'Large_Mythril_Boulder_29328': { - 'hash': 29328, - 'name': 'Large Mythril Boulder', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Spawn_Origin_18860': { - 'hash': 18860, - 'name': 'Spawn Origin', - 'savables': {} - } - } - }, - 'Large_Spiked_Wooden_Club': { - 'hash': 55914, - 'name': 'Large Spiked Wooden Club', - 'embedded': { - 'Large_Spiked_Wooden_Club_55724': { - 'hash': 55724, - 'name': 'Large Spiked Wooden Club', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Large_Sword': { - 'hash': 8374, - 'name': 'Large_Sword', - 'embedded': {} - }, - 'Lava_Pool': { - 'hash': 34696, - 'name': 'Lava Pool', - 'embedded': { - 'Heat_Bit_35218': { - 'hash': 35218, - 'name': 'Heat Bit', - 'savables': {} - }, - 'Hurt_Bit_30842': { - 'hash': 30842, - 'name': 'Hurt Bit', - 'savables': {} - }, - 'Lava_Pool_16578': { - 'hash': 16578, - 'name': 'Lava Pool', - 'savables': {} - }, - 'Slow_Bit_34974': { - 'hash': 34974, - 'name': 'Slow Bit', - 'savables': {} - } - } - }, - 'Leaderboard': { - 'hash': 44390, - 'name': 'Leaderboard', - 'embedded': { - 'Leaderboard_27564': { - 'hash': 27564, - 'name': 'Leaderboard', - 'savables': { - 'Leaderboard': { - 'hash': 3257374625, - 'name': 'Leaderboard' - } - } - } - } - }, - 'Lectern': { - 'hash': 59986, - 'name': 'Lectern', - 'embedded': { - 'Candle_Flame_30100': { - 'hash': 30100, - 'name': 'Candle Flame', - 'savables': { - 'Fire': { - 'hash': 3457519710, - 'name': 'Fire' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Lectern_57672': { - 'hash': 57672, - 'name': 'Lectern', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - }, - 'BookRestrictor': { - 'hash': 2629079826, - 'name': 'BookRestrictor' - } - } - } - } - }, - 'Lectern_Flat': { - 'hash': 45828, - 'name': 'Lectern Flat', - 'embedded': { - 'Lectern_Flat_45826': { - 'hash': 45826, - 'name': 'Lectern Flat', - 'savables': {} - } - } - }, - 'Leveling_Dummy': { - 'hash': 44224, - 'name': 'Leveling Dummy', - 'embedded': { - 'Leveling_Dummy_39942': { - 'hash': 39942, - 'name': 'Leveling Dummy', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'dummy_arm_l_01_jnt_46272': { - 'hash': 46272, - 'name': 'dummy_arm_l_01_jnt', - 'savables': {} - }, - 'dummy_arm_l_02_jnt_46248': { - 'hash': 46248, - 'name': 'dummy_arm_l_02_jnt', - 'savables': {} - }, - 'dummy_arm_l_03_jnt_46250': { - 'hash': 46250, - 'name': 'dummy_arm_l_03_jnt', - 'savables': {} - }, - 'dummy_arm_r_01_jnt_46246': { - 'hash': 46246, - 'name': 'dummy_arm_r_01_jnt', - 'savables': {} - }, - 'dummy_arm_r_02_jnt_46254': { - 'hash': 46254, - 'name': 'dummy_arm_r_02_jnt', - 'savables': {} - }, - 'dummy_arm_r_03_jnt_46256': { - 'hash': 46256, - 'name': 'dummy_arm_r_03_jnt', - 'savables': {} - }, - 'dummy_head_01_jnt_46270': { - 'hash': 46270, - 'name': 'dummy_head_01_jnt', - 'savables': {} - }, - 'dummy_head_02_jnt_46264': { - 'hash': 46264, - 'name': 'dummy_head_02_jnt', - 'savables': {} - }, - 'dummy_head_03_jnt_46262': { - 'hash': 46262, - 'name': 'dummy_head_03_jnt', - 'savables': {} - }, - 'dummy_neck_jnt_46268': { - 'hash': 46268, - 'name': 'dummy_neck_jnt', - 'savables': {} - }, - 'dummy_spineMid_jnt_46274': { - 'hash': 46274, - 'name': 'dummy_spineMid_jnt', - 'savables': {} - }, - 'dummy_spine_01_jnt_46258': { - 'hash': 46258, - 'name': 'dummy_spine_01_jnt', - 'savables': {} - }, - 'dummy_spine_02_jnt_46260': { - 'hash': 46260, - 'name': 'dummy_spine_02_jnt', - 'savables': {} - }, - 'dummy_spine_03_jnt_46266': { - 'hash': 46266, - 'name': 'dummy_spine_03_jnt', - 'savables': {} - }, - 'dummy_sternum_jnt_46252': { - 'hash': 46252, - 'name': 'dummy_sternum_jnt', - 'savables': {} - } - } - }, - 'Lever': { - 'hash': 27966, - 'name': 'Lever', - 'embedded': {} - }, - 'LightPuzzle_Test': { - 'hash': 8524, - 'name': 'LightPuzzle_Test', - 'embedded': {} - }, - 'Liquid_Pump': { - 'hash': 39174, - 'name': 'Liquid_Pump', - 'embedded': {} - }, - 'Lockbox': { - 'hash': 6974, - 'name': 'Lockbox', - 'embedded': { - 'Chunk_19700': { - 'hash': 19700, - 'name': 'Chunk', - 'savables': {} - }, - 'Hand_Touch_46540': { - 'hash': 46540, - 'name': 'Hand Touch', - 'savables': {} - }, - 'Lockbox_9078': { - 'hash': 9078, - 'name': 'Lockbox', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - } - } - }, - 'Lockbox_Docks': { - 'hash': 2226, - 'name': 'Lockbox Docks', - 'embedded': { - 'Bottom_Dock_1_48412': { - 'hash': 48412, - 'name': 'Bottom Dock 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_2_48414': { - 'hash': 48414, - 'name': 'Bottom Dock 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_3_48416': { - 'hash': 48416, - 'name': 'Bottom Dock 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_4_48422': { - 'hash': 48422, - 'name': 'Bottom Dock 4', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_5_48420': { - 'hash': 48420, - 'name': 'Bottom Dock 5', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_6_48418': { - 'hash': 48418, - 'name': 'Bottom Dock 6', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Lockbox_Docks_64298': { - 'hash': 64298, - 'name': 'Lockbox Docks', - 'savables': {} - } - } - }, - 'Log_Mallet': { - 'hash': 42518, - 'name': 'Log_Mallet', - 'embedded': {} - }, - 'Log_Mallet_v02': { - 'hash': 42030, - 'name': 'Log_Mallet_v02', - 'embedded': {} - }, - 'LogicBoolOneTimeActivate': { - 'hash': 28136, - 'name': 'LogicBoolOneTimeActivate', - 'embedded': { - 'LogicBoolOneTimeActivate_28066': { - 'hash': 28066, - 'name': 'LogicBoolOneTimeActivate', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - } - } - } - } - }, - 'LogicFloatChangeOnBool': { - 'hash': 62220, - 'name': 'LogicFloatChangeOnBool', - 'embedded': { - 'LogicFloatChangeOnBool_56894': { - 'hash': 56894, - 'name': 'LogicFloatChangeOnBool', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicFloatChangeOnBool': { - 'hash': 200292695, - 'name': 'LogicFloatChangeOnBool' - }, - 'LogicFloatSender': { - 'hash': 2120963769, - 'name': 'LogicFloatSender' - } - } - } - } - }, - 'LogicFloatReset': { - 'hash': 57100, - 'name': 'LogicFloatReset', - 'embedded': { - 'LogicFloatReset_56894': { - 'hash': 56894, - 'name': 'LogicFloatReset', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicFloatReceiver': { - 'hash': 3188272159, - 'name': 'LogicFloatReceiver' - }, - 'LogicFloatReset': { - 'hash': 3245685963, - 'name': 'LogicFloatReset' - }, - 'LogicFloatSender': { - 'hash': 2120963769, - 'name': 'LogicFloatSender' - } - } - } - } - }, - 'LogicReset': { - 'hash': 36976, - 'name': 'LogicReset', - 'embedded': { - 'LogicReset_42904': { - 'hash': 42904, - 'name': 'LogicReset', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicReset': { - 'hash': 1934129787, - 'name': 'LogicReset' - } - } - } - } - }, - 'Logic_Context': { - 'hash': 34630, - 'name': 'Logic Context', - 'embedded': { - 'Logic_Context_34154': { - 'hash': 34154, - 'name': 'Logic Context', - 'savables': { - 'GlobalLogicManager': { - 'hash': 967932020, - 'name': 'GlobalLogicManager' - } - } - } - } - }, - 'Logic_Int_To_Bool': { - 'hash': 2454, - 'name': 'Logic Int To Bool', - 'embedded': { - 'Logic_Int_To_Bool_9620': { - 'hash': 9620, - 'name': 'Logic Int To Bool', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'LogicIntReceiver': { - 'hash': 1081247904, - 'name': 'LogicIntReceiver' - }, - 'LogicIntToBool': { - 'hash': 2253011220, - 'name': 'LogicIntToBool' - } - } - } - } - }, - 'Logic_Operator': { - 'hash': 13390, - 'name': 'Logic Operator', - 'embedded': { - 'Logic_Operator_13344': { - 'hash': 13344, - 'name': 'Logic Operator', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'LogicGateReceiver': { - 'hash': 1391720462, - 'name': 'LogicGateReceiver' - } - } - } - } - }, - 'Long_S_Hook': { - 'hash': 20598, - 'name': 'Long S Hook', - 'embedded': { - 'Hangable_Dock_5626': { - 'hash': 5626, - 'name': 'Hangable Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Long_S_Hook_17940': { - 'hash': 17940, - 'name': 'Long S Hook', - 'savables': {} - } - } - }, - 'Loot_Module': { - 'hash': 29544, - 'name': 'Loot_Module', - 'embedded': {} - }, - 'MRK_Activation_Line': { - 'hash': 24096, - 'name': 'MRK Activation Line', - 'embedded': { - 'Glow_Ended_44912': { - 'hash': 44912, - 'name': 'Glow Ended', - 'savables': {} - }, - 'Glow_Started_44908': { - 'hash': 44908, - 'name': 'Glow Started', - 'savables': {} - }, - 'MRK_Activation_Line_22336': { - 'hash': 22336, - 'name': 'MRK Activation Line', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - } - } - } - } - }, - 'MRK_Automated_Pipe_Hazard_Elevator': { - 'hash': 38546, - 'name': 'MRK Automated Pipe Hazard Elevator', - 'embedded': { - 'Hurting_Bit_26178': { - 'hash': 26178, - 'name': 'Hurting Bit', - 'savables': {} - }, - 'MRK_Automated_Pipe_Hazard_Elevator_21038': { - 'hash': 21038, - 'name': 'MRK Automated Pipe Hazard Elevator', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - } - } - }, - 'Reset_Receiver_17642': { - 'hash': 17642, - 'name': 'Reset Receiver', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - } - } - }, - 'Steam_Spray_61896': { - 'hash': 61896, - 'name': 'Steam Spray', - 'savables': {} - }, - 'Steam_Start_37968': { - 'hash': 37968, - 'name': 'Steam Start', - 'savables': {} - }, - 'mrk_risingPipe_body_20878': { - 'hash': 20878, - 'name': 'mrk_risingPipe_body', - 'savables': { - 'CurveOutput': { - 'hash': 2576456808, - 'name': 'CurveOutput' - } - } - } - } - }, - 'MRK_Automated_Pipe_Hazard_Elevator_7.6_Variant': { - 'hash': 61754, - 'name': 'MRK Automated Pipe Hazard Elevator 7.6 Variant', - 'embedded': { - 'Hurting_Bit_26178': { - 'hash': 26178, - 'name': 'Hurting Bit', - 'savables': {} - }, - 'MRK_Automated_Pipe_Hazard_Elevator_7.6_Variant_21038': { - 'hash': 21038, - 'name': 'MRK Automated Pipe Hazard Elevator 7.6 Variant', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - } - } - }, - 'Reset_Receiver_17642': { - 'hash': 17642, - 'name': 'Reset Receiver', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - } - } - }, - 'Steam_Spray_61896': { - 'hash': 61896, - 'name': 'Steam Spray', - 'savables': {} - }, - 'Steam_Start_37968': { - 'hash': 37968, - 'name': 'Steam Start', - 'savables': {} - }, - 'mrk_risingPipe_body_20878': { - 'hash': 20878, - 'name': 'mrk_risingPipe_body', - 'savables': { - 'CurveOutput': { - 'hash': 2576456808, - 'name': 'CurveOutput' - } - } - } - } - }, - 'MRK_Automated_Pipe_Hazard_Elevator_Large_Inverse_Variant': { - 'hash': 34664, - 'name': 'MRK Automated Pipe Hazard Elevator Large Inverse Variant', - 'embedded': { - 'Hurting_Bit_26178': { - 'hash': 26178, - 'name': 'Hurting Bit', - 'savables': {} - }, - 'MRK_Automated_Pipe_Hazard_Elevator_Large_Inverse_Variant_21038': { - 'hash': 21038, - 'name': 'MRK Automated Pipe Hazard Elevator Large Inverse Variant', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - } - } - }, - 'Reset_Receiver_17642': { - 'hash': 17642, - 'name': 'Reset Receiver', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - } - } - }, - 'Steam_Spray_61896': { - 'hash': 61896, - 'name': 'Steam Spray', - 'savables': {} - }, - 'Steam_Start_37968': { - 'hash': 37968, - 'name': 'Steam Start', - 'savables': {} - }, - 'mrk_risingPipe_body_20878': { - 'hash': 20878, - 'name': 'mrk_risingPipe_body', - 'savables': { - 'CurveOutput': { - 'hash': 2576456808, - 'name': 'CurveOutput' - } - } - } - } - }, - 'MRK_Automated_Pipe_Hazard_Elevator_Tall_Variant': { - 'hash': 37626, - 'name': 'MRK Automated Pipe Hazard Elevator Tall Variant', - 'embedded': { - 'Hurting_Bit_26178': { - 'hash': 26178, - 'name': 'Hurting Bit', - 'savables': {} - }, - 'MRK_Automated_Pipe_Hazard_Elevator_Tall_Variant_21038': { - 'hash': 21038, - 'name': 'MRK Automated Pipe Hazard Elevator Tall Variant', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - } - } - }, - 'Reset_Receiver_17642': { - 'hash': 17642, - 'name': 'Reset Receiver', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - } - } - }, - 'Steam_Spray_61896': { - 'hash': 61896, - 'name': 'Steam Spray', - 'savables': {} - }, - 'Steam_Start_37968': { - 'hash': 37968, - 'name': 'Steam Start', - 'savables': {} - }, - 'mrk_risingPipe_body_20878': { - 'hash': 20878, - 'name': 'mrk_risingPipe_body', - 'savables': { - 'CurveOutput': { - 'hash': 2576456808, - 'name': 'CurveOutput' - } - } - } - } - }, - 'MRK_Fuel_Core': { - 'hash': 65358, - 'name': 'MRK Fuel Core', - 'embedded': { - 'MRK_Fuel_Core_63598': { - 'hash': 63598, - 'name': 'MRK Fuel Core', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MRK_Horizontal_Lift': { - 'hash': 37822, - 'name': 'MRK Horizontal Lift', - 'embedded': { - 'MRK_Horizontal_Lift_37846': { - 'hash': 37846, - 'name': 'MRK Horizontal Lift', - 'savables': { - 'LogicFloatReceiver': { - 'hash': 3188272159, - 'name': 'LogicFloatReceiver' - }, - 'NetworkedFloatStream': { - 'hash': 2127962967, - 'name': 'NetworkedFloatStream' - } - } - }, - 'Platform_57570': { - 'hash': 57570, - 'name': 'Platform', - 'savables': { - 'WayPointPath': { - 'hash': 1063725326, - 'name': 'WayPointPath' - } - } - } - } - }, - 'MRK_Lantern_01': { - 'hash': 36130, - 'name': 'MRK Lantern_01', - 'embedded': { - 'MRK_Lantern_01_992': { - 'hash': 992, - 'name': 'MRK Lantern_01', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - } - } - } - } - }, - 'MRK_Lantern_Fire': { - 'hash': 29468, - 'name': 'MRK Lantern Fire', - 'embedded': { - 'Fire_29440': { - 'hash': 29440, - 'name': 'Fire', - 'savables': { - 'Fire': { - 'hash': 3457519710, - 'name': 'Fire' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MRK_Lantern_Fire_29466': { - 'hash': 29466, - 'name': 'MRK Lantern Fire', - 'savables': { - 'FireLogic': { - 'hash': 1509838052, - 'name': 'FireLogic' - }, - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - } - } - } - } - }, - 'MRK_Large_Gear_Variant': { - 'hash': 29874, - 'name': 'MRK Large Gear Variant', - 'embedded': { - 'MRK_Large_Gear_Variant_26800': { - 'hash': 26800, - 'name': 'MRK Large Gear Variant', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - } - } - }, - 'Start_Rotating_5010': { - 'hash': 5010, - 'name': 'Start Rotating', - 'savables': {} - }, - 'Stop_Rotating_4822': { - 'hash': 4822, - 'name': 'Stop Rotating', - 'savables': {} - } - } - }, - 'MRK_Large_Lever': { - 'hash': 12812, - 'name': 'MRK Large Lever', - 'embedded': { - 'MRK_Large_Lever_9436': { - 'hash': 9436, - 'name': 'MRK Large Lever', - 'savables': { - 'Lever': { - 'hash': 1594932294, - 'name': 'Lever' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - } - } - }, - 'mrk_large_lever_handle_ROT_2408': { - 'hash': 2408, - 'name': 'mrk_large_lever_handle_ROT', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'mrk_large_lever_handle_grip_44324': { - 'hash': 44324, - 'name': 'mrk_large_lever_handle_grip', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'MRK_Liftable_Pipe_Gate': { - 'hash': 9344, - 'name': 'MRK Liftable Pipe Gate', - 'embedded': { - 'Bottom_Handle_14368': { - 'hash': 14368, - 'name': 'Bottom Handle', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Handle_60880': { - 'hash': 60880, - 'name': 'Handle', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Handle_9490': { - 'hash': 9490, - 'name': 'Handle', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'MRK_Liftable_Pipe_Gate_47896': { - 'hash': 47896, - 'name': 'MRK Liftable Pipe Gate', - 'savables': {} - }, - 'mrk_pipe_gate_door_41532': { - 'hash': 41532, - 'name': 'mrk_pipe_gate_door', - 'savables': { - 'MovePickup': { - 'hash': 1874870249, - 'name': 'MovePickup' - } - } - } - } - }, - 'MRK_Molten_Core': { - 'hash': 51764, - 'name': 'MRK Molten Core', - 'embedded': { - 'MRK_Molten_Core_21206': { - 'hash': 21206, - 'name': 'MRK Molten Core', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MRK_Pipe_Gate': { - 'hash': 49320, - 'name': 'MRK Pipe Gate', - 'embedded': { - 'MRK_Pipe_Gate_47896': { - 'hash': 47896, - 'name': 'MRK Pipe Gate', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'SlidingDoor': { - 'hash': 3583462804, - 'name': 'SlidingDoor' - } - } - } - } - }, - 'MRK_Puzzle_Core_01': { - 'hash': 14158, - 'name': 'MRK Puzzle Core 01', - 'embedded': { - 'MRK_Puzzle_Core_01_12014': { - 'hash': 12014, - 'name': 'MRK Puzzle Core 01', - 'savables': { - 'MultiHandPickup': { - 'hash': 1556697998, - 'name': 'MultiHandPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'MRK_Puzzle_Core_02': { - 'hash': 28416, - 'name': 'MRK Puzzle Core 02', - 'embedded': { - 'MRK_Puzzle_Core_02_12014': { - 'hash': 12014, - 'name': 'MRK Puzzle Core 02', - 'savables': { - 'MultiHandPickup': { - 'hash': 1556697998, - 'name': 'MultiHandPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'MRK_Puzzle_Core_Initial_Stand_01_Variant': { - 'hash': 60550, - 'name': 'MRK Puzzle Core Initial Stand 01 Variant', - 'embedded': { - 'MRK_Puzzle_Core_Initial_Stand_01_Variant_57012': { - 'hash': 57012, - 'name': 'MRK Puzzle Core Initial Stand 01 Variant', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'LogicIntSender': { - 'hash': 2880587164, - 'name': 'LogicIntSender' - }, - 'PlaceItemPuzzleLogic': { - 'hash': 1001395212, - 'name': 'PlaceItemPuzzleLogic' - } - } - }, - 'Pedestal_Dock_27002': { - 'hash': 27002, - 'name': 'Pedestal Dock', - 'savables': { - 'PickupDockPedestalSpawn': { - 'hash': 2592242915, - 'name': 'PickupDockPedestalSpawn' - } - } - } - } - }, - 'MRK_Puzzle_Core_Initial_Stand_02_Variant': { - 'hash': 30056, - 'name': 'MRK Puzzle Core Initial Stand 02 Variant', - 'embedded': { - 'MRK_Puzzle_Core_Initial_Stand_02_Variant_57012': { - 'hash': 57012, - 'name': 'MRK Puzzle Core Initial Stand 02 Variant', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'LogicIntSender': { - 'hash': 2880587164, - 'name': 'LogicIntSender' - }, - 'PlaceItemPuzzleLogic': { - 'hash': 1001395212, - 'name': 'PlaceItemPuzzleLogic' - } - } - }, - 'Pedestal_Dock_27002': { - 'hash': 27002, - 'name': 'Pedestal Dock', - 'savables': { - 'PickupDockPedestalSpawn': { - 'hash': 2592242915, - 'name': 'PickupDockPedestalSpawn' - } - } - } - } - }, - 'MRK_Puzzle_Core_Stand_01': { - 'hash': 58540, - 'name': 'MRK Puzzle Core Stand 01', - 'embedded': { - 'MRK_Puzzle_Core_Stand_01_57012': { - 'hash': 57012, - 'name': 'MRK Puzzle Core Stand 01', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'LogicIntSender': { - 'hash': 2880587164, - 'name': 'LogicIntSender' - }, - 'PlaceItemPuzzleLogic': { - 'hash': 1001395212, - 'name': 'PlaceItemPuzzleLogic' - } - } - }, - 'Pedestal_Dock_27002': { - 'hash': 27002, - 'name': 'Pedestal Dock', - 'savables': { - 'PickupDockPedestalSpawn': { - 'hash': 2592242915, - 'name': 'PickupDockPedestalSpawn' - } - } - } - } - }, - 'MRK_Puzzle_Core_Stand_02': { - 'hash': 34594, - 'name': 'MRK Puzzle Core Stand 02', - 'embedded': { - 'MRK_Puzzle_Core_Stand_02_57012': { - 'hash': 57012, - 'name': 'MRK Puzzle Core Stand 02', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'LogicIntSender': { - 'hash': 2880587164, - 'name': 'LogicIntSender' - }, - 'PlaceItemPuzzleLogic': { - 'hash': 1001395212, - 'name': 'PlaceItemPuzzleLogic' - } - } - }, - 'Pedestal_Dock_27002': { - 'hash': 27002, - 'name': 'Pedestal Dock', - 'savables': { - 'PickupDockPedestalSpawn': { - 'hash': 2592242915, - 'name': 'PickupDockPedestalSpawn' - } - } - } - } - }, - 'MRK_Slip_Door': { - 'hash': 14114, - 'name': 'MRK Slip Door', - 'embedded': { - 'Grip_22142': { - 'hash': 22142, - 'name': 'Grip', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_22248': { - 'hash': 22248, - 'name': 'Grip', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_Point_21894': { - 'hash': 21894, - 'name': 'Grip Point', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_Point_21920': { - 'hash': 21920, - 'name': 'Grip Point', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_Point_22194': { - 'hash': 22194, - 'name': 'Grip Point', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_Point_22228': { - 'hash': 22228, - 'name': 'Grip Point', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_Point_22240': { - 'hash': 22240, - 'name': 'Grip Point', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'MRK_Slip_Door_26828': { - 'hash': 26828, - 'name': 'MRK Slip Door', - 'savables': {} - }, - 'mrk_slipDoor_gate_26512': { - 'hash': 26512, - 'name': 'mrk_slipDoor_gate', - 'savables': { - 'MovePickup': { - 'hash': 1874870249, - 'name': 'MovePickup' - } - } - } - } - }, - 'MRK_Small_Lever': { - 'hash': 1330, - 'name': 'MRK Small Lever', - 'embedded': { - 'MRK_Small_Lever_9436': { - 'hash': 9436, - 'name': 'MRK Small Lever', - 'savables': { - 'Lever': { - 'hash': 1594932294, - 'name': 'Lever' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - } - } - }, - 'mrk_large_lever_handle_grip_44324': { - 'hash': 44324, - 'name': 'mrk_large_lever_handle_grip', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'mrk_small_lever_handle_ROT_29376': { - 'hash': 29376, - 'name': 'mrk_small_lever_handle_ROT', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'MRK_Smelter_Gem_Pedestal_1': { - 'hash': 33006, - 'name': 'MRK Smelter Gem Pedestal 1', - 'embedded': { - 'MRK_Smelter_Gem_Pedestal_1_27194': { - 'hash': 27194, - 'name': 'MRK Smelter Gem Pedestal 1', - 'savables': {} - }, - 'Pedestal_Dock_27002': { - 'hash': 27002, - 'name': 'Pedestal Dock', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'PickupDockPedestalSpawn': { - 'hash': 2592242915, - 'name': 'PickupDockPedestalSpawn' - } - } - } - } - }, - 'MRK_Smelter_Gem_Pedestal_2': { - 'hash': 56376, - 'name': 'MRK Smelter Gem Pedestal 2', - 'embedded': { - 'MRK_Smelter_Gem_Pedestal_2_27194': { - 'hash': 27194, - 'name': 'MRK Smelter Gem Pedestal 2', - 'savables': {} - }, - 'Pedestal_Dock_27002': { - 'hash': 27002, - 'name': 'Pedestal Dock', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'PickupDockPedestalSpawn': { - 'hash': 2592242915, - 'name': 'PickupDockPedestalSpawn' - } - } - } - } - }, - 'MRK_Smelter_Gem_Pedestal_3': { - 'hash': 57516, - 'name': 'MRK Smelter Gem Pedestal 3', - 'embedded': { - 'MRK_Smelter_Gem_Pedestal_3_27194': { - 'hash': 27194, - 'name': 'MRK Smelter Gem Pedestal 3', - 'savables': {} - }, - 'Pedestal_Dock_27002': { - 'hash': 27002, - 'name': 'Pedestal Dock', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'PickupDockPedestalSpawn': { - 'hash': 2592242915, - 'name': 'PickupDockPedestalSpawn' - } - } - } - } - }, - 'MRK_TeleporterOut': { - 'hash': 49418, - 'name': 'MRK_TeleporterOut', - 'embedded': { - 'MRK_Tele_Target_38234': { - 'hash': 38234, - 'name': 'MRK Tele Target', - 'savables': {} - }, - 'MRK_TeleporterOut_7710': { - 'hash': 7710, - 'name': 'MRK_TeleporterOut', - 'savables': { - 'LogicVector3Receiver': { - 'hash': 1228539097, - 'name': 'LogicVector3Receiver' - }, - 'LogicVector3Sender': { - 'hash': 2026743731, - 'name': 'LogicVector3Sender' - }, - 'PositionProvider': { - 'hash': 3538443740, - 'name': 'PositionProvider' - }, - 'TeleportationPoint': { - 'hash': 3146178080, - 'name': 'TeleportationPoint' - } - } - }, - 'Teleporter_27092': { - 'hash': 27092, - 'name': 'Teleporter', - 'savables': {} - } - } - }, - 'MRK_Wheel_Bridge': { - 'hash': 61844, - 'name': 'MRK Wheel Bridge', - 'embedded': { - 'Crank_Rise_8062': { - 'hash': 8062, - 'name': 'Crank Rise', - 'savables': {} - }, - 'MRK_Wheel_Bridge_43884': { - 'hash': 43884, - 'name': 'MRK Wheel Bridge', - 'savables': { - 'LogicFloatReceiver': { - 'hash': 3188272159, - 'name': 'LogicFloatReceiver' - }, - 'LogicFloatSender': { - 'hash': 2120963769, - 'name': 'LogicFloatSender' - }, - 'RotatePickup': { - 'hash': 2498617949, - 'name': 'RotatePickup' - } - } - }, - 'mrk_large_handle_01_23224': { - 'hash': 23224, - 'name': 'mrk_large_handle_01', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'mrk_large_handle_01_23226': { - 'hash': 23226, - 'name': 'mrk_large_handle_01', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'mrk_large_handle_01_23228': { - 'hash': 23228, - 'name': 'mrk_large_handle_01', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'mrk_large_handle_01_23230': { - 'hash': 23230, - 'name': 'mrk_large_handle_01', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'mrk_large_handle_01_52566': { - 'hash': 52566, - 'name': 'mrk_large_handle_01', - 'savables': { - 'Crank': { - 'hash': 1588536425, - 'name': 'Crank' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'mrk_rotating_platform_ROT_35674': { - 'hash': 35674, - 'name': 'mrk_rotating_platform_ROT', - 'savables': { - 'WheelGrab': { - 'hash': 320224849, - 'name': 'WheelGrab' - } - } - } - } - }, - 'MRK_activation_lever': { - 'hash': 35030, - 'name': 'MRK_activation_lever', - 'embedded': { - 'Cost_Definition_20328': { - 'hash': 20328, - 'name': 'Cost Definition', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_22852': { - 'hash': 22852, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Gacha_Turn_15766': { - 'hash': 15766, - 'name': 'Gacha Turn', - 'savables': {} - }, - 'MRK_activation_lever_34108': { - 'hash': 34108, - 'name': 'MRK_activation_lever', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'MRK_ActivationLever': { - 'hash': 2069630919, - 'name': 'MRK_ActivationLever' - } - } - }, - 'Stop_Rotating_48244': { - 'hash': 48244, - 'name': 'Stop Rotating', - 'savables': {} - }, - 'Stop_Rotating_48620': { - 'hash': 48620, - 'name': 'Stop Rotating', - 'savables': {} - }, - 'mrk_activation_lever_ROT_8682': { - 'hash': 8682, - 'name': 'mrk_activation_lever_ROT', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'MRK_gate_01': { - 'hash': 3094, - 'name': 'MRK_gate_01', - 'embedded': { - 'MRK_gate_01_42408': { - 'hash': 42408, - 'name': 'MRK_gate_01', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'SlidingDoor': { - 'hash': 3583462804, - 'name': 'SlidingDoor' - } - } - } - } - }, - 'MRK_gate_01_1.5x_Variant': { - 'hash': 64136, - 'name': 'MRK_gate_01 1.5x Variant', - 'embedded': { - 'MRK_gate_01_1.5x_Variant_42408': { - 'hash': 42408, - 'name': 'MRK_gate_01 1.5x Variant', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'SlidingDoor': { - 'hash': 3583462804, - 'name': 'SlidingDoor' - } - } - } - } - }, - 'MRK_gate_02': { - 'hash': 54328, - 'name': 'MRK_gate_02', - 'embedded': { - 'MRK_gate_02_42408': { - 'hash': 42408, - 'name': 'MRK_gate_02', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'SlidingDoor': { - 'hash': 3583462804, - 'name': 'SlidingDoor' - } - } - } - } - }, - 'MRK_heartReceptacle_01': { - 'hash': 9566, - 'name': 'MRK_heartReceptacle_01', - 'embedded': { - 'Hand_Touch_13548': { - 'hash': 13548, - 'name': 'Hand Touch', - 'savables': {} - }, - 'MRK_heartReceptacle_01_7518': { - 'hash': 7518, - 'name': 'MRK_heartReceptacle_01', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'OneTimeUpgradeInteraction': { - 'hash': 3230087383, - 'name': 'OneTimeUpgradeInteraction' - } - } - } - } - }, - 'Mail_Deposit_Box': { - 'hash': 64204, - 'name': 'Mail Deposit Box', - 'embedded': { - 'Cost_Dock_9564': { - 'hash': 9564, - 'name': 'Cost Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Handle_23190': { - 'hash': 23190, - 'name': 'Handle', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Mail_Deposit_Box_64110': { - 'hash': 64110, - 'name': 'Mail Deposit Box', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - }, - 'Scroller_64946': { - 'hash': 64946, - 'name': 'Scroller', - 'savables': {} - }, - 'Send_Dock_Area_33168': { - 'hash': 33168, - 'name': 'Send Dock Area', - 'savables': {} - }, - 'Sending_Dock_1_9562': { - 'hash': 9562, - 'name': 'Sending Dock 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Sending_Dock_2_54962': { - 'hash': 54962, - 'name': 'Sending Dock 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Sending_Dock_3_9442': { - 'hash': 9442, - 'name': 'Sending Dock 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'mail_depositBox_swivel_51358': { - 'hash': 51358, - 'name': 'mail_depositBox_swivel', - 'savables': {} - }, - 'scroller_throttle_handMetal_LOD0_31026': { - 'hash': 31026, - 'name': 'scroller_throttle_handMetal_LOD0', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Main_Menu_Controller': { - 'hash': 58810, - 'name': 'Main_Menu_Controller', - 'embedded': {} - }, - 'Map_Board': { - 'hash': 60974, - 'name': 'Map Board', - 'embedded': { - 'Hand_Touch_46540': { - 'hash': 46540, - 'name': 'Hand Touch', - 'savables': {} - }, - 'Map_Board_63822': { - 'hash': 63822, - 'name': 'Map Board', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - }, - 'Landmark': { - 'hash': 2590537994, - 'name': 'Landmark' - }, - 'LandmarkDiscoverZone': { - 'hash': 4095875831, - 'name': 'LandmarkDiscoverZone' - }, - 'MapBoard': { - 'hash': 2443660852, - 'name': 'MapBoard' - } - } - } - } - }, - 'Material_Box': { - 'hash': 46376, - 'name': 'Material Box', - 'embedded': { - 'Loot_Spawner_46196': { - 'hash': 46196, - 'name': 'Loot Spawner', - 'savables': {} - }, - 'Material_Box_46360': { - 'hash': 46360, - 'name': 'Material Box', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Pieces_Spawner_23704': { - 'hash': 23704, - 'name': 'Pieces Spawner', - 'savables': {} - } - } - }, - 'Material_Box_Pieces': { - 'hash': 42982, - 'name': 'Material Box Pieces', - 'embedded': { - 'Material_Box_Pieces_43372': { - 'hash': 43372, - 'name': 'Material Box Pieces', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Metal_Bow': { - 'hash': 25100, - 'name': 'Metal Bow', - 'embedded': { - 'Arrow_Dock_25108': { - 'hash': 25108, - 'name': 'Arrow Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Metal_Bow_25094': { - 'hash': 25094, - 'name': 'Metal Bow', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_Bow_Blade_10188': { - 'hash': 10188, - 'name': 'Slot Bow Blade', - 'savables': {} - }, - 'Slot_Bow_Blade_252': { - 'hash': 252, - 'name': 'Slot Bow Blade', - 'savables': {} - }, - 'Slot_Deco_61122': { - 'hash': 61122, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_65334': { - 'hash': 65334, - 'name': 'Slot Deco', - 'savables': {} - }, - 'String_25106': { - 'hash': 25106, - 'name': 'String', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Metal_Hammer_Head': { - 'hash': 22876, - 'name': 'Metal Hammer Head', - 'embedded': { - 'Heat_Point_Collection_1368': { - 'hash': 1368, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_HammerType_End_Cap_52192': { - 'hash': 52192, - 'name': 'Insert HammerType End Cap', - 'savables': {} - }, - 'Metal_Hammer_Head_42978': { - 'hash': 42978, - 'name': 'Metal Hammer Head', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_Deco_37872': { - 'hash': 37872, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_48318': { - 'hash': 48318, - 'name': 'Slot Deco', - 'savables': {} - } - } - }, - 'Metal_Hebios_Katana_Blade': { - 'hash': 17174, - 'name': 'Metal Hebios Katana Blade', - 'embedded': { - 'Insert_Straight_SwordType_7796': { - 'hash': 7796, - 'name': 'Insert Straight SwordType', - 'savables': {} - }, - 'Metal_Hebios_Katana_Blade_57166': { - 'hash': 57166, - 'name': 'Metal Hebios Katana Blade', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'katana_blade_part_full_30124': { - 'hash': 30124, - 'name': 'katana_blade_part_full', - 'savables': {} - } - } - }, - 'Metal_Hebios_Naginata_Blade': { - 'hash': 15124, - 'name': 'Metal Hebios Naginata Blade', - 'embedded': { - 'Insert_Straight_SwordType_7796': { - 'hash': 7796, - 'name': 'Insert Straight SwordType', - 'savables': {} - }, - 'Metal_Hebios_Naginata_Blade_57606': { - 'hash': 57606, - 'name': 'Metal Hebios Naginata Blade', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'naginata_blade_LOD0_56264': { - 'hash': 56264, - 'name': 'naginata_blade_LOD0', - 'savables': {} - } - } - }, - 'Metal_Hebios_Sai_Blade': { - 'hash': 53124, - 'name': 'Metal Hebios Sai Blade', - 'embedded': { - 'Insert_Straight_Short_SwordType_7796': { - 'hash': 7796, - 'name': 'Insert Straight Short SwordType', - 'savables': {} - }, - 'Metal_Hebios_Sai_Blade_57606': { - 'hash': 57606, - 'name': 'Metal Hebios Sai Blade', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'sai_blade_LOD0_11144': { - 'hash': 11144, - 'name': 'sai_blade_LOD0', - 'savables': {} - } - } - }, - 'Metal_Hebios_Wakizashi_Blade': { - 'hash': 48902, - 'name': 'Metal Hebios Wakizashi Blade', - 'embedded': { - 'Insert_Straight_Short_SwordType_7796': { - 'hash': 7796, - 'name': 'Insert Straight Short SwordType', - 'savables': {} - }, - 'Metal_Hebios_Wakizashi_Blade_57606': { - 'hash': 57606, - 'name': 'Metal Hebios Wakizashi Blade', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'wakizashi_blade_26702': { - 'hash': 26702, - 'name': 'wakizashi_blade', - 'savables': {} - } - } - }, - 'Metal_Tap': { - 'hash': 17334, - 'name': 'Metal Tap', - 'embedded': { - 'Metal_Tap_20796': { - 'hash': 20796, - 'name': 'Metal Tap', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Metal_Wall_Hook': { - 'hash': 61180, - 'name': 'Metal_Wall_Hook', - 'embedded': {} - }, - 'Mining_Base_Generator': { - 'hash': 6714, - 'name': 'Mining Base Generator', - 'embedded': { - 'Mining_Base_Generator_6374': { - 'hash': 6374, - 'name': 'Mining Base Generator', - 'savables': {} - } - } - }, - 'Mining_Path': { - 'hash': 30950, - 'name': 'Mining Path', - 'embedded': { - 'Mining_Path_30946': { - 'hash': 30946, - 'name': 'Mining Path', - 'savables': { - 'PopulationPath': { - 'hash': 7704646, - 'name': 'PopulationPath' - } - } - } - } - }, - 'Modular_Backpack': { - 'hash': 12060, - 'name': 'Modular_Backpack', - 'embedded': {} - }, - 'Modular_Hook': { - 'hash': 60188, - 'name': 'Modular_Hook', - 'embedded': {} - }, - 'Modular_Sack': { - 'hash': 8344, - 'name': 'Modular_Sack', - 'embedded': {} - }, - 'Mother_Fern': { - 'hash': 65004, - 'name': 'Mother Fern', - 'embedded': { - 'Death_Fern_AI_29794': { - 'hash': 29794, - 'name': 'Death Fern AI', - 'savables': {} - }, - 'Emit_Gas_Spawner_16984': { - 'hash': 16984, - 'name': 'Emit Gas Spawner', - 'savables': {} - }, - 'Mesh_15308': { - 'hash': 15308, - 'name': 'Mesh', - 'savables': {} - }, - 'Mother_Fern_37626': { - 'hash': 37626, - 'name': 'Mother Fern', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Seed_Spray_1172': { - 'hash': 1172, - 'name': 'Seed Spray', - 'savables': {} - } - } - }, - 'Mother_Fern_Seed_Spray': { - 'hash': 26710, - 'name': 'Mother Fern Seed Spray', - 'embedded': { - 'Mother_Fern_Seed_Spray_44772': { - 'hash': 44772, - 'name': 'Mother Fern Seed Spray', - 'savables': {} - } - } - }, - 'Mould': { - 'hash': 14826, - 'name': 'Mould', - 'embedded': { - 'Mould_14710': { - 'hash': 14710, - 'name': 'Mould', - 'savables': { - 'Mould': { - 'hash': 391977879, - 'name': 'Mould' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Mould_Press_Hebios': { - 'hash': 2594, - 'name': 'Mould Press Hebios', - 'embedded': { - 'Input_36080': { - 'hash': 36080, - 'name': 'Input', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Lever_Physics_45996': { - 'hash': 45996, - 'name': 'Lever Physics', - 'savables': { - 'Lever': { - 'hash': 1594932294, - 'name': 'Lever' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Mould_Press_Hebios_65312': { - 'hash': 65312, - 'name': 'Mould Press Hebios', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - }, - 'Output_52720': { - 'hash': 52720, - 'name': 'Output', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - } - } - }, - 'Mould_Press_Standard': { - 'hash': 13362, - 'name': 'Mould Press Standard', - 'embedded': { - 'Input_36080': { - 'hash': 36080, - 'name': 'Input', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Lever_Physics_45996': { - 'hash': 45996, - 'name': 'Lever Physics', - 'savables': { - 'Lever': { - 'hash': 1594932294, - 'name': 'Lever' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Mould_Press_Standard_65312': { - 'hash': 65312, - 'name': 'Mould Press Standard', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - }, - 'Output_52720': { - 'hash': 52720, - 'name': 'Output', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - } - } - }, - 'Mould_Rack': { - 'hash': 4070, - 'name': 'Mould Rack', - 'embedded': { - 'Dock_57418': { - 'hash': 57418, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_57450': { - 'hash': 57450, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_57456': { - 'hash': 57456, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_57470': { - 'hash': 57470, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_57504': { - 'hash': 57504, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_57528': { - 'hash': 57528, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_57550': { - 'hash': 57550, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_57556': { - 'hash': 57556, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Mould_Rack_498': { - 'hash': 498, - 'name': 'Mould Rack', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - }, - 'Rope_Grab_57800': { - 'hash': 57800, - 'name': 'Rope Grab', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'RopeGrab': { - 'hash': 237360636, - 'name': 'RopeGrab' - } - } - }, - 'Rope_Length_57794': { - 'hash': 57794, - 'name': 'Rope Length', - 'savables': {} - } - } - }, - 'Mould_Restriction_Zone': { - 'hash': 4900, - 'name': 'Mould Restriction Zone', - 'embedded': { - 'Mould_Restriction_Zone_2804': { - 'hash': 2804, - 'name': 'Mould Restriction Zone', - 'savables': { - 'MouldRestrictor': { - 'hash': 1571096900, - 'name': 'MouldRestrictor' - } - } - } - } - }, - 'MushroomBrown_Full_Burnt': { - 'hash': 47126, - 'name': 'MushroomBrown Full Burnt', - 'embedded': { - 'Cooking_35920': { - 'hash': 35920, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomBrown_Full_Burnt_36010': { - 'hash': 36010, - 'name': 'MushroomBrown Full Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomBrown_Full_Cooked': { - 'hash': 46510, - 'name': 'MushroomBrown Full Cooked', - 'embedded': { - 'Cooking_32900': { - 'hash': 32900, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomBrown_Full_Cooked_32990': { - 'hash': 32990, - 'name': 'MushroomBrown Full Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomBrown_Full_Ripe': { - 'hash': 61666, - 'name': 'MushroomBrown Full Ripe', - 'embedded': { - 'Cooking_30802': { - 'hash': 30802, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomBrown_Full_Ripe_30892': { - 'hash': 30892, - 'name': 'MushroomBrown Full Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomBrown_Half_Burnt': { - 'hash': 53372, - 'name': 'MushroomBrown Half Burnt', - 'embedded': { - 'Cooking_28740': { - 'hash': 28740, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomBrown_Half_Burnt_28794': { - 'hash': 28794, - 'name': 'MushroomBrown Half Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomBrown_Half_Cooked': { - 'hash': 50916, - 'name': 'MushroomBrown Half Cooked', - 'embedded': { - 'Cooking_26756': { - 'hash': 26756, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomBrown_Half_Cooked_26810': { - 'hash': 26810, - 'name': 'MushroomBrown Half Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomBrown_Half_Ripe': { - 'hash': 48460, - 'name': 'MushroomBrown Half Ripe', - 'embedded': { - 'Cooking_24846': { - 'hash': 24846, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomBrown_Half_Ripe_24900': { - 'hash': 24900, - 'name': 'MushroomBrown Half Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomCaveLarge_Half_Burnt': { - 'hash': 60330, - 'name': 'MushroomCaveLarge Half Burnt', - 'embedded': { - 'Cooking_60736': { - 'hash': 60736, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomCaveLarge_Half_Burnt_61496': { - 'hash': 61496, - 'name': 'MushroomCaveLarge Half Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomCaveLarge_Half_Cooked': { - 'hash': 9414, - 'name': 'MushroomCaveLarge Half Cooked', - 'embedded': { - 'Cooking_55004': { - 'hash': 55004, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomCaveLarge_Half_Cooked_55764': { - 'hash': 55764, - 'name': 'MushroomCaveLarge Half Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomCaveLarge_Half_Ripe': { - 'hash': 54182, - 'name': 'MushroomCaveLarge Half Ripe', - 'embedded': { - 'Cooking_49572': { - 'hash': 49572, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomCaveLarge_Half_Ripe_50332': { - 'hash': 50332, - 'name': 'MushroomCaveLarge Half Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomCaveSmall_Full_Burnt': { - 'hash': 29148, - 'name': 'MushroomCaveSmall Full Burnt', - 'embedded': { - 'Cooking_27474': { - 'hash': 27474, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomCaveSmall_Full_Burnt_28332': { - 'hash': 28332, - 'name': 'MushroomCaveSmall Full Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomCaveSmall_Full_Cooked': { - 'hash': 40066, - 'name': 'MushroomCaveSmall Full Cooked', - 'embedded': { - 'Cooking_34902': { - 'hash': 34902, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomCaveSmall_Full_Cooked_35760': { - 'hash': 35760, - 'name': 'MushroomCaveSmall Full Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomCaveSmall_Full_Ripe': { - 'hash': 58270, - 'name': 'MushroomCaveSmall Full Ripe', - 'embedded': { - 'Cooking_28844': { - 'hash': 28844, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomCaveSmall_Full_Ripe_29702': { - 'hash': 29702, - 'name': 'MushroomCaveSmall Full Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomCaveSmall_Half_Burnt': { - 'hash': 47142, - 'name': 'MushroomCaveSmall Half Burnt', - 'embedded': { - 'Cooking_23588': { - 'hash': 23588, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomCaveSmall_Half_Burnt_23644': { - 'hash': 23644, - 'name': 'MushroomCaveSmall Half Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomCaveSmall_Half_Cooked': { - 'hash': 44488, - 'name': 'MushroomCaveSmall Half Cooked', - 'embedded': { - 'Cooking_21474': { - 'hash': 21474, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomCaveSmall_Half_Cooked_21530': { - 'hash': 21530, - 'name': 'MushroomCaveSmall Half Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomCaveSmall_Half_Ripe': { - 'hash': 41834, - 'name': 'MushroomCaveSmall Half Ripe', - 'embedded': { - 'Cooking_19434': { - 'hash': 19434, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomCaveSmall_Half_Ripe_19490': { - 'hash': 19490, - 'name': 'MushroomCaveSmall Half Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomGlowing_Full_Burnt': { - 'hash': 43856, - 'name': 'MushroomGlowing Full Burnt', - 'embedded': { - 'Cooking_13584': { - 'hash': 13584, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomGlowing_Full_Burnt_41450': { - 'hash': 41450, - 'name': 'MushroomGlowing Full Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomGlowing_Full_Cooked': { - 'hash': 41428, - 'name': 'MushroomGlowing Full Cooked', - 'embedded': { - 'Cooking_6452': { - 'hash': 6452, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomGlowing_Full_Cooked_14334': { - 'hash': 14334, - 'name': 'MushroomGlowing Full Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomGlowing_Full_Ripe': { - 'hash': 38966, - 'name': 'MushroomGlowing Full Ripe', - 'embedded': { - 'Cooking_1062': { - 'hash': 1062, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomGlowing_Full_Ripe_33808': { - 'hash': 33808, - 'name': 'MushroomGlowing Full Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomGlowing_Half_Burnt': { - 'hash': 36504, - 'name': 'MushroomGlowing Half Burnt', - 'embedded': { - 'Cooking_61912': { - 'hash': 61912, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomGlowing_Half_Burnt_37030': { - 'hash': 37030, - 'name': 'MushroomGlowing Half Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomGlowing_Half_Cooked': { - 'hash': 34042, - 'name': 'MushroomGlowing Half Cooked', - 'embedded': { - 'Cooking_60048': { - 'hash': 60048, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomGlowing_Half_Cooked_14126': { - 'hash': 14126, - 'name': 'MushroomGlowing Half Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomGlowing_Half_Ripe': { - 'hash': 31580, - 'name': 'MushroomGlowing Half Ripe', - 'embedded': { - 'Cooking_58186': { - 'hash': 58186, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomGlowing_Half_Ripe_59620': { - 'hash': 59620, - 'name': 'MushroomGlowing Half Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomRed_Full_Burnt': { - 'hash': 46660, - 'name': 'MushroomRed Full Burnt', - 'embedded': { - 'Cooking_15932': { - 'hash': 15932, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomRed_Full_Burnt_16724': { - 'hash': 16724, - 'name': 'MushroomRed Full Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomRed_Full_Cooked': { - 'hash': 46888, - 'name': 'MushroomRed Full Cooked', - 'embedded': { - 'Cooking_29424': { - 'hash': 29424, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomRed_Full_Cooked_30216': { - 'hash': 30216, - 'name': 'MushroomRed Full Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomRed_Full_Ripe': { - 'hash': 61658, - 'name': 'MushroomRed Full Ripe', - 'embedded': { - 'Cooking_23868': { - 'hash': 23868, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomRed_Full_Ripe_24660': { - 'hash': 24660, - 'name': 'MushroomRed Full Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomRed_Half_Burnt': { - 'hash': 43272, - 'name': 'MushroomRed Half Burnt', - 'embedded': { - 'Cooking_19050': { - 'hash': 19050, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomRed_Half_Burnt_19104': { - 'hash': 19104, - 'name': 'MushroomRed Half Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomRed_Half_Cooked': { - 'hash': 40816, - 'name': 'MushroomRed Half Cooked', - 'embedded': { - 'Cooking_17118': { - 'hash': 17118, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomRed_Half_Cooked_17172': { - 'hash': 17172, - 'name': 'MushroomRed Half Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'MushroomRed_Half_Ripe': { - 'hash': 38360, - 'name': 'MushroomRed Half Ripe', - 'embedded': { - 'Cooking_15260': { - 'hash': 15260, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'MushroomRed_Half_Ripe_15314': { - 'hash': 15314, - 'name': 'MushroomRed Half Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Mushroom_Fairy_Circle_Puzzle': { - 'hash': 46706, - 'name': 'Mushroom Fairy Circle Puzzle', - 'embedded': { - 'Mushroom_Fairy_Circle_Puzzle_28402': { - 'hash': 28402, - 'name': 'Mushroom Fairy Circle Puzzle', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'SpawnInCircle': { - 'hash': 1714180166, - 'name': 'SpawnInCircle' - } - } - } - } - }, - 'Mushroom_Fairy_Circle_Puzzle_OLD': { - 'hash': 44688, - 'name': 'Mushroom_Fairy_Circle_Puzzle_OLD', - 'embedded': {} - }, - 'Mushroom_Fairy_Circle_Puzzle_Teleport': { - 'hash': 28040, - 'name': 'Mushroom Fairy Circle Puzzle Teleport', - 'embedded': { - 'Mushroom_Fairy_Circle_Puzzle_Teleport_8726': { - 'hash': 8726, - 'name': 'Mushroom Fairy Circle Puzzle Teleport', - 'savables': { - 'LogicVector3Receiver': { - 'hash': 1228539097, - 'name': 'LogicVector3Receiver' - }, - 'LogicVector3Sender': { - 'hash': 2026743731, - 'name': 'LogicVector3Sender' - }, - 'PositionProvider': { - 'hash': 3538443740, - 'name': 'PositionProvider' - }, - 'SpawnInCircle': { - 'hash': 1714180166, - 'name': 'SpawnInCircle' - }, - 'TeleportationPoint': { - 'hash': 3146178080, - 'name': 'TeleportationPoint' - } - } - } - } - }, - 'Mushroom_Mix_Recipe_Burnt_Stew': { - 'hash': 27398, - 'name': 'Mushroom_Mix_Recipe_Burnt_Stew', - 'embedded': {} - }, - 'Mushroom_Mix_Recipe_Cooked_Stew': { - 'hash': 27376, - 'name': 'Mushroom_Mix_Recipe_Cooked_Stew', - 'embedded': {} - }, - 'Mushroom_Mix_Recipe_Raw_Stew': { - 'hash': 14914, - 'name': 'Mushroom_Mix_Recipe_Raw_Stew', - 'embedded': {} - }, - 'Mushroom_Poultry_Recipe_Burnt_Stew': { - 'hash': 54614, - 'name': 'Mushroom_Poultry_Recipe_Burnt_Stew', - 'embedded': {} - }, - 'Mushroom_Poultry_Recipe_Cooked_Stew': { - 'hash': 55358, - 'name': 'Mushroom_Poultry_Recipe_Cooked_Stew', - 'embedded': {} - }, - 'Mushroom_Poultry_Recipe_Raw_Stew': { - 'hash': 55978, - 'name': 'Mushroom_Poultry_Recipe_Raw_Stew', - 'embedded': {} - }, - 'Mushroom_Recipe_Burnt_Stew': { - 'hash': 30560, - 'name': 'Mushroom_Recipe_Burnt_Stew', - 'embedded': {} - }, - 'Mushroom_Recipe_Cooked_Stew': { - 'hash': 31606, - 'name': 'Mushroom_Recipe_Cooked_Stew', - 'embedded': {} - }, - 'Mushroom_Recipe_Raw_Stew': { - 'hash': 32650, - 'name': 'Mushroom_Recipe_Raw_Stew', - 'embedded': {} - }, - 'Mythril_Boulder': { - 'hash': 27368, - 'name': 'Mythril Boulder', - 'embedded': { - 'Mythril_Boulder_29328': { - 'hash': 29328, - 'name': 'Mythril Boulder', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Spawn_Origin_18860': { - 'hash': 18860, - 'name': 'Spawn Origin', - 'savables': {} - } - } - }, - 'Mythril_Boulder_Parts': { - 'hash': 43522, - 'name': 'Mythril_Boulder_Parts', - 'embedded': { - 'Mythril_Boulder_Parts_59770': { - 'hash': 59770, - 'name': 'Mythril_Boulder_Parts', - 'savables': {} - }, - 'Mythril_Boulder_part_01_59808': { - 'hash': 59808, - 'name': 'Mythril_Boulder_part_01', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Mythril_Boulder_part_02_59820': { - 'hash': 59820, - 'name': 'Mythril_Boulder_part_02', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Mythril_Boulder_part_03_59816': { - 'hash': 59816, - 'name': 'Mythril_Boulder_part_03', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Mythril_Boulder_part_04_59804': { - 'hash': 59804, - 'name': 'Mythril_Boulder_part_04', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Mythril_Boulder_part_05_59812': { - 'hash': 59812, - 'name': 'Mythril_Boulder_part_05', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Mythril_Ingot': { - 'hash': 24774, - 'name': 'Mythril Ingot', - 'embedded': { - 'Heat_Point_Collection_13294': { - 'hash': 13294, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Mythril_Ingot_24662': { - 'hash': 24662, - 'name': 'Mythril Ingot', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Mythril_Ore': { - 'hash': 11702, - 'name': 'Mythril Ore', - 'embedded': { - 'Mythril_Ore_15610': { - 'hash': 15610, - 'name': 'Mythril Ore', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Naginata': { - 'hash': 41052, - 'name': 'Naginata', - 'embedded': { - 'Naginata_36330': { - 'hash': 36330, - 'name': 'Naginata', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'Enchantable': { - 'hash': 4134534481, - 'name': 'Enchantable' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Name_Proxy': { - 'hash': 15340, - 'name': 'Name_Proxy', - 'embedded': {} - }, - 'Nand': { - 'hash': 42426, - 'name': 'Nand', - 'embedded': {} - }, - 'Navigation_wheel': { - 'hash': 20416, - 'name': 'Navigation_wheel', - 'embedded': { - 'Grip_(1)_54050': { - 'hash': 54050, - 'name': 'Grip (1)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(2)_54614': { - 'hash': 54614, - 'name': 'Grip (2)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(3)_56370': { - 'hash': 56370, - 'name': 'Grip (3)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(4)_53470': { - 'hash': 53470, - 'name': 'Grip (4)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_56728': { - 'hash': 56728, - 'name': 'Grip', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Navigation_wheel_16790': { - 'hash': 16790, - 'name': 'Navigation_wheel', - 'savables': {} - } - } - }, - 'New_Tree_Grower': { - 'hash': 62444, - 'name': 'New Tree Grower', - 'embedded': { - 'New_Tree_Grower_52858': { - 'hash': 52858, - 'name': 'New Tree Grower', - 'savables': { - 'GrowerComponent': { - 'hash': 3402094521, - 'name': 'GrowerComponent' - } - } - } - } - }, - 'Non_Recipe_Burnt_Stew': { - 'hash': 48634, - 'name': 'Non_Recipe_Burnt_Stew', - 'embedded': {} - }, - 'Non_Recipe_Cooked_Stew': { - 'hash': 49314, - 'name': 'Non_Recipe_Cooked_Stew', - 'embedded': {} - }, - 'Non_Recipe_Raw_Stew': { - 'hash': 49962, - 'name': 'Non_Recipe_Raw_Stew', - 'embedded': {} - }, - 'Nor': { - 'hash': 42420, - 'name': 'Nor', - 'embedded': {} - }, - 'Not': { - 'hash': 42414, - 'name': 'Not', - 'embedded': {} - }, - 'Oak_Tree_Growth': { - 'hash': 48238, - 'name': 'Oak Tree Growth', - 'embedded': { - 'Oak_Tree_Growth_33458': { - 'hash': 33458, - 'name': 'Oak Tree Growth', - 'savables': { - 'GrowerComponent': { - 'hash': 3402094521, - 'name': 'GrowerComponent' - } - } - } - } - }, - 'Oak_Tree_Seed': { - 'hash': 17302, - 'name': 'Oak Tree Seed', - 'embedded': { - 'Oak_Tree_Seed_35258': { - 'hash': 35258, - 'name': 'Oak Tree Seed', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'RaycastCrafter': { - 'hash': 2815374842, - 'name': 'RaycastCrafter' - } - } - } - } - }, - 'Oak_Tree_Stage_1': { - 'hash': 17412, - 'name': 'Oak Tree Stage 1', - 'embedded': { - 'Oak_Tree_Stage_1_63514': { - 'hash': 63514, - 'name': 'Oak Tree Stage 1', - 'savables': {} - } - } - }, - 'Obstacle_Path': { - 'hash': 62838, - 'name': 'Obstacle Path', - 'embedded': { - 'Obstacle_Path_30946': { - 'hash': 30946, - 'name': 'Obstacle Path', - 'savables': { - 'PopulationPath': { - 'hash': 7704646, - 'name': 'PopulationPath' - } - } - } - } - }, - 'One_Time_Upgrade_Station_Health': { - 'hash': 46992, - 'name': 'One Time Upgrade Station Health', - 'embedded': { - 'One_Time_Upgrade_Station_Health_46540': { - 'hash': 46540, - 'name': 'One Time Upgrade Station Health', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'OneTimeUpgradeInteraction': { - 'hash': 3230087383, - 'name': 'OneTimeUpgradeInteraction' - } - } - } - } - }, - 'Onion_Full_Burnt': { - 'hash': 48718, - 'name': 'Onion Full Burnt', - 'embedded': { - 'Cooking_61106': { - 'hash': 61106, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Onion_Full_Burnt_48300': { - 'hash': 48300, - 'name': 'Onion Full Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Onion_Full_Cooked': { - 'hash': 48214, - 'name': 'Onion Full Cooked', - 'embedded': { - 'Cooking_60678': { - 'hash': 60678, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Onion_Full_Cooked_47812': { - 'hash': 47812, - 'name': 'Onion Full Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Onion_Full_Ripe': { - 'hash': 47730, - 'name': 'Onion Full Ripe', - 'embedded': { - 'Cooking_58282': { - 'hash': 58282, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Leaves_Parent_20548': { - 'hash': 20548, - 'name': 'Leaves Parent', - 'savables': {} - }, - 'Onion_Full_Ripe_44704': { - 'hash': 44704, - 'name': 'Onion Full Ripe', - 'savables': { - 'BuildupPickup': { - 'hash': 3373651539, - 'name': 'BuildupPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Roots_Parent_17652': { - 'hash': 17652, - 'name': 'Roots Parent', - 'savables': {} - } - } - }, - 'Onion_Full_Unripe': { - 'hash': 43966, - 'name': 'Onion Full Unripe', - 'embedded': { - 'Cooking_57758': { - 'hash': 57758, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Onion_Full_Unripe_43436': { - 'hash': 43436, - 'name': 'Onion Full Unripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Onion_Half_Burnt': { - 'hash': 59314, - 'name': 'Onion Half Burnt', - 'embedded': { - 'Cooking_33410': { - 'hash': 33410, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Onion_Half_Burnt_58976': { - 'hash': 58976, - 'name': 'Onion Half Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Onion_Half_Cooked': { - 'hash': 58910, - 'name': 'Onion Half Cooked', - 'embedded': { - 'Cooking_33064': { - 'hash': 33064, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Onion_Half_Cooked_58572': { - 'hash': 58572, - 'name': 'Onion Half Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Onion_Half_Ripe': { - 'hash': 58506, - 'name': 'Onion Half Ripe', - 'embedded': { - 'Cooking_32718': { - 'hash': 32718, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Onion_Half_Ripe_58168': { - 'hash': 58168, - 'name': 'Onion Half Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Onion_Half_Unripe': { - 'hash': 58102, - 'name': 'Onion Half Unripe', - 'embedded': { - 'Cooking_32372': { - 'hash': 32372, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Onion_Half_Unripe_57764': { - 'hash': 57764, - 'name': 'Onion Half Unripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Onion_Leaves': { - 'hash': 29078, - 'name': 'Onion Leaves', - 'embedded': { - 'Onion_Leaves_31538': { - 'hash': 31538, - 'name': 'Onion Leaves', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'PullPickup_51602': { - 'hash': 51602, - 'name': 'PullPickup', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Onion_Roots': { - 'hash': 32068, - 'name': 'Onion Roots', - 'embedded': { - 'Onion_Roots_47660': { - 'hash': 47660, - 'name': 'Onion Roots', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'PullPickup_32872': { - 'hash': 32872, - 'name': 'PullPickup', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Or': { - 'hash': 42416, - 'name': 'Or', - 'embedded': {} - }, - 'Orchi_Ingot': { - 'hash': 16464, - 'name': 'Orchi Ingot', - 'embedded': { - 'Heat_Point_Collection_13422': { - 'hash': 13422, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Orchi_Ingot_32738': { - 'hash': 32738, - 'name': 'Orchi Ingot', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Ore_Bag': { - 'hash': 64560, - 'name': 'Ore Bag', - 'embedded': { - 'Bag_Body_42972': { - 'hash': 42972, - 'name': 'Bag Body', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Dock_BM_63062': { - 'hash': 63062, - 'name': 'Dock BM', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_L_63242': { - 'hash': 63242, - 'name': 'Dock L', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_R_63236': { - 'hash': 63236, - 'name': 'Dock R', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_TM_63222': { - 'hash': 63222, - 'name': 'Dock TM', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Ore_Bag_43012': { - 'hash': 43012, - 'name': 'Ore Bag', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_Bag_Attach_30776': { - 'hash': 30776, - 'name': 'Slot Bag Attach', - 'savables': {} - }, - 'Slot_Bag_Attach_55164': { - 'hash': 55164, - 'name': 'Slot Bag Attach', - 'savables': {} - }, - 'Slot_Bag_Attach_62396': { - 'hash': 62396, - 'name': 'Slot Bag Attach', - 'savables': {} - }, - 'Slot_Bag_Tool_Attachment_36292': { - 'hash': 36292, - 'name': 'Slot Bag Tool Attachment', - 'savables': {} - }, - 'Slot_Bag_Tool_Attachment_36386': { - 'hash': 36386, - 'name': 'Slot Bag Tool Attachment', - 'savables': {} - }, - 'ore_bag_frame_01_44248': { - 'hash': 44248, - 'name': 'ore_bag_frame_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_frame_02_44244': { - 'hash': 44244, - 'name': 'ore_bag_frame_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_frame_03_44312': { - 'hash': 44312, - 'name': 'ore_bag_frame_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_frame_04_44308': { - 'hash': 44308, - 'name': 'ore_bag_frame_04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_rim_bottom_44264': { - 'hash': 44264, - 'name': 'ore_bag_rim_bottom', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_rim_top_44288': { - 'hash': 44288, - 'name': 'ore_bag_rim_top', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_sack_44268': { - 'hash': 44268, - 'name': 'ore_bag_sack', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_stick_01_44328': { - 'hash': 44328, - 'name': 'ore_bag_stick_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_stick_02_44296': { - 'hash': 44296, - 'name': 'ore_bag_stick_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_stick_03_44284': { - 'hash': 44284, - 'name': 'ore_bag_stick_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_stick_04_44228': { - 'hash': 44228, - 'name': 'ore_bag_stick_04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_stick_05_44224': { - 'hash': 44224, - 'name': 'ore_bag_stick_05', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_stick_06_44304': { - 'hash': 44304, - 'name': 'ore_bag_stick_06', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_stick_07_44300': { - 'hash': 44300, - 'name': 'ore_bag_stick_07', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_stick_08_44240': { - 'hash': 44240, - 'name': 'ore_bag_stick_08', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_stick_09_44236': { - 'hash': 44236, - 'name': 'ore_bag_stick_09', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_stick_10_44324': { - 'hash': 44324, - 'name': 'ore_bag_stick_10', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_stick_11_44320': { - 'hash': 44320, - 'name': 'ore_bag_stick_11', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_stick_12_44280': { - 'hash': 44280, - 'name': 'ore_bag_stick_12', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_stick_13_44232': { - 'hash': 44232, - 'name': 'ore_bag_stick_13', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_strawBind_01_44316': { - 'hash': 44316, - 'name': 'ore_bag_strawBind_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_strawBind_02_44260': { - 'hash': 44260, - 'name': 'ore_bag_strawBind_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_strawBind_03_44276': { - 'hash': 44276, - 'name': 'ore_bag_strawBind_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_strawBind_04_44272': { - 'hash': 44272, - 'name': 'ore_bag_strawBind_04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_strawBind_05_44256': { - 'hash': 44256, - 'name': 'ore_bag_strawBind_05', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_strawBind_06_44252': { - 'hash': 44252, - 'name': 'ore_bag_strawBind_06', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_strawBind_07_44292': { - 'hash': 44292, - 'name': 'ore_bag_strawBind_07', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_handle_body_14308': { - 'hash': 14308, - 'name': 'standard_bag_handle_body', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_bag_handle_wraps_14304': { - 'hash': 14304, - 'name': 'standard_bag_handle_wraps', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Ore_Side_Pouch_Attachment': { - 'hash': 61020, - 'name': 'Ore Side Pouch Attachment', - 'embedded': { - 'Dock_45700': { - 'hash': 45700, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62078': { - 'hash': 62078, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Insert_Bag_Attach_7796': { - 'hash': 7796, - 'name': 'Insert Bag Attach', - 'savables': {} - }, - 'Ore_Side_Pouch_Attachment_7868': { - 'hash': 7868, - 'name': 'Ore Side Pouch Attachment', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Storage_53834': { - 'hash': 53834, - 'name': 'Storage', - 'savables': {} - }, - 'ore_bag_attachment_cloth_01_30702': { - 'hash': 30702, - 'name': 'ore_bag_attachment_cloth_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_attachment_cloth_cover_43718': { - 'hash': 43718, - 'name': 'ore_bag_attachment_cloth_cover', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_attachment_knot_01_30682': { - 'hash': 30682, - 'name': 'ore_bag_attachment_knot_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_attachment_knot_02_30678': { - 'hash': 30678, - 'name': 'ore_bag_attachment_knot_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_attachment_knot_03_30674': { - 'hash': 30674, - 'name': 'ore_bag_attachment_knot_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_attachment_knot_04_30670': { - 'hash': 30670, - 'name': 'ore_bag_attachment_knot_04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_attachment_stick_01_30698': { - 'hash': 30698, - 'name': 'ore_bag_attachment_stick_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_attachment_stick_02_30694': { - 'hash': 30694, - 'name': 'ore_bag_attachment_stick_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_attachment_stick_03_30690': { - 'hash': 30690, - 'name': 'ore_bag_attachment_stick_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_attachment_stick_04_30686': { - 'hash': 30686, - 'name': 'ore_bag_attachment_stick_04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_attachment_stick_05_30658': { - 'hash': 30658, - 'name': 'ore_bag_attachment_stick_05', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'ore_bag_attachment_stick_06_30654': { - 'hash': 30654, - 'name': 'ore_bag_attachment_stick_06', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Ore_Storage': { - 'hash': 65420, - 'name': 'Ore Storage', - 'embedded': { - 'Filter_Dock_57214': { - 'hash': 57214, - 'name': 'Filter Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Interaction_Point_59032': { - 'hash': 59032, - 'name': 'Interaction Point', - 'savables': {} - }, - 'Internal_Dock_59328': { - 'hash': 59328, - 'name': 'Internal Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Ore_Storage_65062': { - 'hash': 65062, - 'name': 'Ore Storage', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - }, - 'CommunalStorage': { - 'hash': 3084373371, - 'name': 'CommunalStorage' - }, - 'PlayerInteractionRestrictor': { - 'hash': 2951515968, - 'name': 'PlayerInteractionRestrictor' - } - } - }, - 'Withdraw_Dock_34750': { - 'hash': 34750, - 'name': 'Withdraw Dock', - 'savables': {} - } - } - }, - 'Ore_Training': { - 'hash': 56300, - 'name': 'Ore Training', - 'embedded': { - 'Ore_Training_56294': { - 'hash': 56294, - 'name': 'Ore Training', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Outdoor_Light_Fixture': { - 'hash': 4686, - 'name': 'Outdoor Light Fixture', - 'embedded': { - 'Fire_53718': { - 'hash': 53718, - 'name': 'Fire', - 'savables': { - 'Fire': { - 'hash': 3457519710, - 'name': 'Fire' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Outdoor_Light_Fixture_2808': { - 'hash': 2808, - 'name': 'Outdoor Light Fixture', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - } - } - }, - 'Outdoor_Light_Fixture_Dim': { - 'hash': 2758, - 'name': 'Outdoor Light Fixture Dim', - 'embedded': { - 'Fire_34930': { - 'hash': 34930, - 'name': 'Fire', - 'savables': {} - }, - 'Outdoor_Light_Fixture_Dim_2756': { - 'hash': 2756, - 'name': 'Outdoor Light Fixture Dim', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - } - } - }, - 'Padlock_Standard': { - 'hash': 3830, - 'name': 'Padlock Standard', - 'embedded': { - 'Padlock_Standard_8924': { - 'hash': 8924, - 'name': 'Padlock Standard', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Page': { - 'hash': 40320, - 'name': 'Page', - 'embedded': {} - }, - 'Paper': { - 'hash': 37066, - 'name': 'Paper', - 'embedded': { - 'Paper_60604': { - 'hash': 60604, - 'name': 'Paper', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PaperPageInstance': { - 'hash': 2241532968, - 'name': 'PaperPageInstance' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Phantom': { - 'hash': 17772, - 'name': 'Phantom', - 'embedded': { - 'AI_25864': { - 'hash': 25864, - 'name': 'AI', - 'savables': {} - }, - 'Phantom_01_16416': { - 'hash': 16416, - 'name': 'Phantom_01', - 'savables': {} - }, - 'Phantom_25882': { - 'hash': 25882, - 'name': 'Phantom', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Phantom_Guard': { - 'hash': 6940, - 'name': 'Phantom Guard', - 'embedded': { - 'Heat_Point_Collection_56294': { - 'hash': 56294, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_SwordType_Craft_39368': { - 'hash': 39368, - 'name': 'Insert SwordType Craft', - 'savables': {} - }, - 'Phantom_Guard_51546': { - 'hash': 51546, - 'name': 'Phantom Guard', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_Multi_39370': { - 'hash': 39370, - 'name': 'Slot Multi', - 'savables': {} - } - } - }, - 'Phantom_Head': { - 'hash': 43960, - 'name': 'Phantom Head', - 'embedded': { - 'AI_25864': { - 'hash': 25864, - 'name': 'AI', - 'savables': {} - }, - 'Phantom_01_16416': { - 'hash': 16416, - 'name': 'Phantom_01', - 'savables': {} - }, - 'Phantom_Head_25882': { - 'hash': 25882, - 'name': 'Phantom Head', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Pick_Axe': { - 'hash': 61654, - 'name': 'Pick Axe', - 'embedded': { - 'Pick_Axe_35090': { - 'hash': 35090, - 'name': 'Pick Axe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Pickaxe_Head': { - 'hash': 35878, - 'name': 'Pickaxe Head', - 'embedded': { - 'Heat_Point_Collection_14016': { - 'hash': 14016, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_HammerType_End_Cap_27166': { - 'hash': 27166, - 'name': 'Insert HammerType End Cap', - 'savables': {} - }, - 'Pickaxe_Head_35758': { - 'hash': 35758, - 'name': 'Pickaxe Head', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Pickaxe_Training': { - 'hash': 29706, - 'name': 'Pickaxe_Training', - 'embedded': {} - }, - 'PickupSlidingDoor': { - 'hash': 13452, - 'name': 'PickupSlidingDoor', - 'embedded': { - 'Grip_(1)_8328': { - 'hash': 8328, - 'name': 'Grip (1)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(2)_8460': { - 'hash': 8460, - 'name': 'Grip (2)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(3)_8292': { - 'hash': 8292, - 'name': 'Grip (3)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(4)_8306': { - 'hash': 8306, - 'name': 'Grip (4)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(5)_27902': { - 'hash': 27902, - 'name': 'Grip (5)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(6)_27924': { - 'hash': 27924, - 'name': 'Grip (6)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(7)_27886': { - 'hash': 27886, - 'name': 'Grip (7)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(8)_27948': { - 'hash': 27948, - 'name': 'Grip (8)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(9)_27940': { - 'hash': 27940, - 'name': 'Grip (9)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_8438': { - 'hash': 8438, - 'name': 'Grip', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'PickupSlidingDoor_13450': { - 'hash': 13450, - 'name': 'PickupSlidingDoor', - 'savables': { - 'MovePickup': { - 'hash': 1874870249, - 'name': 'MovePickup' - } - } - } - } - }, - 'PillarBridgeRotate': { - 'hash': 47436, - 'name': 'PillarBridgeRotate', - 'embedded': { - 'PillarBridgeRotate_10812': { - 'hash': 10812, - 'name': 'PillarBridgeRotate', - 'savables': {} - }, - 'handle_01_30518': { - 'hash': 30518, - 'name': 'handle_01', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'handle_02_30398': { - 'hash': 30398, - 'name': 'handle_02', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'handle_03_30390': { - 'hash': 30390, - 'name': 'handle_03', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'handle_04_30524': { - 'hash': 30524, - 'name': 'handle_04', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'PillarRotate': { - 'hash': 25648, - 'name': 'PillarRotate', - 'embedded': { - 'PillarRotate_10812': { - 'hash': 10812, - 'name': 'PillarRotate', - 'savables': {} - }, - 'handle_01_30158': { - 'hash': 30158, - 'name': 'handle_01', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'handle_02_30102': { - 'hash': 30102, - 'name': 'handle_02', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'handle_03_30096': { - 'hash': 30096, - 'name': 'handle_03', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Pink_Crystal_cluster_02': { - 'hash': 15424, - 'name': 'Pink_Crystal_cluster_02', - 'embedded': { - 'Pink_Crystal_cluster_02_54416': { - 'hash': 54416, - 'name': 'Pink_Crystal_cluster_02', - 'savables': {} - } - } - }, - 'PlaceItemPuzzleNoDock': { - 'hash': 12962, - 'name': 'PlaceItemPuzzleNoDock', - 'embedded': { - 'PlaceItemPuzzleNoDock_26668': { - 'hash': 26668, - 'name': 'PlaceItemPuzzleNoDock', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'PlaceItemNoDockPuzzleLogic': { - 'hash': 1176706580, - 'name': 'PlaceItemNoDockPuzzleLogic' - } - } - } - } - }, - 'PlaceItemPuzzleNoDockFire': { - 'hash': 64858, - 'name': 'PlaceItemPuzzleNoDockFire', - 'embedded': { - 'PlaceItemPuzzleNoDockFire_54686': { - 'hash': 54686, - 'name': 'PlaceItemPuzzleNoDockFire', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'PlaceItemNoDockFirePuzzleLogic': { - 'hash': 2495475500, - 'name': 'PlaceItemNoDockFirePuzzleLogic' - } - } - } - } - }, - 'Placed_Table': { - 'hash': 8520, - 'name': 'Placed Table', - 'embedded': { - 'Placed_Table_55788': { - 'hash': 55788, - 'name': 'Placed Table', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Spawn_Object_(1)_45908': { - 'hash': 45908, - 'name': 'Spawn Object (1)', - 'savables': {} - }, - 'Spawn_Object_(2)_45906': { - 'hash': 45906, - 'name': 'Spawn Object (2)', - 'savables': {} - }, - 'Spawn_Object_(3)_45904': { - 'hash': 45904, - 'name': 'Spawn Object (3)', - 'savables': {} - }, - 'Spawn_Object_(4)_45902': { - 'hash': 45902, - 'name': 'Spawn Object (4)', - 'savables': {} - }, - 'Spawn_Object_45900': { - 'hash': 45900, - 'name': 'Spawn Object', - 'savables': {} - }, - 'table_leg_01_48772': { - 'hash': 48772, - 'name': 'table_leg_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'table_leg_02_48776': { - 'hash': 48776, - 'name': 'table_leg_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'table_leg_03_48784': { - 'hash': 48784, - 'name': 'table_leg_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'table_leg_04_48760': { - 'hash': 48760, - 'name': 'table_leg_04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'table_main_48764': { - 'hash': 48764, - 'name': 'table_main', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'table_support_long_01_48780': { - 'hash': 48780, - 'name': 'table_support_long_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'table_support_long_02_48792': { - 'hash': 48792, - 'name': 'table_support_long_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'table_support_short_01_48788': { - 'hash': 48788, - 'name': 'table_support_short_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'table_support_short_02_48768': { - 'hash': 48768, - 'name': 'table_support_short_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Placement_Crate': { - 'hash': 36614, - 'name': 'Placement Crate', - 'embedded': { - 'Dock_1_2780': { - 'hash': 2780, - 'name': 'Dock 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_2_31842': { - 'hash': 31842, - 'name': 'Dock 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_3_31266': { - 'hash': 31266, - 'name': 'Dock 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_4_30878': { - 'hash': 30878, - 'name': 'Dock 4', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Placement_Crate_14764': { - 'hash': 14764, - 'name': 'Placement Crate', - 'savables': { - 'GeneratedLoot': { - 'hash': 3642863935, - 'name': 'GeneratedLoot' - } - } - } - } - }, - 'PlayerInAreaLogic': { - 'hash': 11982, - 'name': 'PlayerInAreaLogic', - 'embedded': { - 'PlayerInAreaLogic_9782': { - 'hash': 9782, - 'name': 'PlayerInAreaLogic', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'PlayerDetect': { - 'hash': 403040752, - 'name': 'PlayerDetect' - } - } - } - } - }, - 'Player_Template': { - 'hash': 61646, - 'name': 'Player_Template', - 'embedded': {} - }, - 'Poison_Cloud': { - 'hash': 52444, - 'name': 'Poison Cloud', - 'embedded': { - 'Poison_Cloud_50236': { - 'hash': 50236, - 'name': 'Poison Cloud', - 'savables': {} - } - } - }, - 'Poison_Vent': { - 'hash': 37252, - 'name': 'Poison Vent', - 'embedded': { - 'PoisonSpawn_15766': { - 'hash': 15766, - 'name': 'PoisonSpawn', - 'savables': { - 'PlayerDetect': { - 'hash': 403040752, - 'name': 'PlayerDetect' - } - } - }, - 'Poison_Vent_46584': { - 'hash': 46584, - 'name': 'Poison Vent', - 'savables': {} - } - } - }, - 'Pole_Hugger_Edgy': { - 'hash': 17828, - 'name': 'Pole Hugger Edgy', - 'embedded': { - 'Insert_Deco_112': { - 'hash': 112, - 'name': 'Insert Deco', - 'savables': {} - }, - 'Pole_Hugger_Edgy_15532': { - 'hash': 15532, - 'name': 'Pole Hugger Edgy', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Pole_Hugger_Pointy_Ends': { - 'hash': 10962, - 'name': 'Pole Hugger Pointy Ends', - 'embedded': { - 'Insert_Deco_112': { - 'hash': 112, - 'name': 'Insert Deco', - 'savables': {} - }, - 'Pole_Hugger_Pointy_Ends_15532': { - 'hash': 15532, - 'name': 'Pole Hugger Pointy Ends', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Pole_Hugger_Short': { - 'hash': 4920, - 'name': 'Pole Hugger Short', - 'embedded': { - 'Insert_Deco_112': { - 'hash': 112, - 'name': 'Insert Deco', - 'savables': {} - }, - 'Pole_Hugger_Short_15532': { - 'hash': 15532, - 'name': 'Pole Hugger Short', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Pole_Hugger_Tall': { - 'hash': 62282, - 'name': 'Pole Hugger Tall', - 'embedded': { - 'Insert_Deco_112': { - 'hash': 112, - 'name': 'Insert Deco', - 'savables': {} - }, - 'Pole_Hugger_Tall_15532': { - 'hash': 15532, - 'name': 'Pole Hugger Tall', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Pommel': { - 'hash': 15658, - 'name': 'Pommel', - 'embedded': { - 'Heat_Point_Collection_58710': { - 'hash': 58710, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_PommelType_112': { - 'hash': 112, - 'name': 'Insert PommelType', - 'savables': {} - }, - 'Pommel_15532': { - 'hash': 15532, - 'name': 'Pommel', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Pommel_Circle': { - 'hash': 57966, - 'name': 'Pommel Circle', - 'embedded': { - 'Heat_Point_Collection_58958': { - 'hash': 58958, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_PommelType_112': { - 'hash': 112, - 'name': 'Insert PommelType', - 'savables': {} - }, - 'Pommel_Circle_15532': { - 'hash': 15532, - 'name': 'Pommel Circle', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Pommel_Cone': { - 'hash': 52360, - 'name': 'Pommel Cone', - 'embedded': { - 'Insert_Deco_112': { - 'hash': 112, - 'name': 'Insert Deco', - 'savables': {} - }, - 'Pommel_Cone_15532': { - 'hash': 15532, - 'name': 'Pommel Cone', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Pommel_Diamond': { - 'hash': 42764, - 'name': 'Pommel Diamond', - 'embedded': { - 'Heat_Point_Collection_59204': { - 'hash': 59204, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_PommelType_112': { - 'hash': 112, - 'name': 'Insert PommelType', - 'savables': {} - }, - 'Pommel_Diamond_15532': { - 'hash': 15532, - 'name': 'Pommel Diamond', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Pommel_Large_Square': { - 'hash': 42138, - 'name': 'Pommel Large Square', - 'embedded': { - 'Heat_Point_Collection_59448': { - 'hash': 59448, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_PommelType_42136': { - 'hash': 42136, - 'name': 'Insert PommelType', - 'savables': {} - }, - 'Pommel_Large_Square_42132': { - 'hash': 42132, - 'name': 'Pommel Large Square', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Pommel_Squashed': { - 'hash': 1736, - 'name': 'Pommel Squashed', - 'embedded': { - 'Insert_Deco_112': { - 'hash': 112, - 'name': 'Insert Deco', - 'savables': {} - }, - 'Pommel_Squashed_15532': { - 'hash': 15532, - 'name': 'Pommel Squashed', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Pond_Test': { - 'hash': 58844, - 'name': 'Pond Test', - 'embedded': { - 'Heat_Area_15578': { - 'hash': 15578, - 'name': 'Heat Area', - 'savables': {} - }, - 'Pond_Test_21538': { - 'hash': 21538, - 'name': 'Pond Test', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - }, - 'LiquidContainer': { - 'hash': 4179293747, - 'name': 'LiquidContainer' - } - } - } - } - }, - 'Pond_Water': { - 'hash': 23384, - 'name': 'Pond Water', - 'embedded': { - 'Heat_Area_46624': { - 'hash': 46624, - 'name': 'Heat Area', - 'savables': {} - }, - 'Pond_Water_21272': { - 'hash': 21272, - 'name': 'Pond Water', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - }, - 'LiquidContainer': { - 'hash': 4179293747, - 'name': 'LiquidContainer' - } - } - } - } - }, - 'Post_Box': { - 'hash': 9562, - 'name': 'Post Box', - 'embedded': { - 'Handle_17172': { - 'hash': 17172, - 'name': 'Handle', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Post_Box_7104': { - 'hash': 7104, - 'name': 'Post Box', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - } - } - }, - 'Potato_Full_Burnt': { - 'hash': 1574, - 'name': 'Potato Full Burnt', - 'embedded': { - 'Cooking_23418': { - 'hash': 23418, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Potato_Full_Burnt_1198': { - 'hash': 1198, - 'name': 'Potato Full Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Potato_Full_Cooked': { - 'hash': 57840, - 'name': 'Potato Full Cooked', - 'embedded': { - 'Cooking_9014': { - 'hash': 9014, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Potato_Full_Cooked_57464': { - 'hash': 57464, - 'name': 'Potato Full Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Potato_Full_Ripe': { - 'hash': 54692, - 'name': 'Potato Full Ripe', - 'embedded': { - 'Cooking_11142': { - 'hash': 11142, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Potato_Full_Ripe_54316': { - 'hash': 54316, - 'name': 'Potato Full Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Potato_Full_Unripe': { - 'hash': 52146, - 'name': 'Potato Full Unripe', - 'embedded': { - 'Cooking_31548': { - 'hash': 31548, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Potato_Full_Unripe_51770': { - 'hash': 51770, - 'name': 'Potato Full Unripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Potato_Growth': { - 'hash': 49408, - 'name': 'Potato Growth', - 'embedded': { - 'Potato_Growth_33458': { - 'hash': 33458, - 'name': 'Potato Growth', - 'savables': { - 'GrowerComponent': { - 'hash': 3402094521, - 'name': 'GrowerComponent' - } - } - } - } - }, - 'Potato_Half_Burnt': { - 'hash': 59748, - 'name': 'Potato Half Burnt', - 'embedded': { - 'Cooking_23418': { - 'hash': 23418, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Cooking_32800': { - 'hash': 32800, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Potato_Half_Burnt_59372': { - 'hash': 59372, - 'name': 'Potato Half Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Potato_Half_Cooked': { - 'hash': 50612, - 'name': 'Potato Half Cooked', - 'embedded': { - 'Cooking_32982': { - 'hash': 32982, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Cooking_9014': { - 'hash': 9014, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Potato_Half_Cooked_50236': { - 'hash': 50236, - 'name': 'Potato Half Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Potato_Half_Ripe': { - 'hash': 48134, - 'name': 'Potato Half Ripe', - 'embedded': { - 'Cooking_11142': { - 'hash': 11142, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Cooking_33006': { - 'hash': 33006, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Potato_Half_Ripe_47758': { - 'hash': 47758, - 'name': 'Potato Half Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Potato_Half_Unripe': { - 'hash': 45822, - 'name': 'Potato Half Unripe', - 'embedded': { - 'Cooking_31548': { - 'hash': 31548, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Cooking_33396': { - 'hash': 33396, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Potato_Half_Unripe_45446': { - 'hash': 45446, - 'name': 'Potato Half Unripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'RaycastCrafter': { - 'hash': 2815374842, - 'name': 'RaycastCrafter' - } - } - } - } - }, - 'Potato_Plant_Growth': { - 'hash': 15786, - 'name': 'Potato Plant Growth', - 'embedded': { - 'Potato_Plant_Growth_33458': { - 'hash': 33458, - 'name': 'Potato Plant Growth', - 'savables': { - 'GrowerComponent': { - 'hash': 3402094521, - 'name': 'GrowerComponent' - } - } - } - } - }, - 'Potato_Plant_Stage_1': { - 'hash': 62602, - 'name': 'Potato Plant Stage 1', - 'embedded': { - 'Potato_Plant_Stage_1_63514': { - 'hash': 63514, - 'name': 'Potato Plant Stage 1', - 'savables': {} - } - } - }, - 'Potato_Plant_Stage_2': { - 'hash': 63530, - 'name': 'Potato Plant Stage 2', - 'embedded': { - 'Potato_Plant_Stage_2_63514': { - 'hash': 63514, - 'name': 'Potato Plant Stage 2', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Potato_Plant_Stage_3': { - 'hash': 54788, - 'name': 'Potato Plant Stage 3', - 'embedded': { - 'Potato_Plant_Stage_3_54748': { - 'hash': 54748, - 'name': 'Potato Plant Stage 3', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Potato_Puree_Recipe_Burnt_Stew': { - 'hash': 57936, - 'name': 'Potato_Puree_Recipe_Burnt_Stew', - 'embedded': {} - }, - 'Potato_Puree_Recipe_Cooked_Stew': { - 'hash': 57960, - 'name': 'Potato_Puree_Recipe_Cooked_Stew', - 'embedded': {} - }, - 'Potato_Puree_Recipe_Raw_Stew': { - 'hash': 57918, - 'name': 'Potato_Puree_Recipe_Raw_Stew', - 'embedded': {} - }, - 'Potato_Sapling': { - 'hash': 50692, - 'name': 'Potato Sapling', - 'embedded': { - 'Potato_Sapling_52858': { - 'hash': 52858, - 'name': 'Potato Sapling', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Potatoes_29060': { - 'hash': 29060, - 'name': 'Potatoes', - 'savables': { - 'GrowerGroup': { - 'hash': 2363255897, - 'name': 'GrowerGroup' - } - } - } - } - }, - 'Potion_Hoops_Side_Tool_Attachment': { - 'hash': 31418, - 'name': 'Potion Hoops Side Tool Attachment', - 'embedded': { - 'Dock_Mid_31416': { - 'hash': 31416, - 'name': 'Dock Mid', - 'savables': { - 'AdditionalOwnedDock': { - 'hash': 2592242915, - 'name': 'AdditionalOwnedDock' - } - } - }, - 'Dock_Side_21918': { - 'hash': 21918, - 'name': 'Dock Side', - 'savables': { - 'AdditionalOwnedDock': { - 'hash': 2592242915, - 'name': 'AdditionalOwnedDock' - } - } - }, - 'Dock_Side_22020': { - 'hash': 22020, - 'name': 'Dock Side', - 'savables': { - 'AdditionalOwnedDock': { - 'hash': 2592242915, - 'name': 'AdditionalOwnedDock' - } - } - }, - 'Insert_Bag_Attach_7796': { - 'hash': 7796, - 'name': 'Insert Bag Attach', - 'savables': {} - }, - 'Potion_Hoops_Side_Tool_Attachment_7868': { - 'hash': 7868, - 'name': 'Potion Hoops Side Tool Attachment', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Storage_53262': { - 'hash': 53262, - 'name': 'Storage', - 'savables': {} - }, - 'potionHoops_sideTool_pad_01_30876': { - 'hash': 30876, - 'name': 'potionHoops_sideTool_pad_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'potionHoops_sideTool_ringHolder_29430': { - 'hash': 29430, - 'name': 'potionHoops_sideTool_ringHolder', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'potionHoops_sideTool_ringPin_01_30888': { - 'hash': 30888, - 'name': 'potionHoops_sideTool_ringPin_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'potionHoops_sideTool_ringPin_02_30884': { - 'hash': 30884, - 'name': 'potionHoops_sideTool_ringPin_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'potionHoops_sideTool_ringPin_03_30892': { - 'hash': 30892, - 'name': 'potionHoops_sideTool_ringPin_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'potionHoops_sideTool_strap_01_30880': { - 'hash': 30880, - 'name': 'potionHoops_sideTool_strap_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Potion_Medium': { - 'hash': 23644, - 'name': 'Potion Medium', - 'embedded': { - 'CapPickup_21290': { - 'hash': 21290, - 'name': 'CapPickup', - 'savables': { - 'CapPickup': { - 'hash': 3082855726, - 'name': 'CapPickup' - } - } - }, - 'Potion_Medium_23646': { - 'hash': 23646, - 'name': 'Potion Medium', - 'savables': { - 'LiquidContainer': { - 'hash': 4179293747, - 'name': 'LiquidContainer' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Potion_Small': { - 'hash': 62934, - 'name': 'Potion_Small', - 'embedded': {} - }, - 'Pouch': { - 'hash': 38942, - 'name': 'Pouch', - 'embedded': { - 'Pouch_36072': { - 'hash': 36072, - 'name': 'Pouch', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Storage_36080': { - 'hash': 36080, - 'name': 'Storage', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - } - } - }, - 'Pouch_Training': { - 'hash': 57348, - 'name': 'Pouch Training', - 'embedded': { - 'Pouch_Training_36072': { - 'hash': 36072, - 'name': 'Pouch Training', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Storage_65008': { - 'hash': 65008, - 'name': 'Storage', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - } - } - }, - 'Poultry_Onion_Mushroom_Recipe_Burnt_Stew': { - 'hash': 57780, - 'name': 'Poultry_Onion_Mushroom_Recipe_Burnt_Stew', - 'embedded': {} - }, - 'Poultry_Onion_Mushroom_Recipe_Cooked_Stew': { - 'hash': 57762, - 'name': 'Poultry_Onion_Mushroom_Recipe_Cooked_Stew', - 'embedded': {} - }, - 'Poultry_Onion_Mushroom_Recipe_Raw_Stew': { - 'hash': 57804, - 'name': 'Poultry_Onion_Mushroom_Recipe_Raw_Stew', - 'embedded': {} - }, - 'Poultry_Potato_Recipe_Burnt_Stew': { - 'hash': 57894, - 'name': 'Poultry_Potato_Recipe_Burnt_Stew', - 'embedded': {} - }, - 'Poultry_Potato_Recipe_Cooked_Stew': { - 'hash': 57852, - 'name': 'Poultry_Potato_Recipe_Cooked_Stew', - 'embedded': {} - }, - 'Poultry_Potato_Recipe_Raw_Stew': { - 'hash': 57876, - 'name': 'Poultry_Potato_Recipe_Raw_Stew', - 'embedded': {} - }, - 'Poultry_Recipe_Burnt_Stew': { - 'hash': 10830, - 'name': 'Poultry_Recipe_Burnt_Stew', - 'embedded': {} - }, - 'Poultry_Recipe_Cooked_Stew': { - 'hash': 11448, - 'name': 'Poultry_Recipe_Cooked_Stew', - 'embedded': {} - }, - 'Poultry_Recipe_Raw_Stew': { - 'hash': 12132, - 'name': 'Poultry_Recipe_Raw_Stew', - 'embedded': {} - }, - 'Power_Strike_Counter': { - 'hash': 37516, - 'name': 'Power Strike Counter', - 'embedded': { - 'Power_Strike_Counter_63778': { - 'hash': 63778, - 'name': 'Power Strike Counter', - 'savables': {} - } - } - }, - 'Practice_Gate': { - 'hash': 64704, - 'name': 'Practice_Gate', - 'embedded': {} - }, - 'Profession_Upgrade_Shrine': { - 'hash': 32200, - 'name': 'Profession Upgrade Shrine', - 'embedded': { - 'Hand_Touch_46540': { - 'hash': 46540, - 'name': 'Hand Touch', - 'savables': {} - }, - 'Landscape_Finder_33664': { - 'hash': 33664, - 'name': 'Landscape Finder', - 'savables': { - 'Landmark': { - 'hash': 2590537994, - 'name': 'Landmark' - }, - 'LandmarkDiscoverZone': { - 'hash': 4095875831, - 'name': 'LandmarkDiscoverZone' - } - } - }, - 'Profession_Upgrade_Shrine_53594': { - 'hash': 53594, - 'name': 'Profession Upgrade Shrine', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - }, - 'SkillShrine': { - 'hash': 2190886200, - 'name': 'SkillShrine' - } - } - }, - 'Testing_Area_29220': { - 'hash': 29220, - 'name': 'Testing Area', - 'savables': {} - } - } - }, - 'Prongs': { - 'hash': 40460, - 'name': 'Prongs', - 'embedded': { - 'Prongs_13190': { - 'hash': 13190, - 'name': 'Prongs', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Weapon_Dock_5626': { - 'hash': 5626, - 'name': 'Weapon Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - } - } - }, - 'Proto_Greater_Got_Bramble_Wall': { - 'hash': 34050, - 'name': 'Proto Greater Got Bramble Wall', - 'embedded': { - 'Proto_Greater_Got_Bramble_Wall_34034': { - 'hash': 34034, - 'name': 'Proto Greater Got Bramble Wall', - 'savables': {} - } - } - }, - 'Pumpkin_Growth': { - 'hash': 59922, - 'name': 'Pumpkin Growth', - 'embedded': { - 'Pumpkin_Growth_33458': { - 'hash': 33458, - 'name': 'Pumpkin Growth', - 'savables': { - 'GrowerComponent': { - 'hash': 3402094521, - 'name': 'GrowerComponent' - } - } - } - } - }, - 'Pumpkin_Recipe_Burnt_Stew': { - 'hash': 62678, - 'name': 'Pumpkin_Recipe_Burnt_Stew', - 'embedded': {} - }, - 'Pumpkin_Recipe_Cooked_Stew': { - 'hash': 62694, - 'name': 'Pumpkin_Recipe_Cooked_Stew', - 'embedded': {} - }, - 'Pumpkin_Recipe_Raw_Stew': { - 'hash': 62724, - 'name': 'Pumpkin_Recipe_Raw_Stew', - 'embedded': {} - }, - 'Pumpkin_Tree': { - 'hash': 49086, - 'name': 'Pumpkin Tree', - 'embedded': { - 'Pumpkin_Tree_46510': { - 'hash': 46510, - 'name': 'Pumpkin Tree', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Pumpkin_Tree_Growth': { - 'hash': 41658, - 'name': 'Pumpkin Tree Growth', - 'embedded': { - 'Pumpkin_Tree_Growth_33458': { - 'hash': 33458, - 'name': 'Pumpkin Tree Growth', - 'savables': { - 'GrowerComponent': { - 'hash': 3402094521, - 'name': 'GrowerComponent' - } - } - } - } - }, - 'Pumpkin_Tree_Separated': { - 'hash': 23566, - 'name': 'Pumpkin_Tree_Separated', - 'embedded': {} - }, - 'Pumpkin_Tree_Stage_1': { - 'hash': 38672, - 'name': 'Pumpkin Tree Stage 1', - 'embedded': { - 'Pumpkin_Tree_Stage_1_63514': { - 'hash': 63514, - 'name': 'Pumpkin Tree Stage 1', - 'savables': {} - } - } - }, - 'Pumpkin_Tree_Stage_2': { - 'hash': 42508, - 'name': 'Pumpkin Tree Stage 2', - 'embedded': { - 'Pumpkin_Tree_Stage_2_46510': { - 'hash': 46510, - 'name': 'Pumpkin Tree Stage 2', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Pumpkin_Tree_Stage_3': { - 'hash': 63038, - 'name': 'Pumpkin Tree Stage 3', - 'embedded': { - 'Pumpkin_Tree_Stage_3_46510': { - 'hash': 46510, - 'name': 'Pumpkin Tree Stage 3', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Puzzle_Orb_1': { - 'hash': 31620, - 'name': 'Puzzle Orb 1', - 'embedded': { - 'Puzzle_Orb_1_11514': { - 'hash': 11514, - 'name': 'Puzzle Orb 1', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Puzzle_Orb_2': { - 'hash': 47150, - 'name': 'Puzzle Orb 2', - 'embedded': { - 'Puzzle_Orb_2_11514': { - 'hash': 11514, - 'name': 'Puzzle Orb 2', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Puzzle_Orb_Restrictor': { - 'hash': 29276, - 'name': 'Puzzle Orb Restrictor', - 'embedded': { - 'Puzzle_Orb_Restrictor_29424': { - 'hash': 29424, - 'name': 'Puzzle Orb Restrictor', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'PositionRestrictor': { - 'hash': 1776498660, - 'name': 'PositionRestrictor' - } - } - } - } - }, - 'Puzzle_Pillar_with_Wheel_Bridge': { - 'hash': 15908, - 'name': 'Puzzle Pillar with Wheel Bridge', - 'embedded': { - 'Elevator_20982': { - 'hash': 20982, - 'name': 'Elevator', - 'savables': { - 'WayPointPath': { - 'hash': 1063725326, - 'name': 'WayPointPath' - } - } - }, - 'Grip_(1)_54050': { - 'hash': 54050, - 'name': 'Grip (1)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(2)_54614': { - 'hash': 54614, - 'name': 'Grip (2)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(3)_56370': { - 'hash': 56370, - 'name': 'Grip (3)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(4)_53470': { - 'hash': 53470, - 'name': 'Grip (4)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(5)_19654': { - 'hash': 19654, - 'name': 'Grip (5)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_56728': { - 'hash': 56728, - 'name': 'Grip', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Puzzle_Pillar_with_Wheel_Bridge_31136': { - 'hash': 31136, - 'name': 'Puzzle Pillar with Wheel Bridge', - 'savables': { - 'LogicFloatReceiver': { - 'hash': 3188272159, - 'name': 'LogicFloatReceiver' - } - } - }, - 'WheelBridge(Clone)_43884': { - 'hash': 43884, - 'name': 'WheelBridge(Clone)', - 'savables': { - 'LogicFloatReceiver': { - 'hash': 3188272159, - 'name': 'LogicFloatReceiver' - }, - 'LogicFloatSender': { - 'hash': 2120963769, - 'name': 'LogicFloatSender' - }, - 'RotatePickup': { - 'hash': 2498617949, - 'name': 'RotatePickup' - } - } - }, - 'wheel_origin_43868': { - 'hash': 43868, - 'name': 'wheel_origin', - 'savables': { - 'WheelGrab': { - 'hash': 320224849, - 'name': 'WheelGrab' - } - } - } - } - }, - 'Quest_Board': { - 'hash': 57298, - 'name': 'Quest Board', - 'embedded': { - 'Quest_Board_57352': { - 'hash': 57352, - 'name': 'Quest Board', - 'savables': {} - } - } - }, - 'Quiver': { - 'hash': 64640, - 'name': 'Quiver', - 'embedded': { - 'Dock_33558': { - 'hash': 33558, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Quiver_33568': { - 'hash': 33568, - 'name': 'Quiver', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'standard_quiver_body_49088': { - 'hash': 49088, - 'name': 'standard_quiver_body', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_quiver_body_laces_01_43824': { - 'hash': 43824, - 'name': 'standard_quiver_body_laces_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_quiver_body_lipBlock_49092': { - 'hash': 49092, - 'name': 'standard_quiver_body_lipBlock', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_quiver_metalRingBottom_49080': { - 'hash': 49080, - 'name': 'standard_quiver_metalRingBottom', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_quiver_metalRingTop_49084': { - 'hash': 49084, - 'name': 'standard_quiver_metalRingTop', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_quiver_strap_49068': { - 'hash': 49068, - 'name': 'standard_quiver_strap', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_quiver_strap_clasp_01_49072': { - 'hash': 49072, - 'name': 'standard_quiver_strap_clasp_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_quiver_strap_clasp_02_49076': { - 'hash': 49076, - 'name': 'standard_quiver_strap_clasp_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_quiver_strap_wraps_43820': { - 'hash': 43820, - 'name': 'standard_quiver_strap_wraps', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Random_Placement_Crate': { - 'hash': 8246, - 'name': 'Random Placement Crate', - 'embedded': { - 'Crate_place(Clone)_14764': { - 'hash': 14764, - 'name': 'Crate place(Clone)', - 'savables': { - 'GeneratedLoot': { - 'hash': 3642863935, - 'name': 'GeneratedLoot' - } - } - }, - 'Dock_1_2780': { - 'hash': 2780, - 'name': 'Dock 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_2_31842': { - 'hash': 31842, - 'name': 'Dock 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_3_31266': { - 'hash': 31266, - 'name': 'Dock 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_4_30878': { - 'hash': 30878, - 'name': 'Dock 4', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Random_Placement_Crate_14764': { - 'hash': 14764, - 'name': 'Random Placement Crate', - 'savables': {} - } - } - }, - 'Random_Spawn_Rectangle': { - 'hash': 24644, - 'name': 'Random_Spawn_Rectangle', - 'embedded': {} - }, - 'Rapier_Blade': { - 'hash': 11332, - 'name': 'Rapier Blade', - 'embedded': { - 'Heat_Point_Collection_63016': { - 'hash': 63016, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_Straight_SwordType_7796': { - 'hash': 7796, - 'name': 'Insert Straight SwordType', - 'savables': {} - }, - 'Rapier_Blade_35392': { - 'hash': 35392, - 'name': 'Rapier Blade', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'metal_blade_rapier_full_geo_LOD0_6834': { - 'hash': 6834, - 'name': 'metal_blade_rapier_full_geo_LOD0', - 'savables': {} - } - } - }, - 'Recycler': { - 'hash': 60684, - 'name': 'Recycler', - 'embedded': { - 'Display_Dock_6940': { - 'hash': 6940, - 'name': 'Display Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Display_Dock_6988': { - 'hash': 6988, - 'name': 'Display Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Display_Dock_6992': { - 'hash': 6992, - 'name': 'Display Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_Fuel_54958': { - 'hash': 54958, - 'name': 'Dock Fuel', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_Output_44868': { - 'hash': 44868, - 'name': 'Dock Output', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_Output_58172': { - 'hash': 58172, - 'name': 'Dock Output', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_Output_61316': { - 'hash': 61316, - 'name': 'Dock Output', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Handle_24422': { - 'hash': 24422, - 'name': 'Handle', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Handle_6394': { - 'hash': 6394, - 'name': 'Handle', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'HeatArea_37766': { - 'hash': 37766, - 'name': 'HeatArea', - 'savables': {} - }, - 'Recycler_57752': { - 'hash': 57752, - 'name': 'Recycler', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - }, - 'Recycler': { - 'hash': 2450553269, - 'name': 'Recycler' - } - } - }, - 'recycler_fuelHatch_37522': { - 'hash': 37522, - 'name': 'recycler_fuelHatch', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'smelter_bellows_arm_jnt_25672': { - 'hash': 25672, - 'name': 'smelter_bellows_arm_jnt', - 'savables': {} - } - } - }, - 'Red_Iron_Ingot': { - 'hash': 31034, - 'name': 'Red Iron Ingot', - 'embedded': { - 'Heat_Point_Collection_13552': { - 'hash': 13552, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Red_Iron_Ingot_32738': { - 'hash': 32738, - 'name': 'Red Iron Ingot', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Red_Mushroom_Recipe_Burnt_Stew': { - 'hash': 63290, - 'name': 'Red_Mushroom_Recipe_Burnt_Stew', - 'embedded': {} - }, - 'Red_Mushroom_Recipe_Cooked_Stew': { - 'hash': 62660, - 'name': 'Red_Mushroom_Recipe_Cooked_Stew', - 'embedded': {} - }, - 'Red_Mushroom_Recipe_Raw_Stew': { - 'hash': 62024, - 'name': 'Red_Mushroom_Recipe_Raw_Stew', - 'embedded': {} - }, - 'Red_Mushroom_Shield': { - 'hash': 49188, - 'name': 'Red Mushroom Shield', - 'embedded': { - 'Red_Mushroom_Shield_49190': { - 'hash': 49190, - 'name': 'Red Mushroom Shield', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Red_Sauce_Recipe_Burnt_Stew': { - 'hash': 57978, - 'name': 'Red_Sauce_Recipe_Burnt_Stew', - 'embedded': {} - }, - 'Red_Sauce_Recipe_Cooked_Stew': { - 'hash': 58026, - 'name': 'Red_Sauce_Recipe_Cooked_Stew', - 'embedded': {} - }, - 'Red_Sauce_Recipe_Raw_Stew': { - 'hash': 58002, - 'name': 'Red_Sauce_Recipe_Raw_Stew', - 'embedded': {} - }, - 'Redwood_Gotera_Core': { - 'hash': 41402, - 'name': 'Redwood Gotera Core', - 'embedded': { - 'Redwood_Gotera_Core_41418': { - 'hash': 41418, - 'name': 'Redwood Gotera Core', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Redwood_Tree_Growth': { - 'hash': 48248, - 'name': 'Redwood Tree Growth', - 'embedded': { - 'Redwood_Tree_Growth_33458': { - 'hash': 33458, - 'name': 'Redwood Tree Growth', - 'savables': { - 'GrowerComponent': { - 'hash': 3402094521, - 'name': 'GrowerComponent' - } - } - } - } - }, - 'Redwood_Tree_Seed': { - 'hash': 55054, - 'name': 'Redwood Tree Seed', - 'embedded': { - 'Redwood_Tree_Seed_35258': { - 'hash': 35258, - 'name': 'Redwood Tree Seed', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'RaycastCrafter': { - 'hash': 2815374842, - 'name': 'RaycastCrafter' - } - } - } - } - }, - 'Redwood_Tree_Stage_1': { - 'hash': 17526, - 'name': 'Redwood Tree Stage 1', - 'embedded': { - 'Redwood_Tree_Stage_1_63514': { - 'hash': 63514, - 'name': 'Redwood Tree Stage 1', - 'savables': {} - } - } - }, - 'Repair_Box': { - 'hash': 3458, - 'name': 'Repair Box', - 'embedded': { - 'Cost_1_22852': { - 'hash': 22852, - 'name': 'Cost 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Cost_2_22786': { - 'hash': 22786, - 'name': 'Cost 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Cost_3_22772': { - 'hash': 22772, - 'name': 'Cost 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_1_22642': { - 'hash': 22642, - 'name': 'Dock 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_2_22692': { - 'hash': 22692, - 'name': 'Dock 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_3_22698': { - 'hash': 22698, - 'name': 'Dock 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Landmark_Finder_5660': { - 'hash': 5660, - 'name': 'Landmark Finder', - 'savables': { - 'Landmark': { - 'hash': 2590537994, - 'name': 'Landmark' - }, - 'LandmarkDiscoverZone': { - 'hash': 4095875831, - 'name': 'LandmarkDiscoverZone' - } - } - }, - 'Quest_Marker_-_Repair_Box_51948': { - 'hash': 51948, - 'name': 'Quest Marker - Repair Box', - 'savables': { - 'ManualCondition': { - 'hash': 1268269765, - 'name': 'ManualCondition' - }, - 'RepairableObjectComparisonCondition': { - 'hash': 1558189723, - 'name': 'RepairableObjectComparisonCondition' - } - } - }, - 'RepairBox_15188': { - 'hash': 15188, - 'name': 'RepairBox', - 'savables': {} - }, - 'Repair_Box_65496': { - 'hash': 65496, - 'name': 'Repair Box', - 'savables': { - 'RepairBox': { - 'hash': 3820454400, - 'name': 'RepairBox' - } - } - } - } - }, - 'Repair_Box_Standing_Panel': { - 'hash': 32704, - 'name': 'Repair Box Standing Panel', - 'embedded': { - 'Cost_1_32664': { - 'hash': 32664, - 'name': 'Cost 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Cost_2_32662': { - 'hash': 32662, - 'name': 'Cost 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Cost_3_32660': { - 'hash': 32660, - 'name': 'Cost 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_1_32654': { - 'hash': 32654, - 'name': 'Dock 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_2_32656': { - 'hash': 32656, - 'name': 'Dock 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_3_32658': { - 'hash': 32658, - 'name': 'Dock 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Landmark_Finder_4224': { - 'hash': 4224, - 'name': 'Landmark Finder', - 'savables': { - 'Landmark': { - 'hash': 2590537994, - 'name': 'Landmark' - }, - 'LandmarkDiscoverZone': { - 'hash': 4095875831, - 'name': 'LandmarkDiscoverZone' - } - } - }, - 'Quest_Marker_-_Repair_Box_51948': { - 'hash': 51948, - 'name': 'Quest Marker - Repair Box', - 'savables': { - 'ManualCondition': { - 'hash': 1268269765, - 'name': 'ManualCondition' - }, - 'RepairableObjectComparisonCondition': { - 'hash': 1558189723, - 'name': 'RepairableObjectComparisonCondition' - } - } - }, - 'RepairBox_15188': { - 'hash': 15188, - 'name': 'RepairBox', - 'savables': {} - }, - 'Repair_Box_Standing_Panel_32702': { - 'hash': 32702, - 'name': 'Repair Box Standing Panel', - 'savables': { - 'RepairBox': { - 'hash': 3820454400, - 'name': 'RepairBox' - } - } - } - } - }, - 'Repair_Box_Wall_Panel': { - 'hash': 41842, - 'name': 'Repair Box Wall Panel', - 'embedded': { - 'Cost_1_41802': { - 'hash': 41802, - 'name': 'Cost 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Cost_2_41800': { - 'hash': 41800, - 'name': 'Cost 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Cost_3_41798': { - 'hash': 41798, - 'name': 'Cost 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_1_41792': { - 'hash': 41792, - 'name': 'Dock 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_2_41794': { - 'hash': 41794, - 'name': 'Dock 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_3_41796': { - 'hash': 41796, - 'name': 'Dock 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Landmark_Finder_3504': { - 'hash': 3504, - 'name': 'Landmark Finder', - 'savables': { - 'Landmark': { - 'hash': 2590537994, - 'name': 'Landmark' - }, - 'LandmarkDiscoverZone': { - 'hash': 4095875831, - 'name': 'LandmarkDiscoverZone' - } - } - }, - 'Quest_Marker_-_Repair_Box_51948': { - 'hash': 51948, - 'name': 'Quest Marker - Repair Box', - 'savables': { - 'ManualCondition': { - 'hash': 1268269765, - 'name': 'ManualCondition' - }, - 'RepairableObjectComparisonCondition': { - 'hash': 1558189723, - 'name': 'RepairableObjectComparisonCondition' - } - } - }, - 'RepairBox_15188': { - 'hash': 15188, - 'name': 'RepairBox', - 'savables': {} - }, - 'Repair_Box_Wall_Panel_41840': { - 'hash': 41840, - 'name': 'Repair Box Wall Panel', - 'savables': { - 'RepairBox': { - 'hash': 3820454400, - 'name': 'RepairBox' - } - } - } - } - }, - 'Repeater': { - 'hash': 40046, - 'name': 'Repeater', - 'embedded': {} - }, - 'Rock_Boulder_01': { - 'hash': 63838, - 'name': 'Rock_Boulder_01', - 'embedded': {} - }, - 'Rock_Boulder_02': { - 'hash': 63828, - 'name': 'Rock_Boulder_02', - 'embedded': {} - }, - 'Rock_Boulder_03': { - 'hash': 63836, - 'name': 'Rock_Boulder_03', - 'embedded': {} - }, - 'Rock_Boulder_04': { - 'hash': 63834, - 'name': 'Rock_Boulder_04', - 'embedded': {} - }, - 'Rock_Cluster': { - 'hash': 63824, - 'name': 'Rock Cluster', - 'embedded': { - 'Rock_Cluster_18314': { - 'hash': 18314, - 'name': 'Rock Cluster', - 'savables': {} - } - } - }, - 'Rock_Cluster_Tutorial': { - 'hash': 25922, - 'name': 'Rock Cluster Tutorial', - 'embedded': { - 'Rock_Cluster_Tutorial_18314': { - 'hash': 18314, - 'name': 'Rock Cluster Tutorial', - 'savables': {} - } - } - }, - 'Rock_Spire_Gcore_Dynamic': { - 'hash': 40128, - 'name': 'Rock Spire Gcore Dynamic', - 'embedded': { - 'Death_Fern_Spawner_32170': { - 'hash': 32170, - 'name': 'Death Fern Spawner', - 'savables': { - 'CylindricalBoundsSurface': { - 'hash': 34507654, - 'name': 'CylindricalBoundsSurface' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - }, - 'Health_Vine_Spawner_39788': { - 'hash': 39788, - 'name': 'Health Vine Spawner', - 'savables': { - 'DirectionalBoundsSurface': { - 'hash': 1962842866, - 'name': 'DirectionalBoundsSurface' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - }, - 'Rock_Spire_Gcore_Dynamic_23456': { - 'hash': 23456, - 'name': 'Rock Spire Gcore Dynamic', - 'savables': {} - }, - 'Vine_Boulder_Spawner_53936': { - 'hash': 53936, - 'name': 'Vine Boulder Spawner', - 'savables': { - 'CylindricalBoundsSurface': { - 'hash': 34507654, - 'name': 'CylindricalBoundsSurface' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - } - } - }, - 'Rock_WallBoulder_02': { - 'hash': 63832, - 'name': 'Rock_WallBoulder_02', - 'embedded': {} - }, - 'Rod_Long': { - 'hash': 44066, - 'name': 'Rod Long', - 'embedded': { - 'Dock_32818': { - 'hash': 32818, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Rod_Long_24200': { - 'hash': 24200, - 'name': 'Rod Long', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_AxeType_37426': { - 'hash': 37426, - 'name': 'Slot AxeType', - 'savables': {} - }, - 'Slot_EdgeType_Craft_31944': { - 'hash': 31944, - 'name': 'Slot EdgeType Craft', - 'savables': {} - }, - 'Slot_Multi_53940': { - 'hash': 53940, - 'name': 'Slot Multi', - 'savables': {} - } - } - }, - 'Rod_Medium': { - 'hash': 44204, - 'name': 'Rod Medium', - 'embedded': { - 'Dock_32818': { - 'hash': 32818, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Rod_Medium_44084': { - 'hash': 44084, - 'name': 'Rod Medium', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_AxeType_15522': { - 'hash': 15522, - 'name': 'Slot AxeType', - 'savables': {} - }, - 'Slot_Deco_37438': { - 'hash': 37438, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_EdgeType_Craft_35298': { - 'hash': 35298, - 'name': 'Slot EdgeType Craft', - 'savables': {} - }, - 'Slot_Multi_31156': { - 'hash': 31156, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_Multi_39008': { - 'hash': 39008, - 'name': 'Slot Multi', - 'savables': {} - } - } - }, - 'Rod_Slim_40cm': { - 'hash': 59588, - 'name': 'Rod Slim 40cm', - 'embedded': { - 'Rod_Slim_40cm_37330': { - 'hash': 37330, - 'name': 'Rod Slim 40cm', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Slot_Multi_44690': { - 'hash': 44690, - 'name': 'Slot Multi', - 'savables': {} - } - } - }, - 'Rope_Clump': { - 'hash': 43836, - 'name': 'Rope Clump', - 'embedded': { - 'Rope_Clump_47776': { - 'hash': 47776, - 'name': 'Rope Clump', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Rope_Pully_Puzzle': { - 'hash': 51434, - 'name': 'Rope Pully Puzzle', - 'embedded': { - 'Rope_Grab_57800': { - 'hash': 57800, - 'name': 'Rope Grab', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'RopeGrab': { - 'hash': 237360636, - 'name': 'RopeGrab' - } - } - }, - 'Rope_Length_57794': { - 'hash': 57794, - 'name': 'Rope Length', - 'savables': {} - }, - 'Rope_Pully_Puzzle_4580': { - 'hash': 4580, - 'name': 'Rope Pully Puzzle', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'LogicFloatReceiver': { - 'hash': 3188272159, - 'name': 'LogicFloatReceiver' - }, - 'LogicFloatSender': { - 'hash': 2120963769, - 'name': 'LogicFloatSender' - } - } - } - } - }, - 'Ruins_Elevator_Puzzle_Square': { - 'hash': 27582, - 'name': 'Ruins Elevator Puzzle Square', - 'embedded': { - 'Ruins_Elevator_Puzzle_Square_31136': { - 'hash': 31136, - 'name': 'Ruins Elevator Puzzle Square', - 'savables': {} - } - } - }, - 'Ruins_Elevator_Puzzle_Square_Crystal_Pillar': { - 'hash': 3512, - 'name': 'Ruins Elevator Puzzle Square Crystal Pillar', - 'embedded': { - 'Crystal_Blue(Clone)_(1)_40232': { - 'hash': 40232, - 'name': 'Crystal Blue(Clone) (1)', - 'savables': {} - }, - 'Elevator_20982': { - 'hash': 20982, - 'name': 'Elevator', - 'savables': { - 'WayPointPath': { - 'hash': 1063725326, - 'name': 'WayPointPath' - } - } - }, - 'Ruins_Elevator_Puzzle_Square_Crystal_Pillar_31136': { - 'hash': 31136, - 'name': 'Ruins Elevator Puzzle Square Crystal Pillar', - 'savables': { - 'LogicFloatReceiver': { - 'hash': 3188272159, - 'name': 'LogicFloatReceiver' - } - } - } - } - }, - 'Ruins_Elevator_Puzzle_Square_Large_Variant': { - 'hash': 4192, - 'name': 'Ruins Elevator Puzzle Square Large Variant', - 'embedded': { - 'Ruins_Elevator_Puzzle_Square_Large_Variant_16752': { - 'hash': 16752, - 'name': 'Ruins Elevator Puzzle Square Large Variant', - 'savables': {} - } - } - }, - 'Ruins_Elevator_Puzzle_Square_Pillar_Variant': { - 'hash': 22284, - 'name': 'Ruins Elevator Puzzle Square Pillar Variant', - 'embedded': { - 'Ruins_Elevator_Puzzle_Square_Pillar_Variant_31136': { - 'hash': 31136, - 'name': 'Ruins Elevator Puzzle Square Pillar Variant', - 'savables': {} - } - } - }, - 'Ruins_Hand_Touch_Activator': { - 'hash': 1002, - 'name': 'Ruins Hand Touch Activator', - 'embedded': { - 'Ruins_Hand_Touch_Activator_46540': { - 'hash': 46540, - 'name': 'Ruins Hand Touch Activator', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - } - } - } - } - }, - 'Ruins_Pillar_Crystal': { - 'hash': 58240, - 'name': 'Ruins Pillar Crystal', - 'embedded': { - 'Crystal_Blue(Clone)_(1)_40232': { - 'hash': 40232, - 'name': 'Crystal Blue(Clone) (1)', - 'savables': {} - }, - 'Ruins_Pillar_Crystal_58176': { - 'hash': 58176, - 'name': 'Ruins Pillar Crystal', - 'savables': {} - } - } - }, - 'Ruins_Sliding_Wall_Puzzle_Square': { - 'hash': 42494, - 'name': 'Ruins Sliding Wall Puzzle Square', - 'embedded': { - 'Ruins_Sliding_Wall_Puzzle_Square_42408': { - 'hash': 42408, - 'name': 'Ruins Sliding Wall Puzzle Square', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'SlidingDoor': { - 'hash': 3583462804, - 'name': 'SlidingDoor' - } - } - } - } - }, - 'Rusty_Axe': { - 'hash': 4412, - 'name': 'Rusty Axe', - 'embedded': { - 'Rusty_Axe_62196': { - 'hash': 62196, - 'name': 'Rusty Axe', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Rusty_Chisel': { - 'hash': 40366, - 'name': 'Rusty Chisel', - 'embedded': { - 'Rusty_Chisel_40156': { - 'hash': 40156, - 'name': 'Rusty Chisel', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Rusty_Greataxe': { - 'hash': 29296, - 'name': 'Rusty Greataxe', - 'embedded': { - 'Rusty_Greataxe_28996': { - 'hash': 28996, - 'name': 'Rusty Greataxe', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Rusty_Greatsword': { - 'hash': 63156, - 'name': 'Rusty Greatsword', - 'embedded': { - 'Rusty_Greatsword_62946': { - 'hash': 62946, - 'name': 'Rusty Greatsword', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Rusty_Hammer': { - 'hash': 36126, - 'name': 'Rusty Hammer', - 'embedded': { - 'Rusty_Hammer_58538': { - 'hash': 58538, - 'name': 'Rusty Hammer', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Rusty_Pickaxe': { - 'hash': 46874, - 'name': 'Rusty Pickaxe', - 'embedded': { - 'Rusty_Pickaxe_46574': { - 'hash': 46574, - 'name': 'Rusty Pickaxe', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Rusty_Pitchfork': { - 'hash': 59586, - 'name': 'Rusty Pitchfork', - 'embedded': { - 'Rusty_Pitchfork_58914': { - 'hash': 58914, - 'name': 'Rusty Pitchfork', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Rusty_Shield': { - 'hash': 20684, - 'name': 'Rusty Shield', - 'embedded': { - 'Insert_Shield_64244': { - 'hash': 64244, - 'name': 'Insert Shield', - 'savables': {} - }, - 'Rusty_Shield_20260': { - 'hash': 20260, - 'name': 'Rusty Shield', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Rusty_Short_Sword': { - 'hash': 44824, - 'name': 'Rusty Short Sword', - 'embedded': { - 'Rusty_Short_Sword_52378': { - 'hash': 52378, - 'name': 'Rusty Short Sword', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Rusty_Spade': { - 'hash': 33230, - 'name': 'Rusty Spade', - 'embedded': { - 'Fake_Pickup_6096': { - 'hash': 6096, - 'name': 'Fake Pickup', - 'savables': {} - }, - 'Rusty_Spade_60654': { - 'hash': 60654, - 'name': 'Rusty Spade', - 'savables': { - 'DiggingImpactor': { - 'hash': 3445325106, - 'name': 'DiggingImpactor' - }, - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Safe_Point': { - 'hash': 33004, - 'name': 'Safe Point', - 'embedded': { - 'Hand_Touch_46540': { - 'hash': 46540, - 'name': 'Hand Touch', - 'savables': {} - }, - 'Safe_Point_9078': { - 'hash': 9078, - 'name': 'Safe Point', - 'savables': { - 'CheckPoint': { - 'hash': 3704379512, - 'name': 'CheckPoint' - }, - 'SafePositionSetter': { - 'hash': 70871065, - 'name': 'SafePositionSetter' - } - } - } - } - }, - 'Sai': { - 'hash': 27038, - 'name': 'Sai', - 'embedded': { - 'Sai_36330': { - 'hash': 36330, - 'name': 'Sai', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Salt': { - 'hash': 49578, - 'name': 'Salt', - 'embedded': { - 'Salt_30920': { - 'hash': 30920, - 'name': 'Salt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Sandstone_Boulder_01': { - 'hash': 34168, - 'name': 'Sandstone_Boulder_01', - 'embedded': { - 'Sandstone_Boulder_01_13178': { - 'hash': 13178, - 'name': 'Sandstone_Boulder_01', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Sandstone_Boulder_02': { - 'hash': 8006, - 'name': 'Sandstone_Boulder_02', - 'embedded': { - 'Sandstone_Boulder_02_13178': { - 'hash': 13178, - 'name': 'Sandstone_Boulder_02', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Sandstone_Boulder_03': { - 'hash': 5050, - 'name': 'Sandstone_Boulder_03', - 'embedded': { - 'Sandstone_Boulder_03_13178': { - 'hash': 13178, - 'name': 'Sandstone_Boulder_03', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Sandstone_Cluster': { - 'hash': 41676, - 'name': 'Sandstone Cluster', - 'embedded': { - 'Sandstone_Cluster_41674': { - 'hash': 41674, - 'name': 'Sandstone Cluster', - 'savables': {} - } - } - }, - 'Sandstone_Stone': { - 'hash': 55930, - 'name': 'Sandstone Stone', - 'embedded': { - 'Sandstone_Stone_30920': { - 'hash': 30920, - 'name': 'Sandstone Stone', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Sapling': { - 'hash': 25994, - 'name': 'Sapling', - 'embedded': { - 'Sapling_52900': { - 'hash': 52900, - 'name': 'Sapling', - 'savables': {} - } - } - }, - 'Sapling_Freshly_Planted': { - 'hash': 25992, - 'name': 'Sapling Freshly Planted', - 'embedded': { - 'Sapling_Freshly_Planted_44026': { - 'hash': 44026, - 'name': 'Sapling Freshly Planted', - 'savables': {} - } - } - }, - 'ScaleTemp': { - 'hash': 64402, - 'name': 'ScaleTemp', - 'embedded': {} - }, - 'Schmeechee_Glowing': { - 'hash': 53576, - 'name': 'Schmeechee Glowing', - 'embedded': { - 'Schmeechee_53578': { - 'hash': 53578, - 'name': 'Schmeechee', - 'savables': {} - }, - 'Schmeechee_AI_58356': { - 'hash': 58356, - 'name': 'Schmeechee AI', - 'savables': {} - }, - 'Schmeechee_Glowing_53582': { - 'hash': 53582, - 'name': 'Schmeechee Glowing', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Schmeechee_Orange': { - 'hash': 63728, - 'name': 'Schmeechee Orange', - 'embedded': { - 'Schmeechee_21916': { - 'hash': 21916, - 'name': 'Schmeechee', - 'savables': {} - }, - 'Schmeechee_AI_58356': { - 'hash': 58356, - 'name': 'Schmeechee AI', - 'savables': {} - }, - 'Schmeechee_Orange_58792': { - 'hash': 58792, - 'name': 'Schmeechee Orange', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Schmeechee_Poisonous': { - 'hash': 31646, - 'name': 'Schmeechee Poisonous', - 'embedded': { - 'Schmeechee_31648': { - 'hash': 31648, - 'name': 'Schmeechee', - 'savables': {} - }, - 'Schmeechee_AI_58356': { - 'hash': 58356, - 'name': 'Schmeechee AI', - 'savables': {} - }, - 'Schmeechee_Poisonous_31652': { - 'hash': 31652, - 'name': 'Schmeechee Poisonous', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Schmeechee_Red': { - 'hash': 3532, - 'name': 'Schmeechee Red', - 'embedded': { - 'Schmeechee_3534': { - 'hash': 3534, - 'name': 'Schmeechee', - 'savables': {} - }, - 'Schmeechee_AI_58356': { - 'hash': 58356, - 'name': 'Schmeechee AI', - 'savables': {} - }, - 'Schmeechee_Red_3538': { - 'hash': 3538, - 'name': 'Schmeechee Red', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Scythe_Blade': { - 'hash': 26788, - 'name': 'Scythe Blade', - 'embedded': { - 'Insert_AxeType_7796': { - 'hash': 7796, - 'name': 'Insert AxeType', - 'savables': {} - }, - 'Scythe_Blade_29280': { - 'hash': 29280, - 'name': 'Scythe Blade', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'joint_blade_scythe_01_55756': { - 'hash': 55756, - 'name': 'joint_blade_scythe_01', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'joint_blade_scythe_02_55752': { - 'hash': 55752, - 'name': 'joint_blade_scythe_02', - 'savables': {} - }, - 'joint_blade_scythe_03_55776': { - 'hash': 55776, - 'name': 'joint_blade_scythe_03', - 'savables': {} - }, - 'joint_blade_scythe_04_55760': { - 'hash': 55760, - 'name': 'joint_blade_scythe_04', - 'savables': {} - }, - 'joint_blade_scythe_05_55772': { - 'hash': 55772, - 'name': 'joint_blade_scythe_05', - 'savables': {} - }, - 'joint_blade_scythe_06_55768': { - 'hash': 55768, - 'name': 'joint_blade_scythe_06', - 'savables': {} - }, - 'joint_blade_scythe_07_55764': { - 'hash': 55764, - 'name': 'joint_blade_scythe_07', - 'savables': {} - }, - 'metal_blade_scythe_full_geo_LOD0_2552': { - 'hash': 2552, - 'name': 'metal_blade_scythe_full_geo_LOD0', - 'savables': {} - } - } - }, - 'Select_Server_Orb': { - 'hash': 55760, - 'name': 'Select_Server_Orb', - 'embedded': {} - }, - 'Send_Post': { - 'hash': 53190, - 'name': 'Send Post', - 'embedded': { - 'Grab_31026': { - 'hash': 31026, - 'name': 'Grab', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Handle_5088': { - 'hash': 5088, - 'name': 'Handle', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Scroller_Touch_Mode_41098': { - 'hash': 41098, - 'name': 'Scroller Touch Mode', - 'savables': {} - }, - 'Send_Post_53122': { - 'hash': 53122, - 'name': 'Send Post', - 'savables': {} - } - } - }, - 'Set_Piece': { - 'hash': 62334, - 'name': 'Set_Piece', - 'embedded': {} - }, - 'Shelf': { - 'hash': 23630, - 'name': 'Shelf', - 'embedded': { - 'Dock_2780': { - 'hash': 2780, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60210': { - 'hash': 60210, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60212': { - 'hash': 60212, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60214': { - 'hash': 60214, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60216': { - 'hash': 60216, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60218': { - 'hash': 60218, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60220': { - 'hash': 60220, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60222': { - 'hash': 60222, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60224': { - 'hash': 60224, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60226': { - 'hash': 60226, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60228': { - 'hash': 60228, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60230': { - 'hash': 60230, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60232': { - 'hash': 60232, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60234': { - 'hash': 60234, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60236': { - 'hash': 60236, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60238': { - 'hash': 60238, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60240': { - 'hash': 60240, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60242': { - 'hash': 60242, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60244': { - 'hash': 60244, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60246': { - 'hash': 60246, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Shelf_5060': { - 'hash': 5060, - 'name': 'Shelf', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - } - } - }, - 'Shelf_Short': { - 'hash': 20452, - 'name': 'Shelf Short', - 'embedded': { - 'Dock_2780': { - 'hash': 2780, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_58082': { - 'hash': 58082, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_58084': { - 'hash': 58084, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_58086': { - 'hash': 58086, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_58088': { - 'hash': 58088, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_58090': { - 'hash': 58090, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_58092': { - 'hash': 58092, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_58094': { - 'hash': 58094, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_58096': { - 'hash': 58096, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_58098': { - 'hash': 58098, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Shelf_Short_60158': { - 'hash': 60158, - 'name': 'Shelf Short', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - } - } - }, - 'Shield': { - 'hash': 61656, - 'name': 'Shield', - 'embedded': { - 'Shield_32452': { - 'hash': 32452, - 'name': 'Shield', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Shield_Core_Bent_Middle': { - 'hash': 7232, - 'name': 'Shield Core Bent Middle', - 'embedded': { - 'Insert_Shield_Handle_112': { - 'hash': 112, - 'name': 'Insert Shield Handle', - 'savables': {} - }, - 'Shield_Core_Bent_Middle_10382': { - 'hash': 10382, - 'name': 'Shield Core Bent Middle', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Slot_Shield_Part_47874': { - 'hash': 47874, - 'name': 'Slot Shield Part', - 'savables': {} - }, - 'Slot_Shield_Part_8898': { - 'hash': 8898, - 'name': 'Slot Shield Part', - 'savables': {} - } - } - }, - 'Shield_Core_Circle_Middle': { - 'hash': 52756, - 'name': 'Shield Core Circle Middle', - 'embedded': { - 'Insert_Shield_Handle_112': { - 'hash': 112, - 'name': 'Insert Shield Handle', - 'savables': {} - }, - 'Shield_Core_Circle_Middle_52754': { - 'hash': 52754, - 'name': 'Shield Core Circle Middle', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Slot_Shield_Part_47874': { - 'hash': 47874, - 'name': 'Slot Shield Part', - 'savables': {} - }, - 'Slot_Shield_Part_8898': { - 'hash': 8898, - 'name': 'Slot Shield Part', - 'savables': {} - } - } - }, - 'Shield_Core_Handle': { - 'hash': 4530, - 'name': 'Shield Core Handle', - 'embedded': { - 'Shield_Core_Handle_4528': { - 'hash': 4528, - 'name': 'Shield Core Handle', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Slot_Shield_Handle_47874': { - 'hash': 47874, - 'name': 'Slot Shield Handle', - 'savables': {} - } - } - }, - 'Shield_Core_Holed_Middle': { - 'hash': 50602, - 'name': 'Shield Core Holed Middle', - 'embedded': { - 'Insert_Shield_Handle_112': { - 'hash': 112, - 'name': 'Insert Shield Handle', - 'savables': {} - }, - 'Shield_Core_Holed_Middle_50604': { - 'hash': 50604, - 'name': 'Shield Core Holed Middle', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Slot_Shield_Part_47874': { - 'hash': 47874, - 'name': 'Slot Shield Part', - 'savables': {} - }, - 'Slot_Shield_Part_8898': { - 'hash': 8898, - 'name': 'Slot Shield Part', - 'savables': {} - } - } - }, - 'Shield_Part_Half_Circle': { - 'hash': 50888, - 'name': 'Shield Part Half Circle', - 'embedded': { - 'Insert_Shield_Part_112': { - 'hash': 112, - 'name': 'Insert Shield Part', - 'savables': {} - }, - 'Shield_Part_Half_Circle_50886': { - 'hash': 50886, - 'name': 'Shield Part Half Circle', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Slot_Deco_25868': { - 'hash': 25868, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_25870': { - 'hash': 25870, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_51506': { - 'hash': 51506, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_51508': { - 'hash': 51508, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_52564': { - 'hash': 52564, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_52566': { - 'hash': 52566, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_53718': { - 'hash': 53718, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_53720': { - 'hash': 53720, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_55242': { - 'hash': 55242, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_55244': { - 'hash': 55244, - 'name': 'Slot Deco', - 'savables': {} - } - } - }, - 'Shield_Part_Half_Circle_Hole': { - 'hash': 44704, - 'name': 'Shield Part Half Circle Hole', - 'embedded': { - 'Insert_Shield_Part_112': { - 'hash': 112, - 'name': 'Insert Shield Part', - 'savables': {} - }, - 'Shield_Part_Half_Circle_Hole_44702': { - 'hash': 44702, - 'name': 'Shield Part Half Circle Hole', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Slot_Deco_25868': { - 'hash': 25868, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_25870': { - 'hash': 25870, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_51506': { - 'hash': 51506, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_51508': { - 'hash': 51508, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_52564': { - 'hash': 52564, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_52566': { - 'hash': 52566, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_55242': { - 'hash': 55242, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_55244': { - 'hash': 55244, - 'name': 'Slot Deco', - 'savables': {} - } - } - }, - 'Shield_Part_Half_Hole': { - 'hash': 12416, - 'name': 'Shield Part Half Hole', - 'embedded': { - 'Insert_Shield_Part_112': { - 'hash': 112, - 'name': 'Insert Shield Part', - 'savables': {} - }, - 'Shield_Part_Half_Hole_12414': { - 'hash': 12414, - 'name': 'Shield Part Half Hole', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Slot_Deco_20018': { - 'hash': 20018, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_46580': { - 'hash': 46580, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_52138': { - 'hash': 52138, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_56752': { - 'hash': 56752, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_63256': { - 'hash': 63256, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_854': { - 'hash': 854, - 'name': 'Slot Deco', - 'savables': {} - } - } - }, - 'Shield_Part_Half_Point_01': { - 'hash': 59936, - 'name': 'Shield Part Half Point 01', - 'embedded': { - 'Insert_Shield_Part_112': { - 'hash': 112, - 'name': 'Insert Shield Part', - 'savables': {} - }, - 'Shield_Part_Half_Point_01_56662': { - 'hash': 56662, - 'name': 'Shield Part Half Point 01', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Slot_Deco_20420': { - 'hash': 20420, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_26340': { - 'hash': 26340, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_26366': { - 'hash': 26366, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_26368': { - 'hash': 26368, - 'name': 'Slot Deco', - 'savables': {} - }, - 'Slot_Deco_26396': { - 'hash': 26396, - 'name': 'Slot Deco', - 'savables': {} - } - } - }, - 'Short_Sword': { - 'hash': 38566, - 'name': 'Short Sword', - 'embedded': { - 'Short_Sword_36330': { - 'hash': 36330, - 'name': 'Short Sword', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Short_Sword_Blade': { - 'hash': 55310, - 'name': 'Short Sword Blade', - 'embedded': { - 'Heat_Point_Collection_63534': { - 'hash': 63534, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_Straight_SwordType_7796': { - 'hash': 7796, - 'name': 'Insert Straight SwordType', - 'savables': {} - }, - 'Short_Sword_Blade_36330': { - 'hash': 36330, - 'name': 'Short Sword Blade', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'metal_blade_shortSword_full_geo_LOD0_4044': { - 'hash': 4044, - 'name': 'metal_blade_shortSword_full_geo_LOD0', - 'savables': {} - } - } - }, - 'Short_Sword_Training': { - 'hash': 1150, - 'name': 'Short Sword Training', - 'embedded': { - 'Short_Sword_Training_1152': { - 'hash': 1152, - 'name': 'Short Sword Training', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Shotel_Blade': { - 'hash': 36438, - 'name': 'Shotel Blade', - 'embedded': { - 'Heat_Point_Collection_2136': { - 'hash': 2136, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_SwordType_7796': { - 'hash': 7796, - 'name': 'Insert SwordType', - 'savables': {} - }, - 'Shotel_Blade_36346': { - 'hash': 36346, - 'name': 'Shotel Blade', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'metal_blade_shotel_full_geo_LOD0_22394': { - 'hash': 22394, - 'name': 'metal_blade_shotel_full_geo_LOD0', - 'savables': {} - } - } - }, - 'Silver_Boulder': { - 'hash': 9144, - 'name': 'Silver Boulder', - 'embedded': { - 'Silver_Boulder_11186': { - 'hash': 11186, - 'name': 'Silver Boulder', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Spawn_Origin_50402': { - 'hash': 50402, - 'name': 'Spawn Origin', - 'savables': {} - } - } - }, - 'Silver_Boulder_Parts': { - 'hash': 17120, - 'name': 'Silver_Boulder_Parts', - 'embedded': { - 'Silver_Boulder_Parts_56732': { - 'hash': 56732, - 'name': 'Silver_Boulder_Parts', - 'savables': {} - }, - 'Silver_Boulder_part_01_56744': { - 'hash': 56744, - 'name': 'Silver_Boulder_part_01', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Silver_Boulder_part_02_56752': { - 'hash': 56752, - 'name': 'Silver_Boulder_part_02', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Silver_Boulder_part_03_56748': { - 'hash': 56748, - 'name': 'Silver_Boulder_part_03', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Silver_Ingot': { - 'hash': 23528, - 'name': 'Silver Ingot', - 'embedded': { - 'Heat_Point_Collection_13678': { - 'hash': 13678, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Silver_Ingot_23416': { - 'hash': 23416, - 'name': 'Silver Ingot', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Silver_Ore': { - 'hash': 9586, - 'name': 'Silver Ore', - 'embedded': { - 'Silver_Ore_28602': { - 'hash': 28602, - 'name': 'Silver Ore', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Skill_Orb': { - 'hash': 17270, - 'name': 'Skill Orb', - 'embedded': { - 'Skill_Orb_35828': { - 'hash': 35828, - 'name': 'Skill Orb', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Skill_Orb_Replacer': { - 'hash': 23526, - 'name': 'Skill Orb Replacer', - 'embedded': { - 'Skill_Orb_Replacer_35828': { - 'hash': 35828, - 'name': 'Skill Orb Replacer', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'SlidingBlockTestLayoutINCOMPLETE': { - 'hash': 8280, - 'name': 'SlidingBlockTestLayoutINCOMPLETE', - 'embedded': {} - }, - 'Sliding_Door': { - 'hash': 33420, - 'name': 'Sliding_Door', - 'embedded': {} - }, - 'Slingshot': { - 'hash': 13142, - 'name': 'Slingshot', - 'embedded': { - 'Projectile_Dock_40686': { - 'hash': 40686, - 'name': 'Projectile Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Slingshot_15402': { - 'hash': 15402, - 'name': 'Slingshot', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'String_40688': { - 'hash': 40688, - 'name': 'String', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Slow_Grass': { - 'hash': 59062, - 'name': 'Slow Grass', - 'embedded': { - 'Slow_Grass_7970': { - 'hash': 7970, - 'name': 'Slow Grass', - 'savables': {} - } - } - }, - 'Small_Bone_Spike': { - 'hash': 61488, - 'name': 'Small Bone Spike', - 'embedded': { - 'Insert_Deco_112': { - 'hash': 112, - 'name': 'Insert Deco', - 'savables': {} - }, - 'Small_Bone_Spike_15532': { - 'hash': 15532, - 'name': 'Small Bone Spike', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Small_Cave_Mushroom_01': { - 'hash': 33796, - 'name': 'Small Cave Mushroom 01', - 'embedded': { - 'Small_Cave_Mushroom_01_33544': { - 'hash': 33544, - 'name': 'Small Cave Mushroom 01', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Spawner_3488': { - 'hash': 3488, - 'name': 'Spawner', - 'savables': {} - }, - 'cave_mushroom_small_spineTop_jnt_38718': { - 'hash': 38718, - 'name': 'cave_mushroom_small_spineTop_jnt', - 'savables': {} - }, - 'cave_mushroom_small_spine_jnt_46098': { - 'hash': 46098, - 'name': 'cave_mushroom_small_spine_jnt', - 'savables': {} - } - } - }, - 'Small_Cave_Mushroom_Cluster': { - 'hash': 56444, - 'name': 'Small Cave Mushroom Cluster', - 'embedded': { - 'Small_Cave_Mushroom_Cluster_61380': { - 'hash': 61380, - 'name': 'Small Cave Mushroom Cluster', - 'savables': {} - } - } - }, - 'Small_Shield': { - 'hash': 63498, - 'name': 'Small Shield', - 'embedded': { - 'Insert_Shield_64244': { - 'hash': 64244, - 'name': 'Insert Shield', - 'savables': {} - }, - 'Small_Shield_32452': { - 'hash': 32452, - 'name': 'Small Shield', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Small_Shield_Training': { - 'hash': 21312, - 'name': 'Small Shield Training', - 'embedded': { - 'Small_Shield_Training_21302': { - 'hash': 21302, - 'name': 'Small Shield Training', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Smelter': { - 'hash': 44646, - 'name': 'Smelter', - 'embedded': { - 'Dock_37092': { - 'hash': 37092, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_37150': { - 'hash': 37150, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_37236': { - 'hash': 37236, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_Fuel_54958': { - 'hash': 54958, - 'name': 'Dock Fuel', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_Ore_(B)_42990': { - 'hash': 42990, - 'name': 'Dock Ore (B)', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_Ore_(T)_54962': { - 'hash': 54962, - 'name': 'Dock Ore (T)', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_Ore_Dispenser_L_54940': { - 'hash': 54940, - 'name': 'Dock Ore Dispenser L', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_Ore_Dispenser_M_54938': { - 'hash': 54938, - 'name': 'Dock Ore Dispenser M', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_Ore_Dispenser_R_54936': { - 'hash': 54936, - 'name': 'Dock Ore Dispenser R', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_Output_54928': { - 'hash': 54928, - 'name': 'Dock Output', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_Output_54930': { - 'hash': 54930, - 'name': 'Dock Output', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Fire_54948': { - 'hash': 54948, - 'name': 'Fire', - 'savables': { - 'Fire': { - 'hash': 3457519710, - 'name': 'Fire' - } - } - }, - 'Handle_24422': { - 'hash': 24422, - 'name': 'Handle', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Handle_38408': { - 'hash': 38408, - 'name': 'Handle', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Handle_5088': { - 'hash': 5088, - 'name': 'Handle', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Mould_Dock_54960': { - 'hash': 54960, - 'name': 'Mould Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Smelter_19322': { - 'hash': 19322, - 'name': 'Smelter', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - }, - 'Smelter': { - 'hash': 902024186, - 'name': 'Smelter' - } - } - }, - 'UnlockDocks_10172': { - 'hash': 10172, - 'name': 'UnlockDocks', - 'savables': { - 'PositionRestrictor': { - 'hash': 1776498660, - 'name': 'PositionRestrictor' - } - } - }, - 'smelter_bellows_arm_jnt_25672': { - 'hash': 25672, - 'name': 'smelter_bellows_arm_jnt', - 'savables': {} - }, - 'smelter_dispenser_lever_Handle_5912': { - 'hash': 5912, - 'name': 'smelter_dispenser_lever_Handle', - 'savables': { - 'Lever': { - 'hash': 1594932294, - 'name': 'Lever' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'smelter_fuelGate_handle_59832': { - 'hash': 59832, - 'name': 'smelter_fuelGate_handle', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'smelter_fuelGate_pivot_10060': { - 'hash': 10060, - 'name': 'smelter_fuelGate_pivot', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Smelter_Gem_1': { - 'hash': 34986, - 'name': 'Smelter Gem 1', - 'embedded': { - 'Smelter_Gem_1_11514': { - 'hash': 11514, - 'name': 'Smelter Gem 1', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Smelter_Gem_2': { - 'hash': 41638, - 'name': 'Smelter Gem 2', - 'embedded': { - 'Smelter_Gem_2_11514': { - 'hash': 11514, - 'name': 'Smelter Gem 2', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Smelter_Gem_3': { - 'hash': 46508, - 'name': 'Smelter Gem 3', - 'embedded': { - 'Smelter_Gem_3_11514': { - 'hash': 11514, - 'name': 'Smelter Gem 3', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Smelter_gem_2_item_pedestal': { - 'hash': 56098, - 'name': 'Smelter gem 2 item pedestal', - 'embedded': { - 'Pedestal_Dock_27002': { - 'hash': 27002, - 'name': 'Pedestal Dock', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'PickupDockPedestalSpawn': { - 'hash': 2592242915, - 'name': 'PickupDockPedestalSpawn' - } - } - }, - 'Smelter_gem_2_item_pedestal_27194': { - 'hash': 27194, - 'name': 'Smelter gem 2 item pedestal', - 'savables': {} - } - } - }, - 'Smelter_gem_3_item_pedestal': { - 'hash': 63036, - 'name': 'Smelter gem 3 item pedestal', - 'embedded': { - 'Pedestal_Dock_27002': { - 'hash': 27002, - 'name': 'Pedestal Dock', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'PickupDockPedestalSpawn': { - 'hash': 2592242915, - 'name': 'PickupDockPedestalSpawn' - } - } - }, - 'Smelter_gem_3_item_pedestal_27194': { - 'hash': 27194, - 'name': 'Smelter gem 3 item pedestal', - 'savables': {} - } - } - }, - 'SnowballMoundSpawner': { - 'hash': 30542, - 'name': 'SnowballMoundSpawner', - 'embedded': { - 'SnowballMoundSpawner_24412': { - 'hash': 24412, - 'name': 'SnowballMoundSpawner', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'SnowballSpawner': { - 'hash': 22418, - 'name': 'SnowballSpawner', - 'embedded': { - 'SnowballSpawner_52610': { - 'hash': 52610, - 'name': 'SnowballSpawner', - 'savables': {} - }, - 'Spawner_528': { - 'hash': 528, - 'name': 'Spawner', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'SpawnInCircle': { - 'hash': 1714180166, - 'name': 'SpawnInCircle' - } - } - } - } - }, - 'Snowball_network_Prefab': { - 'hash': 52090, - 'name': 'Snowball network Prefab', - 'embedded': { - 'Snowball_network_Prefab_36924': { - 'hash': 36924, - 'name': 'Snowball network Prefab', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Snowman_Network_Prefab_1': { - 'hash': 57830, - 'name': 'Snowman Network Prefab 1', - 'embedded': { - 'Dock_2780': { - 'hash': 2780, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Snowman_Network_Prefab_1_25600': { - 'hash': 25600, - 'name': 'Snowman Network Prefab 1', - 'savables': {} - } - } - }, - 'Snowman_Network_Prefab_2': { - 'hash': 16878, - 'name': 'Snowman Network Prefab 2', - 'embedded': { - 'Dock_2780': { - 'hash': 2780, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Snowman_Network_Prefab_2_25600': { - 'hash': 25600, - 'name': 'Snowman Network Prefab 2', - 'savables': {} - } - } - }, - 'Snowman_Network_Prefab_3': { - 'hash': 17612, - 'name': 'Snowman Network Prefab 3', - 'embedded': { - 'Dock_2780': { - 'hash': 2780, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Snowman_Network_Prefab_3_25600': { - 'hash': 25600, - 'name': 'Snowman Network Prefab 3', - 'savables': {} - } - } - }, - 'Snowman_Network_Prefab_test': { - 'hash': 25690, - 'name': 'Snowman Network Prefab test', - 'embedded': { - 'Dock_2780': { - 'hash': 2780, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Snowman_Network_Prefab_test_25600': { - 'hash': 25600, - 'name': 'Snowman Network Prefab test', - 'savables': {} - } - } - }, - 'Soft_Fabric_Large_Roll': { - 'hash': 23206, - 'name': 'Soft Fabric Large Roll', - 'embedded': { - 'Soft_Fabric_Large_Roll_47776': { - 'hash': 47776, - 'name': 'Soft Fabric Large Roll', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Spawner_43650': { - 'hash': 43650, - 'name': 'Spawner', - 'savables': {} - } - } - }, - 'Soft_Fabric_Medium_Roll': { - 'hash': 47760, - 'name': 'Soft Fabric Medium Roll', - 'embedded': { - 'Soft_Fabric_Medium_Roll_47776': { - 'hash': 47776, - 'name': 'Soft Fabric Medium Roll', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Spawner_43650': { - 'hash': 43650, - 'name': 'Spawner', - 'savables': {} - } - } - }, - 'Soft_Fabric_Medium_Strips': { - 'hash': 63204, - 'name': 'Soft Fabric Medium Strips', - 'embedded': { - 'Soft_Fabric_Medium_Strips_63188': { - 'hash': 63188, - 'name': 'Soft Fabric Medium Strips', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Spade_Head': { - 'hash': 50548, - 'name': 'Spade Head', - 'embedded': { - 'Fake_Pickup_6096': { - 'hash': 6096, - 'name': 'Fake Pickup', - 'savables': {} - }, - 'Insert_AxeType_7796': { - 'hash': 7796, - 'name': 'Insert AxeType', - 'savables': {} - }, - 'Spade_Head_60654': { - 'hash': 60654, - 'name': 'Spade Head', - 'savables': { - 'DiggingImpactor': { - 'hash': 3445325106, - 'name': 'DiggingImpactor' - }, - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'spade_head_LOD0_45520': { - 'hash': 45520, - 'name': 'spade_head_LOD0', - 'savables': {} - } - } - }, - 'Spawn_Point': { - 'hash': 63844, - 'name': 'Spawn Point', - 'embedded': { - 'Spawn_Point_4036': { - 'hash': 4036, - 'name': 'Spawn Point', - 'savables': {} - } - } - }, - 'Spawner_Test': { - 'hash': 51070, - 'name': 'Spawner_Test', - 'embedded': {} - }, - 'Spear_Head_Pyramid': { - 'hash': 13554, - 'name': 'Spear_Head_Pyramid', - 'embedded': {} - }, - 'Spear_Head_Spiky': { - 'hash': 13680, - 'name': 'Spear_Head_Spiky', - 'embedded': {} - }, - 'Spear_Head_Standard': { - 'hash': 13816, - 'name': 'Spear_Head_Standard', - 'embedded': {} - }, - 'Spectral_Ghost': { - 'hash': 57494, - 'name': 'Spectral_Ghost', - 'embedded': {} - }, - 'Spherical_Encounter': { - 'hash': 1222, - 'name': 'Spherical_Encounter', - 'embedded': {} - }, - 'Spike_Fancy': { - 'hash': 12492, - 'name': 'Spike Fancy', - 'embedded': { - 'Heat_Point_Collection_3584': { - 'hash': 3584, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_Deco_112': { - 'hash': 112, - 'name': 'Insert Deco', - 'savables': {} - }, - 'Spike_Fancy_15532': { - 'hash': 15532, - 'name': 'Spike Fancy', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Spike_Short': { - 'hash': 6934, - 'name': 'Spike Short', - 'embedded': { - 'Insert_Deco_112': { - 'hash': 112, - 'name': 'Insert Deco', - 'savables': {} - }, - 'Spike_Short_15532': { - 'hash': 15532, - 'name': 'Spike Short', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Spike_Tall': { - 'hash': 3558, - 'name': 'Spike Tall', - 'embedded': { - 'Insert_Deco_112': { - 'hash': 112, - 'name': 'Insert Deco', - 'savables': {} - }, - 'Spike_Tall_15532': { - 'hash': 15532, - 'name': 'Spike Tall', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Spire_Gcore_Dynamic': { - 'hash': 23472, - 'name': 'Spire Gcore Dynamic', - 'embedded': { - 'Directional_Encounter_33516': { - 'hash': 33516, - 'name': 'Directional Encounter', - 'savables': { - 'DirectionalBoundsSurface': { - 'hash': 1962842866, - 'name': 'DirectionalBoundsSurface' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - }, - 'Spire_Gcore_Dynamic_23456': { - 'hash': 23456, - 'name': 'Spire Gcore Dynamic', - 'savables': {} - } - } - }, - 'Spread_Spawner_Dynamic': { - 'hash': 18426, - 'name': 'Spread Spawner Dynamic', - 'embedded': { - 'Directional_Encounter_(1)_45120': { - 'hash': 45120, - 'name': 'Directional Encounter (1)', - 'savables': { - 'DirectionalBoundsSurface': { - 'hash': 1962842866, - 'name': 'DirectionalBoundsSurface' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - }, - 'Directional_Encounter_45108': { - 'hash': 45108, - 'name': 'Directional Encounter', - 'savables': { - 'DirectionalBoundsSurface': { - 'hash': 1962842866, - 'name': 'DirectionalBoundsSurface' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - }, - 'Spread_Spawner_Dynamic_18410': { - 'hash': 18410, - 'name': 'Spread Spawner Dynamic', - 'savables': {} - } - } - }, - 'Spriggull': { - 'hash': 62050, - 'name': 'Spriggull', - 'embedded': { - 'Body_60576': { - 'hash': 60576, - 'name': 'Body', - 'savables': {} - }, - 'Heat_42194': { - 'hash': 42194, - 'name': 'Heat', - 'savables': { - 'Fire': { - 'hash': 3457519710, - 'name': 'Fire' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Interactor_2642': { - 'hash': 2642, - 'name': 'Interactor', - 'savables': {} - }, - 'Spriggull_62666': { - 'hash': 62666, - 'name': 'Spriggull', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Spriggull_AI_58356': { - 'hash': 58356, - 'name': 'Spriggull AI', - 'savables': {} - }, - 'skin_jaw_jnt_48650': { - 'hash': 48650, - 'name': 'skin_jaw_jnt', - 'savables': {} - } - } - }, - 'SpriggullDrumstick_Bone': { - 'hash': 24406, - 'name': 'SpriggullDrumstick Bone', - 'embedded': { - 'SpriggullDrumstick_Bone_26390': { - 'hash': 26390, - 'name': 'SpriggullDrumstick Bone', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'SpriggullDrumstick_Full_Burnt': { - 'hash': 20570, - 'name': 'SpriggullDrumstick Full Burnt', - 'embedded': { - 'Bone_Spawner_16064': { - 'hash': 16064, - 'name': 'Bone Spawner', - 'savables': {} - }, - 'Cooking_35958': { - 'hash': 35958, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'SpriggullDrumstick_Full_Burnt_36708': { - 'hash': 36708, - 'name': 'SpriggullDrumstick Full Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'SpriggullDrumstick_Full_Cooked': { - 'hash': 33190, - 'name': 'SpriggullDrumstick Full Cooked', - 'embedded': { - 'Bone_Spawner_16556': { - 'hash': 16556, - 'name': 'Bone Spawner', - 'savables': {} - }, - 'Cooking_29822': { - 'hash': 29822, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'SpriggullDrumstick_Full_Cooked_30572': { - 'hash': 30572, - 'name': 'SpriggullDrumstick Full Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'SpriggullDrumstick_Full_Ripe': { - 'hash': 43430, - 'name': 'SpriggullDrumstick Full Ripe', - 'embedded': { - 'Bone_Spawner_38786': { - 'hash': 38786, - 'name': 'Bone Spawner', - 'savables': {} - }, - 'Cooking_24500': { - 'hash': 24500, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'SpriggullDrumstick_Full_Ripe_25250': { - 'hash': 25250, - 'name': 'SpriggullDrumstick Full Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'SpriggullDrumstick_Half_Burnt': { - 'hash': 10908, - 'name': 'SpriggullDrumstick Half Burnt', - 'embedded': { - 'Cooking_19872': { - 'hash': 19872, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'SpriggullDrumstick_Half_Burnt_19928': { - 'hash': 19928, - 'name': 'SpriggullDrumstick Half Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'SpriggullDrumstick_Half_Cooked': { - 'hash': 8440, - 'name': 'SpriggullDrumstick Half Cooked', - 'embedded': { - 'Cooking_18026': { - 'hash': 18026, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'SpriggullDrumstick_Half_Cooked_18082': { - 'hash': 18082, - 'name': 'SpriggullDrumstick Half Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'SpriggullDrumstick_Half_Ripe': { - 'hash': 5972, - 'name': 'SpriggullDrumstick Half Ripe', - 'embedded': { - 'Cooking_16182': { - 'hash': 16182, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'SpriggullDrumstick_Half_Ripe_16238': { - 'hash': 16238, - 'name': 'SpriggullDrumstick Half Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Spriggull_Egg': { - 'hash': 7014, - 'name': 'Spriggull Egg', - 'embedded': { - 'Spriggull_Egg_5216': { - 'hash': 5216, - 'name': 'Spriggull Egg', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Spriggull_Feather_Blue': { - 'hash': 7918, - 'name': 'Spriggull Feather Blue', - 'embedded': { - 'Spriggull_Feather_Blue_61684': { - 'hash': 61684, - 'name': 'Spriggull Feather Blue', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Spriggull_Feather_Green': { - 'hash': 25446, - 'name': 'Spriggull Feather Green', - 'embedded': { - 'Insert_Feather_112': { - 'hash': 112, - 'name': 'Insert Feather', - 'savables': {} - }, - 'Spriggull_Feather_Green_25450': { - 'hash': 25450, - 'name': 'Spriggull Feather Green', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Spriggull_Feather_Purple': { - 'hash': 36248, - 'name': 'Spriggull Feather Purple', - 'embedded': { - 'Insert_Feather_112': { - 'hash': 112, - 'name': 'Insert Feather', - 'savables': {} - }, - 'Spriggull_Feather_Purple_36244': { - 'hash': 36244, - 'name': 'Spriggull Feather Purple', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Spriggull_Feather_Red': { - 'hash': 18734, - 'name': 'Spriggull Feather Red', - 'embedded': { - 'Spriggull_Feather_Red_18738': { - 'hash': 18738, - 'name': 'Spriggull Feather Red', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Spriggull_Fletching_Blue': { - 'hash': 50608, - 'name': 'Spriggull Fletching Blue', - 'embedded': { - 'Insert_Feather_51282': { - 'hash': 51282, - 'name': 'Insert Feather', - 'savables': {} - }, - 'Spriggull_Fletching_Blue_51284': { - 'hash': 51284, - 'name': 'Spriggull Fletching Blue', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Spriggull_Fletching_Red': { - 'hash': 24072, - 'name': 'Spriggull Fletching Red', - 'embedded': { - 'Insert_Feather_112': { - 'hash': 112, - 'name': 'Insert Feather', - 'savables': {} - }, - 'Spriggull_Fletching_Red_18738': { - 'hash': 18738, - 'name': 'Spriggull Fletching Red', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Spriggull_Nest': { - 'hash': 16680, - 'name': 'Spriggull Nest', - 'embedded': { - 'Spriggull_Nest_16166': { - 'hash': 16166, - 'name': 'Spriggull Nest', - 'savables': {} - } - } - }, - 'SpyGlass': { - 'hash': 5170, - 'name': 'SpyGlass', - 'embedded': { - 'SpyGlass_7714': { - 'hash': 7714, - 'name': 'SpyGlass', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'spyglass_body_01_57858': { - 'hash': 57858, - 'name': 'spyglass_body_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'spyglass_body_02_57854': { - 'hash': 57854, - 'name': 'spyglass_body_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'spyglass_wraps_57850': { - 'hash': 57850, - 'name': 'spyglass_wraps', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'SpyGlass_Long': { - 'hash': 64848, - 'name': 'SpyGlass Long', - 'embedded': { - 'SpyGlass_Long_7714': { - 'hash': 7714, - 'name': 'SpyGlass Long', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Stalactite_pillar': { - 'hash': 3944, - 'name': 'Stalactite pillar', - 'embedded': { - 'Explosion_17130': { - 'hash': 17130, - 'name': 'Explosion', - 'savables': {} - }, - 'Explosion_17244': { - 'hash': 17244, - 'name': 'Explosion', - 'savables': {} - }, - 'Explosion_17358': { - 'hash': 17358, - 'name': 'Explosion', - 'savables': {} - }, - 'Explosion_17472': { - 'hash': 17472, - 'name': 'Explosion', - 'savables': {} - }, - 'Explosion_17586': { - 'hash': 17586, - 'name': 'Explosion', - 'savables': {} - }, - 'Explosion_17700': { - 'hash': 17700, - 'name': 'Explosion', - 'savables': {} - }, - 'Explosion_21698': { - 'hash': 21698, - 'name': 'Explosion', - 'savables': {} - }, - 'Explosive_Spike_Stalactite(NoNetworkPrefab)_17234': { - 'hash': 17234, - 'name': 'Explosive Spike Stalactite(NoNetworkPrefab)', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Explosive_Spike_Stalactite(NoNetworkPrefab)_17348': { - 'hash': 17348, - 'name': 'Explosive Spike Stalactite(NoNetworkPrefab)', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Explosive_Spike_Stalactite(NoNetworkPrefab)_17462': { - 'hash': 17462, - 'name': 'Explosive Spike Stalactite(NoNetworkPrefab)', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Explosive_Spike_Stalactite(NoNetworkPrefab)_17576': { - 'hash': 17576, - 'name': 'Explosive Spike Stalactite(NoNetworkPrefab)', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Explosive_Spike_Stalactite(NoNetworkPrefab)_17690': { - 'hash': 17690, - 'name': 'Explosive Spike Stalactite(NoNetworkPrefab)', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Explosive_Spike_Stalactite(NoNetworkPrefab)_17804': { - 'hash': 17804, - 'name': 'Explosive Spike Stalactite(NoNetworkPrefab)', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Explosive_Spike_Stalactite(NoNetworkPrefab)_21742': { - 'hash': 21742, - 'name': 'Explosive Spike Stalactite(NoNetworkPrefab)', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'Hit_Detection_44554': { - 'hash': 44554, - 'name': 'Hit Detection', - 'savables': { - 'ImpactDetectionLogic': { - 'hash': 1435171891, - 'name': 'ImpactDetectionLogic' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Stalactite_pillar_50810': { - 'hash': 50810, - 'name': 'Stalactite pillar', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - } - } - } - } - }, - 'Standard_Crafted_Mould': { - 'hash': 38578, - 'name': 'Standard Crafted Mould', - 'embedded': { - 'Flat_Mould_Emblem_9986': { - 'hash': 9986, - 'name': 'Flat Mould Emblem', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'Standard_Crafted_Mould_14710': { - 'hash': 14710, - 'name': 'Standard Crafted Mould', - 'savables': { - 'Mould': { - 'hash': 391977879, - 'name': 'Mould' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'mould_standard_ingotGraphic_60818': { - 'hash': 60818, - 'name': 'mould_standard_ingotGraphic', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'mould_standard_outerFrame_01_60826': { - 'hash': 60826, - 'name': 'mould_standard_outerFrame_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'mould_standard_railSlot_01_60830': { - 'hash': 60830, - 'name': 'mould_standard_railSlot_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'mould_standard_railSlot_02_60814': { - 'hash': 60814, - 'name': 'mould_standard_railSlot_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'mould_standard_railSlot_03_60822': { - 'hash': 60822, - 'name': 'mould_standard_railSlot_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'mould_standard_railSlot_04_60806': { - 'hash': 60806, - 'name': 'mould_standard_railSlot_04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'mould_standard_timesGraphic_60810': { - 'hash': 60810, - 'name': 'mould_standard_timesGraphic', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Standard_Side_Pouch_Attachment': { - 'hash': 7852, - 'name': 'Standard Side Pouch Attachment', - 'embedded': { - 'Dock_45700': { - 'hash': 45700, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62078': { - 'hash': 62078, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Insert_Bag_Attach_7796': { - 'hash': 7796, - 'name': 'Insert Bag Attach', - 'savables': {} - }, - 'Standard_Side_Pouch_Attachment_7868': { - 'hash': 7868, - 'name': 'Standard Side Pouch Attachment', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Storage_52822': { - 'hash': 52822, - 'name': 'Storage', - 'savables': {} - }, - 'standard_sidePouch_backPin_L1_7968': { - 'hash': 7968, - 'name': 'standard_sidePouch_backPin_L1', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_sidePouch_body_7972': { - 'hash': 7972, - 'name': 'standard_sidePouch_body', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_sidePouch_body_flap_7980': { - 'hash': 7980, - 'name': 'standard_sidePouch_body_flap', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_sidePouch_flap_7976': { - 'hash': 7976, - 'name': 'standard_sidePouch_flap', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Standard_Side_Tool_Attachment': { - 'hash': 59468, - 'name': 'Standard Side Tool Attachment', - 'embedded': { - 'Dock_62078': { - 'hash': 62078, - 'name': 'Dock', - 'savables': { - 'AdditionalOwnedDock': { - 'hash': 2592242915, - 'name': 'AdditionalOwnedDock' - } - } - }, - 'Insert_Bag_Attach_7796': { - 'hash': 7796, - 'name': 'Insert Bag Attach', - 'savables': {} - }, - 'Standard_Side_Tool_Attachment_7868': { - 'hash': 7868, - 'name': 'Standard Side Tool Attachment', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Storage_52526': { - 'hash': 52526, - 'name': 'Storage', - 'savables': {} - }, - 'standard_sideTool_slot_loop_33788': { - 'hash': 33788, - 'name': 'standard_sideTool_slot_loop', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_sideTool_slot_pad_01_33784': { - 'hash': 33784, - 'name': 'standard_sideTool_slot_pad_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_sideTool_slot_pad_02_33780': { - 'hash': 33780, - 'name': 'standard_sideTool_slot_pad_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'standard_sideTool_slot_strap_01_33776': { - 'hash': 33776, - 'name': 'standard_sideTool_slot_strap_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Standard_Stages': { - 'hash': 31152, - 'name': 'Standard Stages', - 'embedded': { - 'Standard_Stages_53224': { - 'hash': 53224, - 'name': 'Standard Stages', - 'savables': { - 'StageBasedPrefab': { - 'hash': 1390862571, - 'name': 'StageBasedPrefab' - } - } - } - } - }, - 'Steam_Spray': { - 'hash': 53376, - 'name': 'Steam Spray', - 'embedded': { - 'Hurting_Bit_26178': { - 'hash': 26178, - 'name': 'Hurting Bit', - 'savables': {} - }, - 'Start_event_44764': { - 'hash': 44764, - 'name': 'Start event', - 'savables': {} - }, - 'Steam_Spray_61896': { - 'hash': 61896, - 'name': 'Steam Spray', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - } - } - }, - 'Stop_event_45050': { - 'hash': 45050, - 'name': 'Stop event', - 'savables': {} - } - } - }, - 'Steel_Alloy_Ingot': { - 'hash': 22222, - 'name': 'Steel_Alloy_Ingot', - 'embedded': {} - }, - 'Stick': { - 'hash': 61674, - 'name': 'Stick', - 'embedded': { - 'Slot_Multi_64914': { - 'hash': 64914, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Slot_Primitive_SwordType_30294': { - 'hash': 30294, - 'name': 'Slot Primitive SwordType', - 'savables': {} - }, - 'Stick_31654': { - 'hash': 31654, - 'name': 'Stick', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Stick_Charred': { - 'hash': 20564, - 'name': 'Stick Charred', - 'embedded': { - 'Stick_Charred_31654': { - 'hash': 31654, - 'name': 'Stick Charred', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Stick_Storage': { - 'hash': 46252, - 'name': 'Stick Storage', - 'embedded': { - 'Filter_Dock_57214': { - 'hash': 57214, - 'name': 'Filter Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Interaction_Point_59032': { - 'hash': 59032, - 'name': 'Interaction Point', - 'savables': {} - }, - 'Internal_Dock_59328': { - 'hash': 59328, - 'name': 'Internal Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Stick_Storage_59042': { - 'hash': 59042, - 'name': 'Stick Storage', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - }, - 'CommunalStorage': { - 'hash': 3084373371, - 'name': 'CommunalStorage' - }, - 'PlayerInteractionRestrictor': { - 'hash': 2951515968, - 'name': 'PlayerInteractionRestrictor' - } - } - }, - 'Withdraw_Dock_34750': { - 'hash': 34750, - 'name': 'Withdraw Dock', - 'savables': {} - } - } - }, - 'Stick_Training': { - 'hash': 61414, - 'name': 'Stick Training', - 'embedded': { - 'Stick_Training_61396': { - 'hash': 61396, - 'name': 'Stick Training', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Stone': { - 'hash': 61670, - 'name': 'Stone', - 'embedded': { - 'Insert_Primitive_SwordType_7796': { - 'hash': 7796, - 'name': 'Insert Primitive SwordType', - 'savables': {} - }, - 'Stone_30920': { - 'hash': 30920, - 'name': 'Stone', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Stone_Boulder_01': { - 'hash': 33376, - 'name': 'Stone Boulder 01', - 'embedded': { - 'Stone_Boulder_01_33370': { - 'hash': 33370, - 'name': 'Stone Boulder 01', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Stone_Boulder_02': { - 'hash': 17686, - 'name': 'Stone Boulder 02', - 'embedded': { - 'Stone_Boulder_02_17680': { - 'hash': 17680, - 'name': 'Stone Boulder 02', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Stone_Boulder_03': { - 'hash': 12450, - 'name': 'Stone Boulder 03', - 'embedded': { - 'Stone_Boulder_03_12444': { - 'hash': 12444, - 'name': 'Stone Boulder 03', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Stone_Boulder_Cluster': { - 'hash': 8948, - 'name': 'Stone Boulder Cluster', - 'embedded': { - 'Stone_Boulder_Cluster_8942': { - 'hash': 8942, - 'name': 'Stone Boulder Cluster', - 'savables': {} - } - } - }, - 'Stone_Training': { - 'hash': 19490, - 'name': 'Stone Training', - 'embedded': { - 'Stone_Training_19480': { - 'hash': 19480, - 'name': 'Stone Training', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Storage_Chest': { - 'hash': 63826, - 'name': 'Storage Chest', - 'embedded': { - 'Bottom_Dock_1_2780': { - 'hash': 2780, - 'name': 'Bottom Dock 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_2_2778': { - 'hash': 2778, - 'name': 'Bottom Dock 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_3_2776': { - 'hash': 2776, - 'name': 'Bottom Dock 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_4_2770': { - 'hash': 2770, - 'name': 'Bottom Dock 4', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_5_2772': { - 'hash': 2772, - 'name': 'Bottom Dock 5', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_6_2774': { - 'hash': 2774, - 'name': 'Bottom Dock 6', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Handle_Left_23970': { - 'hash': 23970, - 'name': 'Handle Left', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Handle_Right_23964': { - 'hash': 23964, - 'name': 'Handle Right', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Lid_2768': { - 'hash': 2768, - 'name': 'Lid', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Storage_Chest_2788': { - 'hash': 2788, - 'name': 'Storage Chest', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - }, - 'Chest': { - 'hash': 3598052397, - 'name': 'Chest' - } - } - }, - 'Top_Dock_1_2766': { - 'hash': 2766, - 'name': 'Top Dock 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_2_2764': { - 'hash': 2764, - 'name': 'Top Dock 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_3_2762': { - 'hash': 2762, - 'name': 'Top Dock 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_4_2756': { - 'hash': 2756, - 'name': 'Top Dock 4', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_5_2758': { - 'hash': 2758, - 'name': 'Top Dock 5', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_6_2760': { - 'hash': 2760, - 'name': 'Top Dock 6', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - } - } - }, - 'Storage_Crate_Parts': { - 'hash': 16574, - 'name': 'Storage Crate Parts', - 'embedded': { - 'Storage_Crate_Parts_23406': { - 'hash': 23406, - 'name': 'Storage Crate Parts', - 'savables': {} - } - } - }, - 'Storage_Crate_Redwood_Closed': { - 'hash': 59594, - 'name': 'Storage Crate Redwood Closed', - 'embedded': { - 'Spawn_Content_29300': { - 'hash': 29300, - 'name': 'Spawn Content', - 'savables': {} - }, - 'Storage_Crate_Redwood_Closed_64282': { - 'hash': 64282, - 'name': 'Storage Crate Redwood Closed', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Storage_Crate_Redwood_Open': { - 'hash': 32788, - 'name': 'Storage Crate Redwood Open', - 'embedded': { - 'Random_Spawn_Rectangle_22462': { - 'hash': 22462, - 'name': 'Random Spawn Rectangle', - 'savables': { - 'RandomSpawnRectangle': { - 'hash': 3101665521, - 'name': 'RandomSpawnRectangle' - } - } - }, - 'Spawn_Content_3812': { - 'hash': 3812, - 'name': 'Spawn Content', - 'savables': {} - }, - 'Storage_Crate_Redwood_Open_50750': { - 'hash': 50750, - 'name': 'Storage Crate Redwood Open', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Street_Post': { - 'hash': 57248, - 'name': 'Street Post', - 'embedded': { - 'Sign_Body_17004': { - 'hash': 17004, - 'name': 'Sign Body', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Street_Post_54666': { - 'hash': 54666, - 'name': 'Street Post', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - }, - 'Visual_1_28010': { - 'hash': 28010, - 'name': 'Visual 1', - 'savables': { - 'MeshPlacement': { - 'hash': 2169673426, - 'name': 'MeshPlacement' - } - } - }, - 'Visual_2_57532': { - 'hash': 57532, - 'name': 'Visual 2', - 'savables': { - 'MeshPlacement': { - 'hash': 2169673426, - 'name': 'MeshPlacement' - } - } - }, - 'Visual_3_15494': { - 'hash': 15494, - 'name': 'Visual 3', - 'savables': { - 'MeshPlacement': { - 'hash': 2169673426, - 'name': 'MeshPlacement' - } - } - }, - 'Visual_4_9368': { - 'hash': 9368, - 'name': 'Visual 4', - 'savables': { - 'MeshPlacement': { - 'hash': 2169673426, - 'name': 'MeshPlacement' - } - } - } - } - }, - 'Structure_Chest': { - 'hash': 35280, - 'name': 'Structure Chest', - 'embedded': { - 'Bottom_Dock_1_2780': { - 'hash': 2780, - 'name': 'Bottom Dock 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_2_2778': { - 'hash': 2778, - 'name': 'Bottom Dock 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_3_2776': { - 'hash': 2776, - 'name': 'Bottom Dock 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_4_2770': { - 'hash': 2770, - 'name': 'Bottom Dock 4', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_5_2772': { - 'hash': 2772, - 'name': 'Bottom Dock 5', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Bottom_Dock_6_2774': { - 'hash': 2774, - 'name': 'Bottom Dock 6', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Handle_Left_23970': { - 'hash': 23970, - 'name': 'Handle Left', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Handle_Right_23964': { - 'hash': 23964, - 'name': 'Handle Right', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Lid_2768': { - 'hash': 2768, - 'name': 'Lid', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Storage_Chest_(1)_2788': { - 'hash': 2788, - 'name': 'Storage Chest (1)', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - }, - 'Chest': { - 'hash': 3598052397, - 'name': 'Chest' - } - } - }, - 'Structure_Chest_21454': { - 'hash': 21454, - 'name': 'Structure Chest', - 'savables': { - 'GeneratedLoot': { - 'hash': 3642863935, - 'name': 'GeneratedLoot' - } - } - }, - 'Top_Dock_1_2766': { - 'hash': 2766, - 'name': 'Top Dock 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_2_2764': { - 'hash': 2764, - 'name': 'Top Dock 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_3_2762': { - 'hash': 2762, - 'name': 'Top Dock 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_4_2756': { - 'hash': 2756, - 'name': 'Top Dock 4', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_5_2758': { - 'hash': 2758, - 'name': 'Top Dock 5', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Top_Dock_6_2760': { - 'hash': 2760, - 'name': 'Top Dock 6', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - } - } - }, - 'TEMP_Hebios_Camp_Spawner_Barren': { - 'hash': 33858, - 'name': 'TEMP_Hebios_Camp_Spawner_Barren', - 'embedded': {} - }, - 'TEMP_Hebios_Camp_Spawner_Valley': { - 'hash': 33880, - 'name': 'TEMP_Hebios_Camp_Spawner_Valley', - 'embedded': {} - }, - 'TEMP_Watch_Tower_Spawner': { - 'hash': 44032, - 'name': 'TEMP_Watch_Tower_Spawner', - 'embedded': {} - }, - 'Tab_Lever': { - 'hash': 3354, - 'name': 'Tab_Lever', - 'embedded': {} - }, - 'Table_Placer': { - 'hash': 25418, - 'name': 'Table Placer', - 'embedded': { - 'Table_Placer_29584': { - 'hash': 29584, - 'name': 'Table Placer', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'RaycastCrafter': { - 'hash': 2815374842, - 'name': 'RaycastCrafter' - } - } - } - } - }, - 'Tall_Support': { - 'hash': 46506, - 'name': 'Tall Support', - 'embedded': { - 'Tall_Support_5348': { - 'hash': 5348, - 'name': 'Tall Support', - 'savables': {} - } - } - }, - 'Tall_Support_Beams': { - 'hash': 5682, - 'name': 'Tall Support Beams', - 'embedded': { - 'Tall_Support_Beams_5680': { - 'hash': 5680, - 'name': 'Tall Support Beams', - 'savables': {} - } - } - }, - 'Targeted_Geyser': { - 'hash': 60812, - 'name': 'Targeted Geyser', - 'embedded': { - 'Erupt_Area_19858': { - 'hash': 19858, - 'name': 'Erupt Area', - 'savables': {} - }, - 'Geyser_AI_29794': { - 'hash': 29794, - 'name': 'Geyser AI', - 'savables': {} - }, - 'Targeted_Geyser_37626': { - 'hash': 37626, - 'name': 'Targeted Geyser', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'TeleportOnTrueLogic': { - 'hash': 18260, - 'name': 'TeleportOnTrueLogic', - 'embedded': { - 'TeleportOnTrueLogic_11330': { - 'hash': 11330, - 'name': 'TeleportOnTrueLogic', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'TeleportationPoint': { - 'hash': 3146178080, - 'name': 'TeleportationPoint' - } - } - } - } - }, - 'Teleport_Point': { - 'hash': 33542, - 'name': 'Teleport_Point', - 'embedded': {} - }, - 'Teleporter_Puzzle': { - 'hash': 19164, - 'name': 'Teleporter Puzzle', - 'embedded': { - 'Customization_Teleporter_2940': { - 'hash': 2940, - 'name': 'Customization_Teleporter', - 'savables': {} - }, - 'Teleporter_Puzzle_7710': { - 'hash': 7710, - 'name': 'Teleporter Puzzle', - 'savables': { - 'LogicVector3Receiver': { - 'hash': 1228539097, - 'name': 'LogicVector3Receiver' - }, - 'LogicVector3Sender': { - 'hash': 2026743731, - 'name': 'LogicVector3Sender' - }, - 'PositionProvider': { - 'hash': 3538443740, - 'name': 'PositionProvider' - }, - 'TeleportationPoint': { - 'hash': 3146178080, - 'name': 'TeleportationPoint' - } - } - } - } - }, - 'Teleporter_To_Customization': { - 'hash': 60372, - 'name': 'Teleporter To Customization', - 'embedded': { - 'Customization_Teleporter_27658': { - 'hash': 27658, - 'name': 'Customization_Teleporter', - 'savables': {} - }, - 'Teleporter_To_Customization_60294': { - 'hash': 60294, - 'name': 'Teleporter To Customization', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - } - } - }, - 'Temp_Dynamic_Wall': { - 'hash': 31628, - 'name': 'Temp Dynamic Wall', - 'embedded': { - 'Temp_Dynamic_Wall_8038': { - 'hash': 8038, - 'name': 'Temp Dynamic Wall', - 'savables': {} - } - } - }, - 'Test_Fire': { - 'hash': 31268, - 'name': 'Test Fire', - 'embedded': { - 'Fire_30100': { - 'hash': 30100, - 'name': 'Fire', - 'savables': { - 'Fire': { - 'hash': 3457519710, - 'name': 'Fire' - } - } - }, - 'Forge_Area_19102': { - 'hash': 19102, - 'name': 'Forge_Area', - 'savables': {} - }, - 'Test_Fire_61848': { - 'hash': 61848, - 'name': 'Test Fire', - 'savables': {} - } - } - }, - 'Test_Serializable_Large': { - 'hash': 57330, - 'name': 'Test_Serializable_Large', - 'embedded': {} - }, - 'Test_Serializable_Small': { - 'hash': 51498, - 'name': 'Test_Serializable_Small', - 'embedded': {} - }, - 'Thick_Great_Sword_Blade': { - 'hash': 25802, - 'name': 'Thick Great Sword Blade', - 'embedded': { - 'Heat_Point_Collection_64052': { - 'hash': 64052, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_Large_SwordType_7796': { - 'hash': 7796, - 'name': 'Insert Large SwordType', - 'savables': {} - }, - 'Thick_Great_Sword_Blade_84': { - 'hash': 84, - 'name': 'Thick Great Sword Blade', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'metal_thickGreatsword_blade_full_geo_LOD0_2564': { - 'hash': 2564, - 'name': 'metal_thickGreatsword_blade_full_geo_LOD0', - 'savables': {} - } - } - }, - 'Thin_Cloth_Medium_Square': { - 'hash': 34570, - 'name': 'Thin Cloth Medium Square', - 'embedded': { - 'Thin_Cloth_Medium_Square_14710': { - 'hash': 14710, - 'name': 'Thin Cloth Medium Square', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Timber_Bag': { - 'hash': 25122, - 'name': 'Timber Bag', - 'embedded': { - 'Bag_Body_42972': { - 'hash': 42972, - 'name': 'Bag Body', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Dock_TL_42990': { - 'hash': 42990, - 'name': 'Dock TL', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Interaction_Point_59032': { - 'hash': 59032, - 'name': 'Interaction Point', - 'savables': {} - }, - 'Slot_Bag_Attach_30776': { - 'hash': 30776, - 'name': 'Slot Bag Attach', - 'savables': {} - }, - 'Slot_Bag_Attach_55164': { - 'hash': 55164, - 'name': 'Slot Bag Attach', - 'savables': {} - }, - 'Timber_Bag_43012': { - 'hash': 43012, - 'name': 'Timber Bag', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'basket_bag_handle_wraps_56574': { - 'hash': 56574, - 'name': 'basket_bag_handle_wraps', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'basket_handle_56602': { - 'hash': 56602, - 'name': 'basket_handle', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_leather_pad_14826': { - 'hash': 14826, - 'name': 'timber_bag_leather_pad', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_plank_01_14822': { - 'hash': 14822, - 'name': 'timber_bag_plank_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_plank_02_14818': { - 'hash': 14818, - 'name': 'timber_bag_plank_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_plank_03_14814': { - 'hash': 14814, - 'name': 'timber_bag_plank_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_ropeKnot_01_14810': { - 'hash': 14810, - 'name': 'timber_bag_ropeKnot_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_ropeKnot_02_14806': { - 'hash': 14806, - 'name': 'timber_bag_ropeKnot_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_ropeKnot_03_14802': { - 'hash': 14802, - 'name': 'timber_bag_ropeKnot_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_ropeKnot_04_14798': { - 'hash': 14798, - 'name': 'timber_bag_ropeKnot_04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_ropeKnot_05_14794': { - 'hash': 14794, - 'name': 'timber_bag_ropeKnot_05', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_ropeKnot_07_14890': { - 'hash': 14890, - 'name': 'timber_bag_ropeKnot_07', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_ropeKnot_08_14886': { - 'hash': 14886, - 'name': 'timber_bag_ropeKnot_08', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_ropeNotch_01_14882': { - 'hash': 14882, - 'name': 'timber_bag_ropeNotch_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_ropeNotch_02_14878': { - 'hash': 14878, - 'name': 'timber_bag_ropeNotch_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_ropeNotch_03_14874': { - 'hash': 14874, - 'name': 'timber_bag_ropeNotch_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_ropeNotch_04_14870': { - 'hash': 14870, - 'name': 'timber_bag_ropeNotch_04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_ropeNotch_05_14866': { - 'hash': 14866, - 'name': 'timber_bag_ropeNotch_05', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_ropeNotch_06_14862': { - 'hash': 14862, - 'name': 'timber_bag_ropeNotch_06', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_ropeNotch_07_14858': { - 'hash': 14858, - 'name': 'timber_bag_ropeNotch_07', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_ropeNotch_08_14854': { - 'hash': 14854, - 'name': 'timber_bag_ropeNotch_08', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_stick_010_14846': { - 'hash': 14846, - 'name': 'timber_bag_stick_010', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_stick_011_14842': { - 'hash': 14842, - 'name': 'timber_bag_stick_011', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_stick_01_14850': { - 'hash': 14850, - 'name': 'timber_bag_stick_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_stick_02_14838': { - 'hash': 14838, - 'name': 'timber_bag_stick_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_stick_03_14834': { - 'hash': 14834, - 'name': 'timber_bag_stick_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_stick_04_14830': { - 'hash': 14830, - 'name': 'timber_bag_stick_04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_stick_05_14790': { - 'hash': 14790, - 'name': 'timber_bag_stick_05', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_stick_06_14786': { - 'hash': 14786, - 'name': 'timber_bag_stick_06', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_stick_07_14782': { - 'hash': 14782, - 'name': 'timber_bag_stick_07', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_stick_08_14778': { - 'hash': 14778, - 'name': 'timber_bag_stick_08', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_stick_09_14774': { - 'hash': 14774, - 'name': 'timber_bag_stick_09', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Timber_Side_Pouch_Attachment': { - 'hash': 7102, - 'name': 'Timber Side Pouch Attachment', - 'embedded': { - 'Dock_45700': { - 'hash': 45700, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62078': { - 'hash': 62078, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Insert_Bag_Attach_7796': { - 'hash': 7796, - 'name': 'Insert Bag Attach', - 'savables': {} - }, - 'Storage_52232': { - 'hash': 52232, - 'name': 'Storage', - 'savables': {} - }, - 'Timber_Side_Pouch_Attachment_7868': { - 'hash': 7868, - 'name': 'Timber Side Pouch Attachment', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'timber_bag_attachment_plank_01_358': { - 'hash': 358, - 'name': 'timber_bag_attachment_plank_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_attachment_ropeKnot_01_406': { - 'hash': 406, - 'name': 'timber_bag_attachment_ropeKnot_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_attachment_ropeKnot_02_402': { - 'hash': 402, - 'name': 'timber_bag_attachment_ropeKnot_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_attachment_ropeNotch_01_390': { - 'hash': 390, - 'name': 'timber_bag_attachment_ropeNotch_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_attachment_stick_01_386': { - 'hash': 386, - 'name': 'timber_bag_attachment_stick_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_attachment_stick_02_382': { - 'hash': 382, - 'name': 'timber_bag_attachment_stick_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_attachment_stick_03_378': { - 'hash': 378, - 'name': 'timber_bag_attachment_stick_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_attachment_stick_04_374': { - 'hash': 374, - 'name': 'timber_bag_attachment_stick_04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_attachment_stick_05_370': { - 'hash': 370, - 'name': 'timber_bag_attachment_stick_05', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'timber_bag_attachment_stick_06_366': { - 'hash': 366, - 'name': 'timber_bag_attachment_stick_06', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Timed_Respawner': { - 'hash': 32620, - 'name': 'Timed Respawner', - 'embedded': { - 'Timed_Respawner_32662': { - 'hash': 32662, - 'name': 'Timed Respawner', - 'savables': { - 'RespawnOnDestroy': { - 'hash': 830106687, - 'name': 'RespawnOnDestroy' - } - } - } - } - }, - 'TimerLogic': { - 'hash': 18490, - 'name': 'TimerLogic', - 'embedded': { - 'TimerLogic_63978': { - 'hash': 63978, - 'name': 'TimerLogic', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'TimerLogic': { - 'hash': 3109677933, - 'name': 'TimerLogic' - } - } - } - } - }, - 'Tinder': { - 'hash': 34122, - 'name': 'Tinder', - 'embedded': { - 'Fire_8488': { - 'hash': 8488, - 'name': 'Fire', - 'savables': { - 'Fire': { - 'hash': 3457519710, - 'name': 'Fire' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Spawner_49628': { - 'hash': 49628, - 'name': 'Spawner', - 'savables': {} - }, - 'Tinder_24372': { - 'hash': 24372, - 'name': 'Tinder', - 'savables': { - 'BasicDecay': { - 'hash': 3801256786, - 'name': 'BasicDecay' - } - } - } - } - }, - 'Tomato_Flower_Bloom': { - 'hash': 13022, - 'name': 'Tomato Flower Bloom', - 'embedded': { - 'Tomato_Flower_Bloom_49826': { - 'hash': 49826, - 'name': 'Tomato Flower Bloom', - 'savables': {} - } - } - }, - 'Tomato_Flower_Bud': { - 'hash': 13024, - 'name': 'Tomato Flower Bud', - 'embedded': { - 'Tomato_Flower_Bud_49898': { - 'hash': 49898, - 'name': 'Tomato Flower Bud', - 'savables': {} - } - } - }, - 'Tomato_Full_Burnt': { - 'hash': 38742, - 'name': 'Tomato Full Burnt', - 'embedded': { - 'Cooking_57238': { - 'hash': 57238, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Tomato_Full_Burnt_38212': { - 'hash': 38212, - 'name': 'Tomato Full Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Tomato_Full_Cooked': { - 'hash': 38098, - 'name': 'Tomato Full Cooked', - 'embedded': { - 'Cooking_56718': { - 'hash': 56718, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Tomato_Full_Cooked_37568': { - 'hash': 37568, - 'name': 'Tomato Full Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Tomato_Full_Ripe': { - 'hash': 37454, - 'name': 'Tomato Full Ripe', - 'embedded': { - 'Cooking_56198': { - 'hash': 56198, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Tomato_Full_Ripe_36924': { - 'hash': 36924, - 'name': 'Tomato Full Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Tomato_Full_Unripe': { - 'hash': 36810, - 'name': 'Tomato Full Unripe', - 'embedded': { - 'Cooking_55678': { - 'hash': 55678, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Tomato_Full_Unripe_36280': { - 'hash': 36280, - 'name': 'Tomato Full Unripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Tomato_Growth': { - 'hash': 19280, - 'name': 'Tomato Growth', - 'embedded': { - 'Tomato_Growth_33458': { - 'hash': 33458, - 'name': 'Tomato Growth', - 'savables': { - 'GrowerComponent': { - 'hash': 3402094521, - 'name': 'GrowerComponent' - } - } - } - } - }, - 'Tomato_Half_Burnt': { - 'hash': 57698, - 'name': 'Tomato Half Burnt', - 'embedded': { - 'Cooking_30630': { - 'hash': 30630, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Tomato_Half_Burnt_57360': { - 'hash': 57360, - 'name': 'Tomato Half Burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Tomato_Half_Cooked': { - 'hash': 57294, - 'name': 'Tomato Half Cooked', - 'embedded': { - 'Cooking_30288': { - 'hash': 30288, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Tomato_Half_Cooked_56956': { - 'hash': 56956, - 'name': 'Tomato Half Cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Tomato_Half_Ripe': { - 'hash': 56890, - 'name': 'Tomato Half Ripe', - 'embedded': { - 'Cooking_29946': { - 'hash': 29946, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Tomato_Half_Ripe_56552': { - 'hash': 56552, - 'name': 'Tomato Half Ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Tomato_Half_Unripe': { - 'hash': 56486, - 'name': 'Tomato Half Unripe', - 'embedded': { - 'Cooking_29604': { - 'hash': 29604, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Tomato_Half_Unripe_56148': { - 'hash': 56148, - 'name': 'Tomato Half Unripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'RaycastCrafter': { - 'hash': 2815374842, - 'name': 'RaycastCrafter' - } - } - } - } - }, - 'Tomato_Tree': { - 'hash': 56492, - 'name': 'Tomato Tree', - 'embedded': { - 'Tomato_Tree_54408': { - 'hash': 54408, - 'name': 'Tomato Tree', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Tomato_Tree_Growth': { - 'hash': 16358, - 'name': 'Tomato Tree Growth', - 'embedded': { - 'Tomato_Tree_Growth_33458': { - 'hash': 33458, - 'name': 'Tomato Tree Growth', - 'savables': { - 'GrowerComponent': { - 'hash': 3402094521, - 'name': 'GrowerComponent' - } - } - } - } - }, - 'Tomato_Tree_Separated': { - 'hash': 21548, - 'name': 'Tomato_Tree_Separated', - 'embedded': {} - }, - 'Tomato_Tree_Stage_1': { - 'hash': 2384, - 'name': 'Tomato Tree Stage 1', - 'embedded': { - 'Tomato_Tree_Stage_1_63514': { - 'hash': 63514, - 'name': 'Tomato Tree Stage 1', - 'savables': {} - } - } - }, - 'Tomato_Tree_Stage_2': { - 'hash': 2542, - 'name': 'Tomato Tree Stage 2', - 'embedded': { - 'Tomato_Tree_Stage_2_52164': { - 'hash': 52164, - 'name': 'Tomato Tree Stage 2', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Tomato_Tree_Stage_3': { - 'hash': 2892, - 'name': 'Tomato Tree Stage 3', - 'embedded': { - 'Tomato_Tree_Stage_3_23378': { - 'hash': 23378, - 'name': 'Tomato Tree Stage 3', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Torch': { - 'hash': 56698, - 'name': 'Torch', - 'embedded': { - 'Fire_30100': { - 'hash': 30100, - 'name': 'Fire', - 'savables': { - 'Fire': { - 'hash': 3457519710, - 'name': 'Fire' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Torch_30110': { - 'hash': 30110, - 'name': 'Torch', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Township_Bridge_Broken': { - 'hash': 8620, - 'name': 'Township Bridge Broken', - 'embedded': { - 'Township_Bridge_Broken_13660': { - 'hash': 13660, - 'name': 'Township Bridge Broken', - 'savables': {} - } - } - }, - 'Township_Bridge_Fixed': { - 'hash': 33334, - 'name': 'Township Bridge Fixed', - 'embedded': { - 'Township_Bridge_Fixed_13518': { - 'hash': 13518, - 'name': 'Township Bridge Fixed', - 'savables': {} - } - } - }, - 'Township_Bridge_Repair_Box': { - 'hash': 60674, - 'name': 'Township Bridge Repair Box', - 'embedded': { - 'Cost_1_22852': { - 'hash': 22852, - 'name': 'Cost 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Cost_2_22786': { - 'hash': 22786, - 'name': 'Cost 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Cost_3_22772': { - 'hash': 22772, - 'name': 'Cost 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_1_22642': { - 'hash': 22642, - 'name': 'Dock 1', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_2_22692': { - 'hash': 22692, - 'name': 'Dock 2', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_3_22698': { - 'hash': 22698, - 'name': 'Dock 3', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Township_Bridge_Broken_60312': { - 'hash': 60312, - 'name': 'Township Bridge Broken', - 'savables': {} - }, - 'Township_Bridge_Repair_Box_60672': { - 'hash': 60672, - 'name': 'Township Bridge Repair Box', - 'savables': { - 'RepairBox': { - 'hash': 3820454400, - 'name': 'RepairBox' - } - } - } - } - }, - 'Trade_Deck': { - 'hash': 30016, - 'name': 'Trade Deck', - 'embedded': { - 'BuyCoinDisplay_3686': { - 'hash': 3686, - 'name': 'BuyCoinDisplay', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'BuyItemDisplay_3684': { - 'hash': 3684, - 'name': 'BuyItemDisplay', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'CoinTradeCounter_63408': { - 'hash': 63408, - 'name': 'CoinTradeCounter', - 'savables': { - 'ButtonCounter': { - 'hash': 3901697682, - 'name': 'ButtonCounter' - } - } - }, - 'Grab_14560': { - 'hash': 14560, - 'name': 'Grab', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grab_22452': { - 'hash': 22452, - 'name': 'Grab', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Handle_65280': { - 'hash': 65280, - 'name': 'Handle', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'ItemTradeCounters_404': { - 'hash': 404, - 'name': 'ItemTradeCounters', - 'savables': { - 'ButtonCounter': { - 'hash': 3901697682, - 'name': 'ButtonCounter' - } - } - }, - 'ProfitDock_52720': { - 'hash': 52720, - 'name': 'ProfitDock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'SellCoinDisplay_3680': { - 'hash': 3680, - 'name': 'SellCoinDisplay', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'SellItemDisplay_34750': { - 'hash': 34750, - 'name': 'SellItemDisplay', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'StockDock_50586': { - 'hash': 50586, - 'name': 'StockDock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'TaxDock_54312': { - 'hash': 54312, - 'name': 'TaxDock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'TaxLever_48782': { - 'hash': 48782, - 'name': 'TaxLever', - 'savables': { - 'Lever': { - 'hash': 1594932294, - 'name': 'Lever' - } - } - }, - 'TemporaryCoinDock_28320': { - 'hash': 28320, - 'name': 'TemporaryCoinDock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Trade_Deck_31038': { - 'hash': 31038, - 'name': 'Trade Deck', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - }, - 'TaxManager': { - 'hash': 43510150, - 'name': 'TaxManager' - }, - 'TradeVendor': { - 'hash': 1645673210, - 'name': 'TradeVendor' - } - } - } - } - }, - 'TraderPrototype': { - 'hash': 28820, - 'name': 'TraderPrototype', - 'embedded': {} - }, - 'Training_Short_Sword_Blade_COLD': { - 'hash': 1850, - 'name': 'Training Short Sword Blade COLD', - 'embedded': { - 'Forged_Model_4044': { - 'hash': 4044, - 'name': 'Forged Model', - 'savables': {} - }, - 'Heat_Point_Collection_11428': { - 'hash': 11428, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Training_Short_Sword_Blade_COLD_36330': { - 'hash': 36330, - 'name': 'Training Short Sword Blade COLD', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Training_Short_Sword_Blade_HOT': { - 'hash': 13220, - 'name': 'Training Short Sword Blade HOT', - 'embedded': { - 'Forged_Model_4044': { - 'hash': 4044, - 'name': 'Forged Model', - 'savables': {} - }, - 'Heat_Point_Collection_11814': { - 'hash': 11814, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Training_Short_Sword_Blade_HOT_36330': { - 'hash': 36330, - 'name': 'Training Short Sword Blade HOT', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'ForgedPointCollection': { - 'hash': 2272630171, - 'name': 'ForgedPointCollection' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Tree': { - 'hash': 8860, - 'name': 'Tree', - 'embedded': { - 'Tree_54994': { - 'hash': 54994, - 'name': 'Tree', - 'savables': { - 'GrowthStageComponent': { - 'hash': 751359624, - 'name': 'GrowthStageComponent' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - }, - 'TreeDecay': { - 'hash': 2042199192, - 'name': 'TreeDecay' - }, - 'WoodcutTree': { - 'hash': 1098050191, - 'name': 'WoodcutTree' - } - } - } - } - }, - 'Tree_Button_Spawner': { - 'hash': 3934, - 'name': 'Tree_Button_Spawner', - 'embedded': {} - }, - 'Tree_Grower': { - 'hash': 25934, - 'name': 'Tree Grower', - 'embedded': { - 'Tree_Grower_33458': { - 'hash': 33458, - 'name': 'Tree Grower', - 'savables': { - 'TimeBasedStagedPrefab': { - 'hash': 1085701614, - 'name': 'TimeBasedStagedPrefab' - } - } - } - } - }, - 'Tree_Grown': { - 'hash': 30572, - 'name': 'Tree Grown', - 'embedded': { - 'Tree_Grown_53296': { - 'hash': 53296, - 'name': 'Tree Grown', - 'savables': {} - } - } - }, - 'Tree_Spawner_-_Any_Ash': { - 'hash': 50794, - 'name': 'Tree Spawner - Any Ash', - 'embedded': { - 'Tree_Spawner_-_Any_Ash_50788': { - 'hash': 50788, - 'name': 'Tree Spawner - Any Ash', - 'savables': { - 'TreeSpawner': { - 'hash': 3638500874, - 'name': 'TreeSpawner' - } - } - } - } - }, - 'Tree_Spawner_-_Any_Birch': { - 'hash': 570, - 'name': 'Tree Spawner - Any Birch', - 'embedded': { - 'Tree_Spawner_-_Any_Birch_21194': { - 'hash': 21194, - 'name': 'Tree Spawner - Any Birch', - 'savables': { - 'TreeSpawner': { - 'hash': 3638500874, - 'name': 'TreeSpawner' - } - } - } - } - }, - 'Tree_Spawner_-_Any_Oak': { - 'hash': 48358, - 'name': 'Tree Spawner - Any Oak', - 'embedded': { - 'Tree_Spawner_-_Any_Oak_21194': { - 'hash': 21194, - 'name': 'Tree Spawner - Any Oak', - 'savables': { - 'TreeSpawner': { - 'hash': 3638500874, - 'name': 'TreeSpawner' - } - } - } - } - }, - 'Tree_Spawner_-_Any_Redwood': { - 'hash': 546, - 'name': 'Tree Spawner - Any Redwood', - 'embedded': { - 'Tree_Spawner_-_Any_Redwood_21194': { - 'hash': 21194, - 'name': 'Tree Spawner - Any Redwood', - 'savables': { - 'TreeSpawner': { - 'hash': 3638500874, - 'name': 'TreeSpawner' - } - } - } - } - }, - 'Tree_Spawner_-_Any_Standard': { - 'hash': 15738, - 'name': 'Tree Spawner - Any Standard', - 'embedded': { - 'Tree_Spawner_-_Any_Standard_21194': { - 'hash': 21194, - 'name': 'Tree Spawner - Any Standard', - 'savables': { - 'TreeSpawner': { - 'hash': 3638500874, - 'name': 'TreeSpawner' - } - } - } - } - }, - 'Tree_Spawner_-_Any_TEMP_TEST': { - 'hash': 58970, - 'name': 'Tree_Spawner_-_Any_TEMP_TEST', - 'embedded': {} - }, - 'Tree_Spawner_-_Any_Walnut': { - 'hash': 34710, - 'name': 'Tree Spawner - Any Walnut', - 'embedded': { - 'Tree_Spawner_-_Any_Walnut_21194': { - 'hash': 21194, - 'name': 'Tree Spawner - Any Walnut', - 'savables': { - 'TreeSpawner': { - 'hash': 3638500874, - 'name': 'TreeSpawner' - } - } - } - } - }, - 'Tree_Spawner_-_Small_Standard': { - 'hash': 57286, - 'name': 'Tree Spawner - Small Standard', - 'embedded': { - 'Tree_Spawner_-_Small_Standard_21194': { - 'hash': 21194, - 'name': 'Tree Spawner - Small Standard', - 'savables': { - 'TreeSpawner': { - 'hash': 3638500874, - 'name': 'TreeSpawner' - } - } - } - } - }, - 'Tree_Young': { - 'hash': 30570, - 'name': 'Tree Young', - 'embedded': { - 'Tree_Young_53362': { - 'hash': 53362, - 'name': 'Tree Young', - 'savables': {} - } - } - }, - 'Trial_Spawner_MD-T1': { - 'hash': 62144, - 'name': 'Trial Spawner MD-T1', - 'embedded': { - 'Trial_Spawner_MD-T1_37438': { - 'hash': 37438, - 'name': 'Trial Spawner MD-T1', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - } - } - }, - 'Trial_Spawner_MD-T2': { - 'hash': 60910, - 'name': 'Trial Spawner MD-T2', - 'embedded': { - 'Trial_Spawner_MD-T2_37438': { - 'hash': 37438, - 'name': 'Trial Spawner MD-T2', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - } - } - }, - 'Trial_Spawner_MD-T3': { - 'hash': 52988, - 'name': 'Trial Spawner MD-T3', - 'embedded': { - 'Trial_Spawner_MD-T3_37438': { - 'hash': 37438, - 'name': 'Trial Spawner MD-T3', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - } - } - }, - 'Trial_Spawner_MD-W1': { - 'hash': 32210, - 'name': 'Trial Spawner MD-W1', - 'embedded': { - 'Trial_Spawner_MD-W1_52626': { - 'hash': 52626, - 'name': 'Trial Spawner MD-W1', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - } - } - }, - 'Trial_Spawner_MD-W2': { - 'hash': 50818, - 'name': 'Trial Spawner MD-W2', - 'embedded': { - 'Trial_Spawner_MD-W2_52626': { - 'hash': 52626, - 'name': 'Trial Spawner MD-W2', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - } - } - }, - 'Trial_Spawner_T-1': { - 'hash': 7744, - 'name': 'Trial Spawner T-1', - 'embedded': { - 'Trial_Spawner_T-1_37438': { - 'hash': 37438, - 'name': 'Trial Spawner T-1', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - } - } - }, - 'Trial_Spawner_T-2': { - 'hash': 40198, - 'name': 'Trial Spawner T-2', - 'embedded': { - 'Trial_Spawner_T-2_9898': { - 'hash': 9898, - 'name': 'Trial Spawner T-2', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - } - } - }, - 'Trial_Spawner_T-3': { - 'hash': 45096, - 'name': 'Trial Spawner T-3', - 'embedded': { - 'Trial_Spawner_T-3_37438': { - 'hash': 37438, - 'name': 'Trial Spawner T-3', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - } - } - }, - 'Trial_Spawner_T-3-Myth': { - 'hash': 49994, - 'name': 'Trial Spawner T-3-Myth', - 'embedded': { - 'Trial_Spawner_T-3-Myth_37438': { - 'hash': 37438, - 'name': 'Trial Spawner T-3-Myth', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - } - } - }, - 'Trial_Spawner_W-1': { - 'hash': 33084, - 'name': 'Trial Spawner W-1', - 'embedded': { - 'Trial_Spawner_W-1_52626': { - 'hash': 52626, - 'name': 'Trial Spawner W-1', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - } - } - }, - 'Trial_Spawner_W-2': { - 'hash': 18696, - 'name': 'Trial Spawner W-2', - 'embedded': { - 'Trial_Spawner_W-2_52626': { - 'hash': 52626, - 'name': 'Trial Spawner W-2', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - } - } - }, - 'Trial_Spawner_W-2-Crys': { - 'hash': 58286, - 'name': 'Trial Spawner W-2-Crys', - 'embedded': { - 'Trial_Spawner_W-2-Crys_52626': { - 'hash': 52626, - 'name': 'Trial Spawner W-2-Crys', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - } - } - }, - 'Trial_Spawner_W-3': { - 'hash': 42624, - 'name': 'Trial Spawner W-3', - 'embedded': { - 'Trial_Spawner_W-3_52626': { - 'hash': 52626, - 'name': 'Trial Spawner W-3', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - } - } - }, - 'Turabada': { - 'hash': 13804, - 'name': 'Turabada', - 'embedded': { - 'Arm_Collision_L_40528': { - 'hash': 40528, - 'name': 'Arm Collision L', - 'savables': {} - }, - 'Arm_Collision_R_42784': { - 'hash': 42784, - 'name': 'Arm Collision R', - 'savables': {} - }, - 'Explosion_58370': { - 'hash': 58370, - 'name': 'Explosion', - 'savables': {} - }, - 'Killed_Drops_63174': { - 'hash': 63174, - 'name': 'Killed Drops', - 'savables': {} - }, - 'Target_Collector_10522': { - 'hash': 10522, - 'name': 'Target Collector', - 'savables': {} - }, - 'Turabada_01_2540': { - 'hash': 2540, - 'name': 'Turabada_01', - 'savables': {} - }, - 'Turabada_13756': { - 'hash': 13756, - 'name': 'Turabada', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Turabada_AI_10656': { - 'hash': 10656, - 'name': 'Turabada AI', - 'savables': { - 'LevelStatModifier': { - 'hash': 788405183, - 'name': 'LevelStatModifier' - } - } - } - } - }, - 'Turabada_Arm': { - 'hash': 15584, - 'name': 'Turabada Arm', - 'embedded': { - 'Insert_HammerType_End_Cap_52192': { - 'hash': 52192, - 'name': 'Insert HammerType End Cap', - 'savables': {} - }, - 'Turabada_Arm_15540': { - 'hash': 15540, - 'name': 'Turabada Arm', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Turabada_Copper_Destroy_Variant': { - 'hash': 34850, - 'name': 'Turabada Copper Destroy Variant', - 'embedded': { - 'Turabada_Copper_Destroy_Variant_37492': { - 'hash': 37492, - 'name': 'Turabada Copper Destroy Variant', - 'savables': {} - } - } - }, - 'Turabada_Copper_Trial_Variant': { - 'hash': 14248, - 'name': 'Turabada Copper Trial Variant', - 'embedded': { - 'Arm_Collision_L_40528': { - 'hash': 40528, - 'name': 'Arm Collision L', - 'savables': {} - }, - 'Arm_Collision_R_42784': { - 'hash': 42784, - 'name': 'Arm Collision R', - 'savables': {} - }, - 'Explosion_58370': { - 'hash': 58370, - 'name': 'Explosion', - 'savables': {} - }, - 'Killed_Drops_63174': { - 'hash': 63174, - 'name': 'Killed Drops', - 'savables': {} - }, - 'Target_Collector_10522': { - 'hash': 10522, - 'name': 'Target Collector', - 'savables': {} - }, - 'Turabada_01_2540': { - 'hash': 2540, - 'name': 'Turabada_01', - 'savables': {} - }, - 'Turabada_AI_10656': { - 'hash': 10656, - 'name': 'Turabada AI', - 'savables': { - 'LevelStatModifier': { - 'hash': 788405183, - 'name': 'LevelStatModifier' - } - } - }, - 'Turabada_Copper_Trial_Variant_13756': { - 'hash': 13756, - 'name': 'Turabada Copper Trial Variant', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Turabada_Copper_Variant': { - 'hash': 39056, - 'name': 'Turabada Copper Variant', - 'embedded': { - 'Arm_Collision_L_40528': { - 'hash': 40528, - 'name': 'Arm Collision L', - 'savables': {} - }, - 'Arm_Collision_R_42784': { - 'hash': 42784, - 'name': 'Arm Collision R', - 'savables': {} - }, - 'Explosion_58370': { - 'hash': 58370, - 'name': 'Explosion', - 'savables': {} - }, - 'Killed_Drops_63174': { - 'hash': 63174, - 'name': 'Killed Drops', - 'savables': {} - }, - 'Target_Collector_10522': { - 'hash': 10522, - 'name': 'Target Collector', - 'savables': {} - }, - 'Turabada_01_2540': { - 'hash': 2540, - 'name': 'Turabada_01', - 'savables': {} - }, - 'Turabada_AI_10656': { - 'hash': 10656, - 'name': 'Turabada AI', - 'savables': { - 'LevelStatModifier': { - 'hash': 788405183, - 'name': 'LevelStatModifier' - } - } - }, - 'Turabada_Copper_Variant_13756': { - 'hash': 13756, - 'name': 'Turabada Copper Variant', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Turabada_Destroy': { - 'hash': 37508, - 'name': 'Turabada Destroy', - 'embedded': { - 'Turabada_Destroy_37492': { - 'hash': 37492, - 'name': 'Turabada Destroy', - 'savables': {} - } - } - }, - 'Turabada_Gold_Destroy_Variant': { - 'hash': 15310, - 'name': 'Turabada Gold Destroy Variant', - 'embedded': { - 'Turabada_Gold_Destroy_Variant_37492': { - 'hash': 37492, - 'name': 'Turabada Gold Destroy Variant', - 'savables': {} - } - } - }, - 'Turabada_Gold_Trial_Variant': { - 'hash': 15506, - 'name': 'Turabada Gold Trial Variant', - 'embedded': { - 'Arm_Collision_L_40528': { - 'hash': 40528, - 'name': 'Arm Collision L', - 'savables': {} - }, - 'Arm_Collision_R_42784': { - 'hash': 42784, - 'name': 'Arm Collision R', - 'savables': {} - }, - 'Explosion_58370': { - 'hash': 58370, - 'name': 'Explosion', - 'savables': {} - }, - 'Killed_Drops_63174': { - 'hash': 63174, - 'name': 'Killed Drops', - 'savables': {} - }, - 'Target_Collector_10522': { - 'hash': 10522, - 'name': 'Target Collector', - 'savables': {} - }, - 'Turabada_01_2540': { - 'hash': 2540, - 'name': 'Turabada_01', - 'savables': {} - }, - 'Turabada_AI_10656': { - 'hash': 10656, - 'name': 'Turabada AI', - 'savables': { - 'LevelStatModifier': { - 'hash': 788405183, - 'name': 'LevelStatModifier' - } - } - }, - 'Turabada_Gold_Trial_Variant_13756': { - 'hash': 13756, - 'name': 'Turabada Gold Trial Variant', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Turabada_Gold_Variant': { - 'hash': 37176, - 'name': 'Turabada Gold Variant', - 'embedded': { - 'Arm_Collision_L_40528': { - 'hash': 40528, - 'name': 'Arm Collision L', - 'savables': {} - }, - 'Arm_Collision_R_42784': { - 'hash': 42784, - 'name': 'Arm Collision R', - 'savables': {} - }, - 'Explosion_58370': { - 'hash': 58370, - 'name': 'Explosion', - 'savables': {} - }, - 'Killed_Drops_63174': { - 'hash': 63174, - 'name': 'Killed Drops', - 'savables': {} - }, - 'Target_Collector_10522': { - 'hash': 10522, - 'name': 'Target Collector', - 'savables': {} - }, - 'Turabada_01_2540': { - 'hash': 2540, - 'name': 'Turabada_01', - 'savables': {} - }, - 'Turabada_AI_10656': { - 'hash': 10656, - 'name': 'Turabada AI', - 'savables': { - 'LevelStatModifier': { - 'hash': 788405183, - 'name': 'LevelStatModifier' - } - } - }, - 'Turabada_Gold_Variant_13756': { - 'hash': 13756, - 'name': 'Turabada Gold Variant', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Turabada_Hub_Dynamic': { - 'hash': 48478, - 'name': 'Turabada Hub Dynamic', - 'embedded': { - 'Core_Spawn_16554': { - 'hash': 16554, - 'name': 'Core Spawn', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'SpawnArea': { - 'hash': 2617495528, - 'name': 'SpawnArea' - } - } - }, - 'Door_Blockage_Spawn_47616': { - 'hash': 47616, - 'name': 'Door Blockage Spawn', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - }, - 'Enemy_Spawn_30256': { - 'hash': 30256, - 'name': 'Enemy Spawn', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'SpawnArea': { - 'hash': 2617495528, - 'name': 'SpawnArea' - } - } - }, - 'Turabada_Hub_Dynamic_53304': { - 'hash': 53304, - 'name': 'Turabada Hub Dynamic', - 'savables': {} - } - } - }, - 'Turabada_Iron_Destroy_Variant': { - 'hash': 42690, - 'name': 'Turabada Iron Destroy Variant', - 'embedded': { - 'Turabada_Iron_Destroy_Variant_37492': { - 'hash': 37492, - 'name': 'Turabada Iron Destroy Variant', - 'savables': {} - } - } - }, - 'Turabada_Iron_Trial_Variant': { - 'hash': 16684, - 'name': 'Turabada Iron Trial Variant', - 'embedded': { - 'Arm_Collision_L_40528': { - 'hash': 40528, - 'name': 'Arm Collision L', - 'savables': {} - }, - 'Arm_Collision_R_42784': { - 'hash': 42784, - 'name': 'Arm Collision R', - 'savables': {} - }, - 'Explosion_58370': { - 'hash': 58370, - 'name': 'Explosion', - 'savables': {} - }, - 'Killed_Drops_63174': { - 'hash': 63174, - 'name': 'Killed Drops', - 'savables': {} - }, - 'Target_Collector_10522': { - 'hash': 10522, - 'name': 'Target Collector', - 'savables': {} - }, - 'Turabada_01_2540': { - 'hash': 2540, - 'name': 'Turabada_01', - 'savables': {} - }, - 'Turabada_AI_10656': { - 'hash': 10656, - 'name': 'Turabada AI', - 'savables': { - 'LevelStatModifier': { - 'hash': 788405183, - 'name': 'LevelStatModifier' - } - } - }, - 'Turabada_Iron_Trial_Variant_13756': { - 'hash': 13756, - 'name': 'Turabada Iron Trial Variant', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Turabada_Iron_Variant': { - 'hash': 8298, - 'name': 'Turabada Iron Variant', - 'embedded': { - 'Arm_Collision_L_40528': { - 'hash': 40528, - 'name': 'Arm Collision L', - 'savables': {} - }, - 'Arm_Collision_R_42784': { - 'hash': 42784, - 'name': 'Arm Collision R', - 'savables': {} - }, - 'Explosion_58370': { - 'hash': 58370, - 'name': 'Explosion', - 'savables': {} - }, - 'Killed_Drops_63174': { - 'hash': 63174, - 'name': 'Killed Drops', - 'savables': {} - }, - 'Target_Collector_10522': { - 'hash': 10522, - 'name': 'Target Collector', - 'savables': {} - }, - 'Turabada_01_2540': { - 'hash': 2540, - 'name': 'Turabada_01', - 'savables': {} - }, - 'Turabada_AI_10656': { - 'hash': 10656, - 'name': 'Turabada AI', - 'savables': { - 'LevelStatModifier': { - 'hash': 788405183, - 'name': 'LevelStatModifier' - } - } - }, - 'Turabada_Iron_Variant_13756': { - 'hash': 13756, - 'name': 'Turabada Iron Variant', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Turabada_Large_Destroy_Variant': { - 'hash': 63178, - 'name': 'Turabada Large Destroy Variant', - 'embedded': { - 'Turabada_Large_Destroy_Variant_37492': { - 'hash': 37492, - 'name': 'Turabada Large Destroy Variant', - 'savables': {} - } - } - }, - 'Turabada_Large_Trial_Variant': { - 'hash': 17814, - 'name': 'Turabada Large Trial Variant', - 'embedded': { - 'Arm_Collision_L_40528': { - 'hash': 40528, - 'name': 'Arm Collision L', - 'savables': {} - }, - 'Arm_Collision_R_42784': { - 'hash': 42784, - 'name': 'Arm Collision R', - 'savables': {} - }, - 'Explosion_58370': { - 'hash': 58370, - 'name': 'Explosion', - 'savables': {} - }, - 'Killed_Drops_63174': { - 'hash': 63174, - 'name': 'Killed Drops', - 'savables': {} - }, - 'Target_Collector_10522': { - 'hash': 10522, - 'name': 'Target Collector', - 'savables': {} - }, - 'Turabada_01_2540': { - 'hash': 2540, - 'name': 'Turabada_01', - 'savables': {} - }, - 'Turabada_AI_10656': { - 'hash': 10656, - 'name': 'Turabada AI', - 'savables': { - 'LevelStatModifier': { - 'hash': 788405183, - 'name': 'LevelStatModifier' - } - } - }, - 'Turabada_Large_Trial_Variant_13756': { - 'hash': 13756, - 'name': 'Turabada Large Trial Variant', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Turabada_Large_Variant': { - 'hash': 41172, - 'name': 'Turabada Large Variant', - 'embedded': { - 'Arm_Collision_L_40528': { - 'hash': 40528, - 'name': 'Arm Collision L', - 'savables': {} - }, - 'Arm_Collision_R_42784': { - 'hash': 42784, - 'name': 'Arm Collision R', - 'savables': {} - }, - 'Explosion_58370': { - 'hash': 58370, - 'name': 'Explosion', - 'savables': {} - }, - 'Killed_Drops_63174': { - 'hash': 63174, - 'name': 'Killed Drops', - 'savables': {} - }, - 'Target_Collector_10522': { - 'hash': 10522, - 'name': 'Target Collector', - 'savables': {} - }, - 'Turabada_01_2540': { - 'hash': 2540, - 'name': 'Turabada_01', - 'savables': {} - }, - 'Turabada_AI_10656': { - 'hash': 10656, - 'name': 'Turabada AI', - 'savables': { - 'LevelStatModifier': { - 'hash': 788405183, - 'name': 'LevelStatModifier' - } - } - }, - 'Turabada_Large_Variant_13756': { - 'hash': 13756, - 'name': 'Turabada Large Variant', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Turabada_Mythril_Destroy_Variant': { - 'hash': 45488, - 'name': 'Turabada Mythril Destroy Variant', - 'embedded': { - 'Turabada_Mythril_Destroy_Variant_37492': { - 'hash': 37492, - 'name': 'Turabada Mythril Destroy Variant', - 'savables': {} - } - } - }, - 'Turabada_Mythril_Trial_Variant': { - 'hash': 18722, - 'name': 'Turabada Mythril Trial Variant', - 'embedded': { - 'Arm_Collision_L_40528': { - 'hash': 40528, - 'name': 'Arm Collision L', - 'savables': {} - }, - 'Arm_Collision_R_42784': { - 'hash': 42784, - 'name': 'Arm Collision R', - 'savables': {} - }, - 'Explosion_58370': { - 'hash': 58370, - 'name': 'Explosion', - 'savables': {} - }, - 'Killed_Drops_63174': { - 'hash': 63174, - 'name': 'Killed Drops', - 'savables': {} - }, - 'Target_Collector_10522': { - 'hash': 10522, - 'name': 'Target Collector', - 'savables': {} - }, - 'Turabada_01_2540': { - 'hash': 2540, - 'name': 'Turabada_01', - 'savables': {} - }, - 'Turabada_AI_10656': { - 'hash': 10656, - 'name': 'Turabada AI', - 'savables': { - 'LevelStatModifier': { - 'hash': 788405183, - 'name': 'LevelStatModifier' - } - } - }, - 'Turabada_Mythril_Trial_Variant_13756': { - 'hash': 13756, - 'name': 'Turabada Mythril Trial Variant', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Turabada_Mythril_Variant': { - 'hash': 62968, - 'name': 'Turabada Mythril Variant', - 'embedded': { - 'Arm_Collision_L_40528': { - 'hash': 40528, - 'name': 'Arm Collision L', - 'savables': {} - }, - 'Arm_Collision_R_42784': { - 'hash': 42784, - 'name': 'Arm Collision R', - 'savables': {} - }, - 'Explosion_58370': { - 'hash': 58370, - 'name': 'Explosion', - 'savables': {} - }, - 'Killed_Drops_63174': { - 'hash': 63174, - 'name': 'Killed Drops', - 'savables': {} - }, - 'Target_Collector_10522': { - 'hash': 10522, - 'name': 'Target Collector', - 'savables': {} - }, - 'Turabada_01_2540': { - 'hash': 2540, - 'name': 'Turabada_01', - 'savables': {} - }, - 'Turabada_AI_10656': { - 'hash': 10656, - 'name': 'Turabada AI', - 'savables': { - 'LevelStatModifier': { - 'hash': 788405183, - 'name': 'LevelStatModifier' - } - } - }, - 'Turabada_Mythril_Variant_13756': { - 'hash': 13756, - 'name': 'Turabada Mythril Variant', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Turabada_Preview': { - 'hash': 49464, - 'name': 'Turabada_Preview', - 'embedded': {} - }, - 'Turabada_Shard_Core': { - 'hash': 7900, - 'name': 'Turabada Shard Core', - 'embedded': { - 'Chisel_Piece_58818': { - 'hash': 58818, - 'name': 'Chisel Piece', - 'savables': {} - }, - 'Chisel_Piece_58820': { - 'hash': 58820, - 'name': 'Chisel Piece', - 'savables': {} - }, - 'Chisel_Piece_58822': { - 'hash': 58822, - 'name': 'Chisel Piece', - 'savables': {} - }, - 'Chisel_Piece_58824': { - 'hash': 58824, - 'name': 'Chisel Piece', - 'savables': {} - }, - 'Chisel_Piece_58826': { - 'hash': 58826, - 'name': 'Chisel Piece', - 'savables': {} - }, - 'Chisel_Piece_58828': { - 'hash': 58828, - 'name': 'Chisel Piece', - 'savables': {} - }, - 'Chisel_Piece_58830': { - 'hash': 58830, - 'name': 'Chisel Piece', - 'savables': {} - }, - 'Chisel_Piece_58832': { - 'hash': 58832, - 'name': 'Chisel Piece', - 'savables': {} - }, - 'Chisel_Piece_58834': { - 'hash': 58834, - 'name': 'Chisel Piece', - 'savables': {} - }, - 'Chisel_Piece_58836': { - 'hash': 58836, - 'name': 'Chisel Piece', - 'savables': {} - }, - 'Chisel_Piece_58838': { - 'hash': 58838, - 'name': 'Chisel Piece', - 'savables': {} - }, - 'Chisel_Piece_58840': { - 'hash': 58840, - 'name': 'Chisel Piece', - 'savables': {} - }, - 'Chisel_Piece_58842': { - 'hash': 58842, - 'name': 'Chisel Piece', - 'savables': {} - }, - 'Explosion_44800': { - 'hash': 44800, - 'name': 'Explosion', - 'savables': {} - }, - 'Turabada_Shard_Core_7884': { - 'hash': 7884, - 'name': 'Turabada Shard Core', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Turabada_Short_Destroy_Variant': { - 'hash': 48002, - 'name': 'Turabada Short Destroy Variant', - 'embedded': { - 'Turabada_Short_Destroy_Variant_37492': { - 'hash': 37492, - 'name': 'Turabada Short Destroy Variant', - 'savables': {} - } - } - }, - 'Turabada_Short_Trial_Variant': { - 'hash': 19936, - 'name': 'Turabada Short Trial Variant', - 'embedded': { - 'Arm_Collision_L_40528': { - 'hash': 40528, - 'name': 'Arm Collision L', - 'savables': {} - }, - 'Arm_Collision_R_42784': { - 'hash': 42784, - 'name': 'Arm Collision R', - 'savables': {} - }, - 'Explosion_58370': { - 'hash': 58370, - 'name': 'Explosion', - 'savables': {} - }, - 'Killed_Drops_63174': { - 'hash': 63174, - 'name': 'Killed Drops', - 'savables': {} - }, - 'Target_Collector_10522': { - 'hash': 10522, - 'name': 'Target Collector', - 'savables': {} - }, - 'Turabada_01_2540': { - 'hash': 2540, - 'name': 'Turabada_01', - 'savables': {} - }, - 'Turabada_AI_10656': { - 'hash': 10656, - 'name': 'Turabada AI', - 'savables': { - 'LevelStatModifier': { - 'hash': 788405183, - 'name': 'LevelStatModifier' - } - } - }, - 'Turabada_Short_Trial_Variant_13756': { - 'hash': 13756, - 'name': 'Turabada Short Trial Variant', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Turabada_Short_Variant': { - 'hash': 63878, - 'name': 'Turabada Short Variant', - 'embedded': { - 'Arm_Collision_L_40528': { - 'hash': 40528, - 'name': 'Arm Collision L', - 'savables': {} - }, - 'Arm_Collision_R_42784': { - 'hash': 42784, - 'name': 'Arm Collision R', - 'savables': {} - }, - 'Explosion_58370': { - 'hash': 58370, - 'name': 'Explosion', - 'savables': {} - }, - 'Killed_Drops_63174': { - 'hash': 63174, - 'name': 'Killed Drops', - 'savables': {} - }, - 'Target_Collector_10522': { - 'hash': 10522, - 'name': 'Target Collector', - 'savables': {} - }, - 'Turabada_01_2540': { - 'hash': 2540, - 'name': 'Turabada_01', - 'savables': {} - }, - 'Turabada_AI_10656': { - 'hash': 10656, - 'name': 'Turabada AI', - 'savables': { - 'LevelStatModifier': { - 'hash': 788405183, - 'name': 'LevelStatModifier' - } - } - }, - 'Turabada_Short_Variant_13756': { - 'hash': 13756, - 'name': 'Turabada Short Variant', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Turabada_Silver_Destroy_Variant': { - 'hash': 1960, - 'name': 'Turabada Silver Destroy Variant', - 'embedded': { - 'Turabada_Silver_Destroy_Variant_37492': { - 'hash': 37492, - 'name': 'Turabada Silver Destroy Variant', - 'savables': {} - } - } - }, - 'Turabada_Silver_Trial_Variant': { - 'hash': 20844, - 'name': 'Turabada Silver Trial Variant', - 'embedded': { - 'Arm_Collision_L_40528': { - 'hash': 40528, - 'name': 'Arm Collision L', - 'savables': {} - }, - 'Arm_Collision_R_42784': { - 'hash': 42784, - 'name': 'Arm Collision R', - 'savables': {} - }, - 'Explosion_58370': { - 'hash': 58370, - 'name': 'Explosion', - 'savables': {} - }, - 'Killed_Drops_63174': { - 'hash': 63174, - 'name': 'Killed Drops', - 'savables': {} - }, - 'Target_Collector_10522': { - 'hash': 10522, - 'name': 'Target Collector', - 'savables': {} - }, - 'Turabada_01_2540': { - 'hash': 2540, - 'name': 'Turabada_01', - 'savables': {} - }, - 'Turabada_AI_10656': { - 'hash': 10656, - 'name': 'Turabada AI', - 'savables': { - 'LevelStatModifier': { - 'hash': 788405183, - 'name': 'LevelStatModifier' - } - } - }, - 'Turabada_Silver_Trial_Variant_13756': { - 'hash': 13756, - 'name': 'Turabada Silver Trial Variant', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Turabada_Silver_Variant': { - 'hash': 45716, - 'name': 'Turabada Silver Variant', - 'embedded': { - 'Arm_Collision_L_40528': { - 'hash': 40528, - 'name': 'Arm Collision L', - 'savables': {} - }, - 'Arm_Collision_R_42784': { - 'hash': 42784, - 'name': 'Arm Collision R', - 'savables': {} - }, - 'Explosion_58370': { - 'hash': 58370, - 'name': 'Explosion', - 'savables': {} - }, - 'Killed_Drops_63174': { - 'hash': 63174, - 'name': 'Killed Drops', - 'savables': {} - }, - 'Target_Collector_10522': { - 'hash': 10522, - 'name': 'Target Collector', - 'savables': {} - }, - 'Turabada_01_2540': { - 'hash': 2540, - 'name': 'Turabada_01', - 'savables': {} - }, - 'Turabada_AI_10656': { - 'hash': 10656, - 'name': 'Turabada AI', - 'savables': { - 'LevelStatModifier': { - 'hash': 788405183, - 'name': 'LevelStatModifier' - } - } - }, - 'Turabada_Silver_Variant_13756': { - 'hash': 13756, - 'name': 'Turabada Silver Variant', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Turabada_Spawner_Automatic': { - 'hash': 51652, - 'name': 'Turabada Spawner Automatic', - 'embedded': { - 'Turabada_Spawner_Automatic_26726': { - 'hash': 26726, - 'name': 'Turabada Spawner Automatic', - 'savables': {} - }, - 'caveRock_34072': { - 'hash': 34072, - 'name': 'caveRock', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Turabada_Spawner_Reactive': { - 'hash': 27188, - 'name': 'Turabada Spawner Reactive', - 'embedded': { - 'Reactive_AI_17314': { - 'hash': 17314, - 'name': 'Reactive AI', - 'savables': {} - }, - 'Turabada_Spawner_Reactive_26726': { - 'hash': 26726, - 'name': 'Turabada Spawner Reactive', - 'savables': {} - }, - 'caveRock_34072': { - 'hash': 34072, - 'name': 'caveRock', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Turabada_Trial_Variant': { - 'hash': 21882, - 'name': 'Turabada Trial Variant', - 'embedded': { - 'Arm_Collision_L_40528': { - 'hash': 40528, - 'name': 'Arm Collision L', - 'savables': {} - }, - 'Arm_Collision_R_42784': { - 'hash': 42784, - 'name': 'Arm Collision R', - 'savables': {} - }, - 'Explosion_58370': { - 'hash': 58370, - 'name': 'Explosion', - 'savables': {} - }, - 'Killed_Drops_63174': { - 'hash': 63174, - 'name': 'Killed Drops', - 'savables': {} - }, - 'Target_Collector_10522': { - 'hash': 10522, - 'name': 'Target Collector', - 'savables': {} - }, - 'Turabada_01_2540': { - 'hash': 2540, - 'name': 'Turabada_01', - 'savables': {} - }, - 'Turabada_AI_10656': { - 'hash': 10656, - 'name': 'Turabada AI', - 'savables': { - 'LevelStatModifier': { - 'hash': 788405183, - 'name': 'LevelStatModifier' - } - } - }, - 'Turabada_Trial_Variant_13756': { - 'hash': 13756, - 'name': 'Turabada Trial Variant', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'UnplacedMetalWallHook': { - 'hash': 18972, - 'name': 'UnplacedMetalWallHook', - 'embedded': { - 'Heat_Point_Collection_11020': { - 'hash': 11020, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'UnplacedMetalWallHook_26498': { - 'hash': 26498, - 'name': 'UnplacedMetalWallHook', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'RaycastCrafter': { - 'hash': 2815374842, - 'name': 'RaycastCrafter' - } - } - } - } - }, - 'VR_Player_Character_New': { - 'hash': 49582, - 'name': 'VR_Player_Character_New', - 'embedded': {} - }, - 'Vacuum': { - 'hash': 8586, - 'name': 'Vacuum', - 'embedded': { - 'Dock_42390': { - 'hash': 42390, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Vacuum_7480': { - 'hash': 7480, - 'name': 'Vacuum', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Vegetable_Ragu_Recipe_Burnt_Stew': { - 'hash': 58092, - 'name': 'Vegetable_Ragu_Recipe_Burnt_Stew', - 'embedded': {} - }, - 'Vegetable_Ragu_Recipe_Cooked_Stew': { - 'hash': 58074, - 'name': 'Vegetable_Ragu_Recipe_Cooked_Stew', - 'embedded': {} - }, - 'Vegetable_Ragu_Recipe_Raw_Stew': { - 'hash': 58050, - 'name': 'Vegetable_Ragu_Recipe_Raw_Stew', - 'embedded': {} - }, - 'Vine_Attack_Fern': { - 'hash': 24402, - 'name': 'Vine Attack Fern', - 'embedded': { - 'Death_Fern_AI_29794': { - 'hash': 29794, - 'name': 'Death Fern AI', - 'savables': {} - }, - 'Emit_Gas_Spawner_16984': { - 'hash': 16984, - 'name': 'Emit Gas Spawner', - 'savables': {} - }, - 'Erupt_Area_19858': { - 'hash': 19858, - 'name': 'Erupt Area', - 'savables': {} - }, - 'Impactor_63610': { - 'hash': 63610, - 'name': 'Impactor', - 'savables': {} - }, - 'Impactor_65072': { - 'hash': 65072, - 'name': 'Impactor', - 'savables': {} - }, - 'Impactor_65078': { - 'hash': 65078, - 'name': 'Impactor', - 'savables': {} - }, - 'Mesh_15308': { - 'hash': 15308, - 'name': 'Mesh', - 'savables': {} - }, - 'Vine_Attack_Fern_37626': { - 'hash': 37626, - 'name': 'Vine Attack Fern', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Vine_Boulder_01': { - 'hash': 31088, - 'name': 'Vine Boulder 01', - 'embedded': { - 'Directional_Encounter_63404': { - 'hash': 63404, - 'name': 'Directional Encounter', - 'savables': { - 'DirectionalBoundsSurface': { - 'hash': 1962842866, - 'name': 'DirectionalBoundsSurface' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - }, - 'Vine_Boulder_01_62528': { - 'hash': 62528, - 'name': 'Vine Boulder 01', - 'savables': {} - } - } - }, - 'Vision_Recipe_Burnt_Stew': { - 'hash': 58138, - 'name': 'Vision_Recipe_Burnt_Stew', - 'embedded': {} - }, - 'Vision_Recipe_Cooked_Stew': { - 'hash': 58120, - 'name': 'Vision_Recipe_Cooked_Stew', - 'embedded': {} - }, - 'Vision_Recipe_Raw_Stew': { - 'hash': 58162, - 'name': 'Vision_Recipe_Raw_Stew', - 'embedded': {} - }, - 'Wakizashi': { - 'hash': 29856, - 'name': 'Wakizashi', - 'embedded': { - 'Wakizashi_36330': { - 'hash': 36330, - 'name': 'Wakizashi', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'Enchantable': { - 'hash': 4134534481, - 'name': 'Enchantable' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Walk_Air': { - 'hash': 50936, - 'name': 'Walk_Air', - 'embedded': {} - }, - 'Wall_Shelf': { - 'hash': 15548, - 'name': 'Wall Shelf', - 'embedded': { - 'Dock_62060': { - 'hash': 62060, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62062': { - 'hash': 62062, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62064': { - 'hash': 62064, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_62066': { - 'hash': 62066, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Wall_Shelf_62464': { - 'hash': 62464, - 'name': 'Wall Shelf', - 'savables': {} - } - } - }, - 'Wall_Street_Post': { - 'hash': 50078, - 'name': 'Wall Street Post', - 'embedded': { - 'Sign_Body_13458': { - 'hash': 13458, - 'name': 'Sign Body', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Visual_1_44280': { - 'hash': 44280, - 'name': 'Visual 1', - 'savables': { - 'MeshPlacement': { - 'hash': 2169673426, - 'name': 'MeshPlacement' - } - } - }, - 'Visual_2_38710': { - 'hash': 38710, - 'name': 'Visual 2', - 'savables': { - 'MeshPlacement': { - 'hash': 2169673426, - 'name': 'MeshPlacement' - } - } - }, - 'Visual_3_23608': { - 'hash': 23608, - 'name': 'Visual 3', - 'savables': { - 'MeshPlacement': { - 'hash': 2169673426, - 'name': 'MeshPlacement' - } - } - }, - 'Visual_4_16452': { - 'hash': 16452, - 'name': 'Visual 4', - 'savables': { - 'MeshPlacement': { - 'hash': 2169673426, - 'name': 'MeshPlacement' - } - } - }, - 'Wall_Street_Post_16266': { - 'hash': 16266, - 'name': 'Wall Street Post', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - } - } - }, - 'Wall_Torch_Holder': { - 'hash': 3786, - 'name': 'Wall Torch Holder', - 'embedded': { - 'Torch_Dock_5626': { - 'hash': 5626, - 'name': 'Torch Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Wall_Torch_Holder_54416': { - 'hash': 54416, - 'name': 'Wall Torch Holder', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - } - } - }, - 'Wall_Torch_Holder_Puzzle': { - 'hash': 30196, - 'name': 'Wall Torch Holder Puzzle', - 'embedded': { - 'Extra_Logic_1_49636': { - 'hash': 49636, - 'name': 'Extra Logic 1', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - } - } - }, - 'Torch_Dock_5626': { - 'hash': 5626, - 'name': 'Torch Dock', - 'savables': { - 'LogicIntSender': { - 'hash': 2880587164, - 'name': 'LogicIntSender' - }, - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - }, - 'PlaceItemPuzzleLogic': { - 'hash': 1001395212, - 'name': 'PlaceItemPuzzleLogic' - } - } - }, - 'Wall_Torch_Holder_Puzzle_30194': { - 'hash': 30194, - 'name': 'Wall Torch Holder Puzzle', - 'savables': {} - } - } - }, - 'Walnut_Gotera_Bomb_Dart': { - 'hash': 39716, - 'name': 'Walnut Gotera Bomb Dart', - 'embedded': { - 'Dart_62940': { - 'hash': 62940, - 'name': 'Dart', - 'savables': {} - }, - 'Walnut_Gotera_Bomb_Dart_3092': { - 'hash': 3092, - 'name': 'Walnut Gotera Bomb Dart', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Walnut_Tree_Growth': { - 'hash': 48268, - 'name': 'Walnut Tree Growth', - 'embedded': { - 'Walnut_Tree_Growth_33458': { - 'hash': 33458, - 'name': 'Walnut Tree Growth', - 'savables': { - 'GrowerComponent': { - 'hash': 3402094521, - 'name': 'GrowerComponent' - } - } - } - } - }, - 'Walnut_Tree_Seed': { - 'hash': 44172, - 'name': 'Walnut Tree Seed', - 'embedded': { - 'Walnut_Tree_Seed_35258': { - 'hash': 35258, - 'name': 'Walnut Tree Seed', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'RaycastCrafter': { - 'hash': 2815374842, - 'name': 'RaycastCrafter' - } - } - } - } - }, - 'Walnut_Tree_Stage_1': { - 'hash': 26568, - 'name': 'Walnut Tree Stage 1', - 'embedded': { - 'Walnut_Tree_Stage_1_63514': { - 'hash': 63514, - 'name': 'Walnut Tree Stage 1', - 'savables': {} - } - } - }, - 'WarHammer': { - 'hash': 9630, - 'name': 'WarHammer', - 'embedded': { - 'Heat_Point_Collection_1720': { - 'hash': 1720, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Insert_HammerType_End_Cap_52192': { - 'hash': 52192, - 'name': 'Insert HammerType End Cap', - 'savables': {} - }, - 'WarHammer_42978': { - 'hash': 42978, - 'name': 'WarHammer', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Water_Well_Dynamic': { - 'hash': 14364, - 'name': 'Water_Well_Dynamic', - 'embedded': {} - }, - 'Water_Well_Tunnel_Dynamic': { - 'hash': 12356, - 'name': 'Water Well Tunnel Dynamic', - 'embedded': { - 'Dock_2780': { - 'hash': 2780, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60224': { - 'hash': 60224, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60226': { - 'hash': 60226, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60228': { - 'hash': 60228, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60234': { - 'hash': 60234, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60236': { - 'hash': 60236, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60238': { - 'hash': 60238, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60244': { - 'hash': 60244, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_60246': { - 'hash': 60246, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Water_Well_Tunnel_Dynamic_14816': { - 'hash': 14816, - 'name': 'Water Well Tunnel Dynamic', - 'savables': {} - } - } - }, - 'Weapon_Rack_Wall': { - 'hash': 13062, - 'name': 'Weapon Rack Wall', - 'embedded': { - 'ToolDock_(1)_26316': { - 'hash': 26316, - 'name': 'ToolDock (1)', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'ToolDock_(2)_26308': { - 'hash': 26308, - 'name': 'ToolDock (2)', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'ToolDock_(3)_26304': { - 'hash': 26304, - 'name': 'ToolDock (3)', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'ToolDock_5626': { - 'hash': 5626, - 'name': 'ToolDock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Weapon_Rack_Wall_9260': { - 'hash': 9260, - 'name': 'Weapon Rack Wall', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - } - } - }, - 'Wedge_Training': { - 'hash': 53570, - 'name': 'Wedge Training', - 'embedded': { - 'Wedge_Training_53566': { - 'hash': 53566, - 'name': 'Wedge Training', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - } - } - }, - 'Weight_Gauge': { - 'hash': 48306, - 'name': 'Weight Gauge', - 'embedded': { - 'Weight_Gauge_48288': { - 'hash': 48288, - 'name': 'Weight Gauge', - 'savables': {} - } - } - }, - 'WheelBridge': { - 'hash': 7252, - 'name': 'WheelBridge', - 'embedded': { - 'Grip_(1)_54050': { - 'hash': 54050, - 'name': 'Grip (1)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(2)_54614': { - 'hash': 54614, - 'name': 'Grip (2)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(3)_56370': { - 'hash': 56370, - 'name': 'Grip (3)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(4)_53470': { - 'hash': 53470, - 'name': 'Grip (4)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(5)_19654': { - 'hash': 19654, - 'name': 'Grip (5)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_56728': { - 'hash': 56728, - 'name': 'Grip', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'WheelBridge_43884': { - 'hash': 43884, - 'name': 'WheelBridge', - 'savables': { - 'LogicFloatReceiver': { - 'hash': 3188272159, - 'name': 'LogicFloatReceiver' - }, - 'LogicFloatSender': { - 'hash': 2120963769, - 'name': 'LogicFloatSender' - }, - 'RotatePickup': { - 'hash': 2498617949, - 'name': 'RotatePickup' - } - } - }, - 'wheel_origin_43868': { - 'hash': 43868, - 'name': 'wheel_origin', - 'savables': { - 'WheelGrab': { - 'hash': 320224849, - 'name': 'WheelGrab' - } - } - } - } - }, - 'WheelPuzzle': { - 'hash': 52364, - 'name': 'WheelPuzzle', - 'embedded': { - 'Grip_(1)_54050': { - 'hash': 54050, - 'name': 'Grip (1)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(2)_54614': { - 'hash': 54614, - 'name': 'Grip (2)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(3)_56370': { - 'hash': 56370, - 'name': 'Grip (3)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(4)_53470': { - 'hash': 53470, - 'name': 'Grip (4)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_(5)_19654': { - 'hash': 19654, - 'name': 'Grip (5)', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Grip_56728': { - 'hash': 56728, - 'name': 'Grip', - 'savables': { - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'WheelPuzzle_43884': { - 'hash': 43884, - 'name': 'WheelPuzzle', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'LogicFloatReceiver': { - 'hash': 3188272159, - 'name': 'LogicFloatReceiver' - }, - 'LogicFloatSender': { - 'hash': 2120963769, - 'name': 'LogicFloatSender' - }, - 'RotatePickup': { - 'hash': 2498617949, - 'name': 'RotatePickup' - } - } - }, - 'wheel_origin_43868': { - 'hash': 43868, - 'name': 'wheel_origin', - 'savables': { - 'WheelGrab': { - 'hash': 320224849, - 'name': 'WheelGrab' - } - } - } - } - }, - 'WheelPuzzleOLD': { - 'hash': 61964, - 'name': 'WheelPuzzleOLD', - 'embedded': {} - }, - 'White_Gold_Ingot': { - 'hash': 13158, - 'name': 'White Gold Ingot', - 'embedded': { - 'Heat_Point_Collection_13798': { - 'hash': 13798, - 'name': 'Heat Point Collection', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'White_Gold_Ingot_32738': { - 'hash': 32738, - 'name': 'White Gold Ingot', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Woodcut_Ash_LeafClump_Base': { - 'hash': 28312, - 'name': 'Woodcut Ash LeafClump Base', - 'embedded': { - 'Woodcut_Ash_LeafClump_Base_28328': { - 'hash': 28328, - 'name': 'Woodcut Ash LeafClump Base', - 'savables': {} - } - } - }, - 'Woodcut_Ash_LeafClump_C1C1': { - 'hash': 44892, - 'name': 'Woodcut Ash LeafClump C1C1', - 'embedded': { - 'Woodcut_Ash_LeafClump_C1C1_44890': { - 'hash': 44890, - 'name': 'Woodcut Ash LeafClump C1C1', - 'savables': {} - } - } - }, - 'Woodcut_Ash_LeafClump_C1C2': { - 'hash': 34638, - 'name': 'Woodcut Ash LeafClump C1C2', - 'embedded': { - 'Woodcut_Ash_LeafClump_C1C2_34636': { - 'hash': 34636, - 'name': 'Woodcut Ash LeafClump C1C2', - 'savables': {} - } - } - }, - 'Woodcut_Ash_LeafClump_C1C2_E': { - 'hash': 47502, - 'name': 'Woodcut Ash LeafClump C1C2 E', - 'embedded': { - 'Woodcut_Ash_LeafClump_C1C2_E_47500': { - 'hash': 47500, - 'name': 'Woodcut Ash LeafClump C1C2 E', - 'savables': {} - } - } - }, - 'Woodcut_Ash_LeafClump_C1_E': { - 'hash': 47458, - 'name': 'Woodcut Ash LeafClump C1 E', - 'embedded': { - 'Woodcut_Ash_LeafClump_C1_E_47456': { - 'hash': 47456, - 'name': 'Woodcut Ash LeafClump C1 E', - 'savables': {} - } - } - }, - 'Woodcut_Ash_LeafClump_C1_E_1': { - 'hash': 14074, - 'name': 'Woodcut Ash LeafClump C1 E 1', - 'embedded': { - 'Woodcut_Ash_LeafClump_C1_E_1_14072': { - 'hash': 14072, - 'name': 'Woodcut Ash LeafClump C1 E 1', - 'savables': {} - } - } - }, - 'Woodcut_Ash_LeafClump_C1_E_2': { - 'hash': 40722, - 'name': 'Woodcut Ash LeafClump C1 E 2', - 'embedded': { - 'Woodcut_Ash_LeafClump_C1_E_2_40720': { - 'hash': 40720, - 'name': 'Woodcut Ash LeafClump C1 E 2', - 'savables': {} - } - } - }, - 'Woodcut_Ash_LeafClump_C2C2': { - 'hash': 44908, - 'name': 'Woodcut Ash LeafClump C2C2', - 'embedded': { - 'Woodcut_Ash_LeafClump_C2C2_44906': { - 'hash': 44906, - 'name': 'Woodcut Ash LeafClump C2C2', - 'savables': {} - } - } - }, - 'Woodcut_Ash_LeafClump_C2C3': { - 'hash': 9426, - 'name': 'Woodcut Ash LeafClump C2C3', - 'embedded': { - 'Woodcut_Ash_LeafClump_C2C3_9424': { - 'hash': 9424, - 'name': 'Woodcut Ash LeafClump C2C3', - 'savables': {} - } - } - }, - 'Woodcut_Ash_LeafClump_C2C3_E': { - 'hash': 57802, - 'name': 'Woodcut Ash LeafClump C2C3 E', - 'embedded': { - 'Woodcut_Ash_LeafClump_C2C3_E_57800': { - 'hash': 57800, - 'name': 'Woodcut Ash LeafClump C2C3 E', - 'savables': {} - } - } - }, - 'Woodcut_Ash_LeafClump_C2_E': { - 'hash': 29976, - 'name': 'Woodcut Ash LeafClump C2 E', - 'embedded': { - 'Woodcut_Ash_LeafClump_C2_E_29974': { - 'hash': 29974, - 'name': 'Woodcut Ash LeafClump C2 E', - 'savables': {} - } - } - }, - 'Woodcut_Ash_LeafClump_C2_E_1': { - 'hash': 24422, - 'name': 'Woodcut Ash LeafClump C2 E 1', - 'embedded': { - 'Woodcut_Ash_LeafClump_C2_E_1_24420': { - 'hash': 24420, - 'name': 'Woodcut Ash LeafClump C2 E 1', - 'savables': {} - } - } - }, - 'Woodcut_Ash_LeafClump_C3C3': { - 'hash': 10682, - 'name': 'Woodcut Ash LeafClump C3C3', - 'embedded': { - 'Woodcut_Ash_LeafClump_C3C3_10680': { - 'hash': 10680, - 'name': 'Woodcut Ash LeafClump C3C3', - 'savables': {} - } - } - }, - 'Woodcut_Ash_LeafClump_C3_E': { - 'hash': 57250, - 'name': 'Woodcut Ash LeafClump C3 E', - 'embedded': { - 'Woodcut_Ash_LeafClump_C3_E_57248': { - 'hash': 57248, - 'name': 'Woodcut Ash LeafClump C3 E', - 'savables': {} - } - } - }, - 'Woodcut_Ash_Seed_Spawner_Attachment': { - 'hash': 16054, - 'name': 'Woodcut Ash Seed Spawner Attachment', - 'embedded': { - 'Woodcut_Ash_Seed_Spawner_Attachment_36402': { - 'hash': 36402, - 'name': 'Woodcut Ash Seed Spawner Attachment', - 'savables': {} - } - } - }, - 'Woodcut_B0_B0': { - 'hash': 11470, - 'name': 'Woodcut_B0_B0', - 'embedded': { - 'Top_8056': { - 'hash': 8056, - 'name': 'Top_8056', - 'savables': {} - } - } - }, - 'Woodcut_B0_B0_S-30': { - 'hash': 19224, - 'name': 'Woodcut B0 B0 S-30', - 'embedded': { - 'Stick_53710': { - 'hash': 53710, - 'name': 'Stick', - 'savables': {} - }, - 'Top_53706': { - 'hash': 53706, - 'name': 'Top', - 'savables': {} - }, - 'Woodcut_B0_B0_S-30_35608': { - 'hash': 35608, - 'name': 'Woodcut B0 B0 S-30', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_B0_B0_S15': { - 'hash': 35014, - 'name': 'Woodcut_B0_B0_S15', - 'embedded': { - 'Top_53706': { - 'hash': 53706, - 'name': 'Top_53706', - 'savables': {} - }, - 'Stick_53710': { - 'hash': 53710, - 'name': 'Stick_53710', - 'savables': {} - } - } - }, - 'Woodcut_B0_B0_S30': { - 'hash': 36844, - 'name': 'Woodcut B0 B0 S30', - 'embedded': { - 'Stick_53710': { - 'hash': 53710, - 'name': 'Stick', - 'savables': {} - }, - 'Top_53706': { - 'hash': 53706, - 'name': 'Top', - 'savables': {} - }, - 'Woodcut_B0_B0_S30_35608': { - 'hash': 35608, - 'name': 'Woodcut B0 B0 S30', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_B0_B0_S30_S30': { - 'hash': 6224, - 'name': 'Woodcut B0 B0 S30 S30', - 'embedded': { - 'Branch_1_20342': { - 'hash': 20342, - 'name': 'Branch 1', - 'savables': {} - }, - 'Stick_1_20338': { - 'hash': 20338, - 'name': 'Stick 1', - 'savables': {} - }, - 'Stick_2_55820': { - 'hash': 55820, - 'name': 'Stick 2', - 'savables': {} - }, - 'Woodcut_B0_B0_S30_S30_6218': { - 'hash': 6218, - 'name': 'Woodcut B0 B0 S30 S30', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_B0_B15_B30': { - 'hash': 35020, - 'name': 'Woodcut_B0_B15_B30', - 'embedded': { - 'Branch_1_20342': { - 'hash': 20342, - 'name': 'Branch_1_20342', - 'savables': {} - }, - 'Branch_2_20338': { - 'hash': 20338, - 'name': 'Branch_2_20338', - 'savables': {} - } - } - }, - 'Woodcut_B0_B30_S30': { - 'hash': 51486, - 'name': 'Woodcut B0 B30 S30', - 'embedded': { - 'Stick_51478': { - 'hash': 51478, - 'name': 'Stick', - 'savables': {} - }, - 'Top_51476': { - 'hash': 51476, - 'name': 'Top', - 'savables': {} - }, - 'Woodcut_B0_B30_S30_51474': { - 'hash': 51474, - 'name': 'Woodcut B0 B30 S30', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_B0_E': { - 'hash': 29444, - 'name': 'Woodcut_B0_E', - 'embedded': {} - }, - 'Woodcut_B0_S0_S30': { - 'hash': 35028, - 'name': 'Woodcut_B0_S0_S30', - 'embedded': { - 'Stick_1_38940': { - 'hash': 38940, - 'name': 'Stick_1_38940', - 'savables': {} - }, - 'Stick_2_38936': { - 'hash': 38936, - 'name': 'Stick_2_38936', - 'savables': {} - } - } - }, - 'Woodcut_B0_S0_S60': { - 'hash': 8102, - 'name': 'Woodcut B0 S0 S60', - 'embedded': { - 'Stick_1_38940': { - 'hash': 38940, - 'name': 'Stick 1', - 'savables': {} - }, - 'Stick_2_38936': { - 'hash': 38936, - 'name': 'Stick 2', - 'savables': {} - }, - 'Woodcut_B0_S0_S60_35622': { - 'hash': 35622, - 'name': 'Woodcut B0 S0 S60', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_B0_S30_S30': { - 'hash': 54764, - 'name': 'Woodcut B0 S30 S30', - 'embedded': { - 'Stick_1_38940': { - 'hash': 38940, - 'name': 'Stick 1', - 'savables': {} - }, - 'Stick_2_38936': { - 'hash': 38936, - 'name': 'Stick 2', - 'savables': {} - }, - 'Woodcut_B0_S30_S30_35622': { - 'hash': 35622, - 'name': 'Woodcut B0 S30 S30', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_B15_B15': { - 'hash': 38016, - 'name': 'Woodcut_B15_B15', - 'embedded': { - 'Top_4690': { - 'hash': 4690, - 'name': 'Top_4690', - 'savables': {} - } - } - }, - 'Woodcut_B30_B30': { - 'hash': 62548, - 'name': 'Woodcut_B30_B30', - 'embedded': { - 'Top_58002': { - 'hash': 58002, - 'name': 'Top_58002', - 'savables': {} - } - } - }, - 'Woodcut_B5_B5': { - 'hash': 1780, - 'name': 'Woodcut_B5_B5', - 'embedded': { - 'Top_37822': { - 'hash': 37822, - 'name': 'Top_37822', - 'savables': {} - } - } - }, - 'Woodcut_Birch_LeafClump_Base': { - 'hash': 37794, - 'name': 'Woodcut Birch LeafClump Base', - 'embedded': { - 'Woodcut_Birch_LeafClump_Base_36402': { - 'hash': 36402, - 'name': 'Woodcut Birch LeafClump Base', - 'savables': {} - } - } - }, - 'Woodcut_Birch_LeafClump_C1C1_1': { - 'hash': 1178, - 'name': 'Woodcut Birch LeafClump C1C1 1', - 'embedded': { - 'Woodcut_Birch_LeafClump_C1C1_1_1176': { - 'hash': 1176, - 'name': 'Woodcut Birch LeafClump C1C1 1', - 'savables': {} - } - } - }, - 'Woodcut_Birch_LeafClump_C1C1_1_E': { - 'hash': 7260, - 'name': 'Woodcut Birch LeafClump C1C1 1 E', - 'embedded': { - 'Woodcut_Birch_LeafClump_C1C1_1_E_7258': { - 'hash': 7258, - 'name': 'Woodcut Birch LeafClump C1C1 1 E', - 'savables': {} - } - } - }, - 'Woodcut_Birch_LeafClump_C1C1_2': { - 'hash': 42598, - 'name': 'Woodcut Birch LeafClump C1C1 2', - 'embedded': { - 'Woodcut_Birch_LeafClump_C1C1_2_42596': { - 'hash': 42596, - 'name': 'Woodcut Birch LeafClump C1C1 2', - 'savables': {} - } - } - }, - 'Woodcut_Birch_LeafClump_C1C1_2_E': { - 'hash': 10700, - 'name': 'Woodcut Birch LeafClump C1C1 2 E', - 'embedded': { - 'Woodcut_Birch_LeafClump_C1C1_2_E_10698': { - 'hash': 10698, - 'name': 'Woodcut Birch LeafClump C1C1 2 E', - 'savables': {} - } - } - }, - 'Woodcut_Birch_LeafClump_C1C2_1': { - 'hash': 54804, - 'name': 'Woodcut Birch LeafClump C1C2 1', - 'embedded': { - 'Woodcut_Birch_LeafClump_C1C2_1_54802': { - 'hash': 54802, - 'name': 'Woodcut Birch LeafClump C1C2 1', - 'savables': {} - } - } - }, - 'Woodcut_Birch_LeafClump_C1C2_1_E': { - 'hash': 2760, - 'name': 'Woodcut Birch LeafClump C1C2 1 E', - 'embedded': { - 'Woodcut_Birch_LeafClump_C1C2_1_E_2758': { - 'hash': 2758, - 'name': 'Woodcut Birch LeafClump C1C2 1 E', - 'savables': {} - } - } - }, - 'Woodcut_Birch_LeafClump_C1C2_2': { - 'hash': 12688, - 'name': 'Woodcut Birch LeafClump C1C2 2', - 'embedded': { - 'Woodcut_Birch_LeafClump_C1C2_2_12686': { - 'hash': 12686, - 'name': 'Woodcut Birch LeafClump C1C2 2', - 'savables': {} - } - } - }, - 'Woodcut_Birch_LeafClump_C1C2_2_E': { - 'hash': 54174, - 'name': 'Woodcut Birch LeafClump C1C2 2 E', - 'embedded': { - 'Woodcut_Birch_LeafClump_C1C2_2_E_54172': { - 'hash': 54172, - 'name': 'Woodcut Birch LeafClump C1C2 2 E', - 'savables': {} - } - } - }, - 'Woodcut_Birch_LeafClump_C1_E': { - 'hash': 55364, - 'name': 'Woodcut Birch LeafClump C1 E', - 'embedded': { - 'Woodcut_Birch_LeafClump_C1_E_55362': { - 'hash': 55362, - 'name': 'Woodcut Birch LeafClump C1 E', - 'savables': {} - } - } - }, - 'Woodcut_Birch_LeafClump_C2C3_1': { - 'hash': 54092, - 'name': 'Woodcut Birch LeafClump C2C3 1', - 'embedded': { - 'Woodcut_Birch_LeafClump_C2C3_1_54090': { - 'hash': 54090, - 'name': 'Woodcut Birch LeafClump C2C3 1', - 'savables': {} - } - } - }, - 'Woodcut_Birch_LeafClump_C2C3_1_E': { - 'hash': 2568, - 'name': 'Woodcut Birch LeafClump C2C3 1 E', - 'embedded': { - 'Woodcut_Birch_LeafClump_C2C3_1_E_2566': { - 'hash': 2566, - 'name': 'Woodcut Birch LeafClump C2C3 1 E', - 'savables': {} - } - } - }, - 'Woodcut_Birch_LeafClump_C2C3_2': { - 'hash': 54852, - 'name': 'Woodcut Birch LeafClump C2C3 2', - 'embedded': { - 'Woodcut_Birch_LeafClump_C2C3_2_54850': { - 'hash': 54850, - 'name': 'Woodcut Birch LeafClump C2C3 2', - 'savables': {} - } - } - }, - 'Woodcut_Birch_LeafClump_C2C3_2_E': { - 'hash': 54108, - 'name': 'Woodcut Birch LeafClump C2C3 2 E', - 'embedded': { - 'Woodcut_Birch_LeafClump_C2C3_2_E_54106': { - 'hash': 54106, - 'name': 'Woodcut Birch LeafClump C2C3 2 E', - 'savables': {} - } - } - }, - 'Woodcut_Birch_LeafClump_C2_E': { - 'hash': 12672, - 'name': 'Woodcut Birch LeafClump C2 E', - 'embedded': { - 'Woodcut_Birch_LeafClump_C2_E_12670': { - 'hash': 12670, - 'name': 'Woodcut Birch LeafClump C2 E', - 'savables': {} - } - } - }, - 'Woodcut_Birch_LeafClump_C3C4_1': { - 'hash': 7276, - 'name': 'Woodcut Birch LeafClump C3C4 1', - 'embedded': { - 'Woodcut_Birch_LeafClump_C3C4_1_7274': { - 'hash': 7274, - 'name': 'Woodcut Birch LeafClump C3C4 1', - 'savables': {} - } - } - }, - 'Woodcut_Birch_LeafClump_C3C4_1_E': { - 'hash': 34602, - 'name': 'Woodcut Birch LeafClump C3C4 1 E', - 'embedded': { - 'Woodcut_Birch_LeafClump_C3C4_1_E_34600': { - 'hash': 34600, - 'name': 'Woodcut Birch LeafClump C3C4 1 E', - 'savables': {} - } - } - }, - 'Woodcut_Birch_LeafClump_C3C4_2': { - 'hash': 12182, - 'name': 'Woodcut Birch LeafClump C3C4 2', - 'embedded': { - 'Woodcut_Birch_LeafClump_C3C4_2_12180': { - 'hash': 12180, - 'name': 'Woodcut Birch LeafClump C3C4 2', - 'savables': {} - } - } - }, - 'Woodcut_Birch_LeafClump_C3C4_2_E': { - 'hash': 11234, - 'name': 'Woodcut Birch LeafClump C3C4 2 E', - 'embedded': { - 'Woodcut_Birch_LeafClump_C3C4_2_E_11232': { - 'hash': 11232, - 'name': 'Woodcut Birch LeafClump C3C4 2 E', - 'savables': {} - } - } - }, - 'Woodcut_Birch_LeafClump_C3_E': { - 'hash': 54820, - 'name': 'Woodcut Birch LeafClump C3 E', - 'embedded': { - 'Woodcut_Birch_LeafClump_C3_E_54818': { - 'hash': 54818, - 'name': 'Woodcut Birch LeafClump C3 E', - 'savables': {} - } - } - }, - 'Woodcut_Birch_LeafClump_C4_E': { - 'hash': 44404, - 'name': 'Woodcut Birch LeafClump C4 E', - 'embedded': { - 'Woodcut_Birch_LeafClump_C4_E_44402': { - 'hash': 44402, - 'name': 'Woodcut Birch LeafClump C4 E', - 'savables': {} - } - } - }, - 'Woodcut_Birch_Seed_Spawner_Attachment': { - 'hash': 16026, - 'name': 'Woodcut Birch Seed Spawner Attachment', - 'embedded': { - 'Woodcut_Birch_Seed_Spawner_Attachment_36402': { - 'hash': 36402, - 'name': 'Woodcut Birch Seed Spawner Attachment', - 'savables': {} - } - } - }, - 'Woodcut_BranchRoot_V1_B0': { - 'hash': 8158, - 'name': 'Woodcut_BranchRoot_V1_B0', - 'embedded': { - 'Top_14282': { - 'hash': 14282, - 'name': 'Top_14282', - 'savables': {} - } - } - }, - 'Woodcut_BranchRoot_V1_B15_S30': { - 'hash': 22660, - 'name': 'Woodcut_BranchRoot_V1_B15_S30', - 'embedded': { - 'Top_63620': { - 'hash': 63620, - 'name': 'Top_63620', - 'savables': {} - }, - 'Branch_63622': { - 'hash': 63622, - 'name': 'Branch_63622', - 'savables': {} - } - } - }, - 'Woodcut_BranchRoot_V2_B0': { - 'hash': 50658, - 'name': 'Woodcut BranchRoot V2 B0', - 'embedded': { - 'Top_14282': { - 'hash': 14282, - 'name': 'Top', - 'savables': {} - }, - 'Woodcut_BranchRoot_V2_B0_10678': { - 'hash': 10678, - 'name': 'Woodcut BranchRoot V2 B0', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_Leaves_V1_L_F': { - 'hash': 42932, - 'name': 'Woodcut_Leaves_V1_L_F', - 'embedded': {} - }, - 'Woodcut_Leaves_V1_L_S': { - 'hash': 42928, - 'name': 'Woodcut_Leaves_V1_L_S', - 'embedded': {} - }, - 'Woodcut_Leaves_V1_S_F': { - 'hash': 42934, - 'name': 'Woodcut_Leaves_V1_S_F', - 'embedded': {} - }, - 'Woodcut_Leaves_V1_S_S': { - 'hash': 42930, - 'name': 'Woodcut_Leaves_V1_S_S', - 'embedded': {} - }, - 'Woodcut_Leaves_V2_D': { - 'hash': 63786, - 'name': 'Woodcut_Leaves_V2_D', - 'embedded': {} - }, - 'Woodcut_Leaves_V2_L': { - 'hash': 63466, - 'name': 'Woodcut_Leaves_V2_L', - 'embedded': {} - }, - 'Woodcut_Leaves_V2_Topper': { - 'hash': 26276, - 'name': 'Woodcut_Leaves_V2_Topper', - 'embedded': {} - }, - 'Woodcut_Oak_LeafClump_Base': { - 'hash': 60158, - 'name': 'Woodcut Oak LeafClump Base', - 'embedded': { - 'Woodcut_Oak_LeafClump_Base_36402': { - 'hash': 36402, - 'name': 'Woodcut Oak LeafClump Base', - 'savables': {} - } - } - }, - 'Woodcut_Oak_LeafClump_C1C1_1': { - 'hash': 38364, - 'name': 'Woodcut Oak LeafClump C1C1 1', - 'embedded': { - 'Woodcut_Oak_LeafClump_C1C1_1_38362': { - 'hash': 38362, - 'name': 'Woodcut Oak LeafClump C1C1 1', - 'savables': {} - } - } - }, - 'Woodcut_Oak_LeafClump_C1C1_2': { - 'hash': 38344, - 'name': 'Woodcut Oak LeafClump C1C1 2', - 'embedded': { - 'Woodcut_Oak_LeafClump_C1C1_2_38342': { - 'hash': 38342, - 'name': 'Woodcut Oak LeafClump C1C1 2', - 'savables': {} - } - } - }, - 'Woodcut_Oak_LeafClump_C1C2_1': { - 'hash': 38324, - 'name': 'Woodcut Oak LeafClump C1C2 1', - 'embedded': { - 'Woodcut_Oak_LeafClump_C1C2_1_38322': { - 'hash': 38322, - 'name': 'Woodcut Oak LeafClump C1C2 1', - 'savables': {} - } - } - }, - 'Woodcut_Oak_LeafClump_C1C2_2': { - 'hash': 38304, - 'name': 'Woodcut Oak LeafClump C1C2 2', - 'embedded': { - 'Woodcut_Oak_LeafClump_C1C2_2_38302': { - 'hash': 38302, - 'name': 'Woodcut Oak LeafClump C1C2 2', - 'savables': {} - } - } - }, - 'Woodcut_Oak_LeafClump_C1C2_E': { - 'hash': 38284, - 'name': 'Woodcut Oak LeafClump C1C2 E', - 'embedded': { - 'Woodcut_Oak_LeafClump_C1C2_E_38282': { - 'hash': 38282, - 'name': 'Woodcut Oak LeafClump C1C2 E', - 'savables': {} - } - } - }, - 'Woodcut_Oak_LeafClump_C1_E': { - 'hash': 38382, - 'name': 'Woodcut Oak LeafClump C1 E', - 'embedded': { - 'Woodcut_Oak_LeafClump_C1_E_38380': { - 'hash': 38380, - 'name': 'Woodcut Oak LeafClump C1 E', - 'savables': {} - } - } - }, - 'Woodcut_Oak_LeafClump_C2C2_1': { - 'hash': 38242, - 'name': 'Woodcut Oak LeafClump C2C2 1', - 'embedded': { - 'Woodcut_Oak_LeafClump_C2C2_1_38240': { - 'hash': 38240, - 'name': 'Woodcut Oak LeafClump C2C2 1', - 'savables': {} - } - } - }, - 'Woodcut_Oak_LeafClump_C2C2_2': { - 'hash': 38224, - 'name': 'Woodcut Oak LeafClump C2C2 2', - 'embedded': { - 'Woodcut_Oak_LeafClump_C2C2_2_38222': { - 'hash': 38222, - 'name': 'Woodcut Oak LeafClump C2C2 2', - 'savables': {} - } - } - }, - 'Woodcut_Oak_LeafClump_C2C3_1': { - 'hash': 38204, - 'name': 'Woodcut Oak LeafClump C2C3 1', - 'embedded': { - 'Woodcut_Oak_LeafClump_C2C3_1_38202': { - 'hash': 38202, - 'name': 'Woodcut Oak LeafClump C2C3 1', - 'savables': {} - } - } - }, - 'Woodcut_Oak_LeafClump_C2C3_2': { - 'hash': 38184, - 'name': 'Woodcut Oak LeafClump C2C3 2', - 'embedded': { - 'Woodcut_Oak_LeafClump_C2C3_2_38182': { - 'hash': 38182, - 'name': 'Woodcut Oak LeafClump C2C3 2', - 'savables': {} - } - } - }, - 'Woodcut_Oak_LeafClump_C2C3_E': { - 'hash': 38162, - 'name': 'Woodcut Oak LeafClump C2C3 E', - 'embedded': { - 'Woodcut_Oak_LeafClump_C2C3_E_38160': { - 'hash': 38160, - 'name': 'Woodcut Oak LeafClump C2C3 E', - 'savables': {} - } - } - }, - 'Woodcut_Oak_LeafClump_C2_E': { - 'hash': 38264, - 'name': 'Woodcut Oak LeafClump C2 E', - 'embedded': { - 'Woodcut_Oak_LeafClump_C2_E_38262': { - 'hash': 38262, - 'name': 'Woodcut Oak LeafClump C2 E', - 'savables': {} - } - } - }, - 'Woodcut_Oak_LeafClump_C3C3_1': { - 'hash': 38122, - 'name': 'Woodcut Oak LeafClump C3C3 1', - 'embedded': { - 'Woodcut_Oak_LeafClump_C3C3_1_38120': { - 'hash': 38120, - 'name': 'Woodcut Oak LeafClump C3C3 1', - 'savables': {} - } - } - }, - 'Woodcut_Oak_LeafClump_C3C3_2': { - 'hash': 38102, - 'name': 'Woodcut Oak LeafClump C3C3 2', - 'embedded': { - 'Woodcut_Oak_LeafClump_C3C3_2_38100': { - 'hash': 38100, - 'name': 'Woodcut Oak LeafClump C3C3 2', - 'savables': {} - } - } - }, - 'Woodcut_Oak_LeafClump_C3_E': { - 'hash': 38144, - 'name': 'Woodcut Oak LeafClump C3 E', - 'embedded': { - 'Woodcut_Oak_LeafClump_C3_E_38142': { - 'hash': 38142, - 'name': 'Woodcut Oak LeafClump C3 E', - 'savables': {} - } - } - }, - 'Woodcut_Oak_Seed_Spawner_Attachment': { - 'hash': 49710, - 'name': 'Woodcut Oak Seed Spawner Attachment', - 'embedded': { - 'Woodcut_Oak_Seed_Spawner_Attachment_36402': { - 'hash': 36402, - 'name': 'Woodcut Oak Seed Spawner Attachment', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafClump_Base': { - 'hash': 55152, - 'name': 'Woodcut Redwood LeafClump Base', - 'embedded': { - 'Woodcut_Redwood_LeafClump_Base_55166': { - 'hash': 55166, - 'name': 'Woodcut Redwood LeafClump Base', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafClump_T1_D30_C1C2': { - 'hash': 21374, - 'name': 'Woodcut Redwood LeafClump T1 D30 C1C2', - 'embedded': { - 'Woodcut_Redwood_LeafClump_T1_D30_C1C2_21372': { - 'hash': 21372, - 'name': 'Woodcut Redwood LeafClump T1 D30 C1C2', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafClump_T1_D30_C3C4': { - 'hash': 49074, - 'name': 'Woodcut Redwood LeafClump T1 D30 C3C4', - 'embedded': { - 'Woodcut_Redwood_LeafClump_T1_D30_C3C4_49072': { - 'hash': 49072, - 'name': 'Woodcut Redwood LeafClump T1 D30 C3C4', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafClump_T1_D30_C5C6': { - 'hash': 55378, - 'name': 'Woodcut Redwood LeafClump T1 D30 C5C6', - 'embedded': { - 'Woodcut_Redwood_LeafClump_T1_D30_C5C6_55376': { - 'hash': 55376, - 'name': 'Woodcut Redwood LeafClump T1 D30 C5C6', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafClump_T1_D30_C7C8': { - 'hash': 47486, - 'name': 'Woodcut Redwood LeafClump T1 D30 C7C8', - 'embedded': { - 'Woodcut_Redwood_LeafClump_T1_D30_C7C8_47484': { - 'hash': 47484, - 'name': 'Woodcut Redwood LeafClump T1 D30 C7C8', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafClump_T2_D30_C1C2': { - 'hash': 55954, - 'name': 'Woodcut Redwood LeafClump T2 D30 C1C2', - 'embedded': { - 'Woodcut_Redwood_LeafClump_T2_D30_C1C2_55952': { - 'hash': 55952, - 'name': 'Woodcut Redwood LeafClump T2 D30 C1C2', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafClump_T2_D30_C3C4': { - 'hash': 57266, - 'name': 'Woodcut Redwood LeafClump T2 D30 C3C4', - 'embedded': { - 'Woodcut_Redwood_LeafClump_T2_D30_C3C4_57264': { - 'hash': 57264, - 'name': 'Woodcut Redwood LeafClump T2 D30 C3C4', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafClump_T2_D30_C5C6': { - 'hash': 1528, - 'name': 'Woodcut Redwood LeafClump T2 D30 C5C6', - 'embedded': { - 'Woodcut_Redwood_LeafClump_T2_D30_C5C6_1526': { - 'hash': 1526, - 'name': 'Woodcut Redwood LeafClump T2 D30 C5C6', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafClump_T2_D30_C7C8': { - 'hash': 9410, - 'name': 'Woodcut Redwood LeafClump T2 D30 C7C8', - 'embedded': { - 'Woodcut_Redwood_LeafClump_T2_D30_C7C8_9408': { - 'hash': 9408, - 'name': 'Woodcut Redwood LeafClump T2 D30 C7C8', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafClump_T3_D30_C1C2': { - 'hash': 10666, - 'name': 'Woodcut Redwood LeafClump T3 D30 C1C2', - 'embedded': { - 'Woodcut_Redwood_LeafClump_T3_D30_C1C2_10664': { - 'hash': 10664, - 'name': 'Woodcut Redwood LeafClump T3 D30 C1C2', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafClump_T3_D30_C3C4': { - 'hash': 6716, - 'name': 'Woodcut Redwood LeafClump T3 D30 C3C4', - 'embedded': { - 'Woodcut_Redwood_LeafClump_T3_D30_C3C4_6714': { - 'hash': 6714, - 'name': 'Woodcut Redwood LeafClump T3 D30 C3C4', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafClump_T3_D30_C5C6': { - 'hash': 55520, - 'name': 'Woodcut Redwood LeafClump T3 D30 C5C6', - 'embedded': { - 'Woodcut_Redwood_LeafClump_T3_D30_C5C6_55518': { - 'hash': 55518, - 'name': 'Woodcut Redwood LeafClump T3 D30 C5C6', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafClump_T3_D30_C7C8': { - 'hash': 6732, - 'name': 'Woodcut Redwood LeafClump T3 D30 C7C8', - 'embedded': { - 'Woodcut_Redwood_LeafClump_T3_D30_C7C8_6730': { - 'hash': 6730, - 'name': 'Woodcut Redwood LeafClump T3 D30 C7C8', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafClump_T4_D30_C1': { - 'hash': 42552, - 'name': 'Woodcut Redwood LeafClump T4 D30 C1', - 'embedded': { - 'Woodcut_Redwood_LeafClump_T4_D30_C1_44634': { - 'hash': 44634, - 'name': 'Woodcut Redwood LeafClump T4 D30 C1', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafClump_T4_D30_C2': { - 'hash': 46726, - 'name': 'Woodcut Redwood LeafClump T4 D30 C2', - 'embedded': { - 'Woodcut_Redwood_LeafClump_T4_D30_C2_46724': { - 'hash': 46724, - 'name': 'Woodcut Redwood LeafClump T4 D30 C2', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafClump_T4_D30_C3': { - 'hash': 1774, - 'name': 'Woodcut Redwood LeafClump T4 D30 C3', - 'embedded': { - 'Woodcut_Redwood_LeafClump_T4_D30_C3_1772': { - 'hash': 1772, - 'name': 'Woodcut Redwood LeafClump T4 D30 C3', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafClump_T4_D30_C4': { - 'hash': 1512, - 'name': 'Woodcut Redwood LeafClump T4 D30 C4', - 'embedded': { - 'Woodcut_Redwood_LeafClump_T4_D30_C4_1510': { - 'hash': 1510, - 'name': 'Woodcut Redwood LeafClump T4 D30 C4', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafClump_T4_D30_C5': { - 'hash': 54122, - 'name': 'Woodcut Redwood LeafClump T4 D30 C5', - 'embedded': { - 'Woodcut_Redwood_LeafClump_T4_D30_C5_54120': { - 'hash': 54120, - 'name': 'Woodcut Redwood LeafClump T4 D30 C5', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafClump_T4_D30_C6': { - 'hash': 7242, - 'name': 'Woodcut Redwood LeafClump T4 D30 C6', - 'embedded': { - 'Woodcut_Redwood_LeafClump_T4_D30_C6_7240': { - 'hash': 7240, - 'name': 'Woodcut Redwood LeafClump T4 D30 C6', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafClump_T4_D30_C7': { - 'hash': 44386, - 'name': 'Woodcut Redwood LeafClump T4 D30 C7', - 'embedded': { - 'Woodcut_Redwood_LeafClump_T4_D30_C7_44384': { - 'hash': 44384, - 'name': 'Woodcut Redwood LeafClump T4 D30 C7', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafClump_T4_D30_C8': { - 'hash': 10754, - 'name': 'Woodcut Redwood LeafClump T4 D30 C8', - 'embedded': { - 'Woodcut_Redwood_LeafClump_T4_D30_C8_10752': { - 'hash': 10752, - 'name': 'Woodcut Redwood LeafClump T4 D30 C8', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_LeafTopper': { - 'hash': 34724, - 'name': 'Woodcut Redwood LeafTopper', - 'embedded': { - 'Woodcut_Redwood_LeafTopper_34720': { - 'hash': 34720, - 'name': 'Woodcut Redwood LeafTopper', - 'savables': {} - } - } - }, - 'Woodcut_Redwood_Seed_Spawner_Attachment': { - 'hash': 16012, - 'name': 'Woodcut Redwood Seed Spawner Attachment', - 'embedded': { - 'Woodcut_Redwood_Seed_Spawner_Attachment_36402': { - 'hash': 36402, - 'name': 'Woodcut Redwood Seed Spawner Attachment', - 'savables': {} - } - } - }, - 'Woodcut_Root_V1_T0': { - 'hash': 31522, - 'name': 'Woodcut_Root_V1_T0', - 'embedded': { - 'Top_49314': { - 'hash': 49314, - 'name': 'Top_49314', - 'savables': {} - } - } - }, - 'Woodcut_Root_V1_T0_B15': { - 'hash': 34660, - 'name': 'Woodcut_Root_V1_T0_B15', - 'embedded': { - 'Top_23584': { - 'hash': 23584, - 'name': 'Top_23584', - 'savables': {} - }, - 'Branch_12832': { - 'hash': 12832, - 'name': 'Branch_12832', - 'savables': {} - } - } - }, - 'Woodcut_Root_V1_T0_S30': { - 'hash': 34546, - 'name': 'Woodcut_Root_V1_T0_S30', - 'embedded': { - 'Top_56452': { - 'hash': 56452, - 'name': 'Top_56452', - 'savables': {} - }, - 'Stick_51558': { - 'hash': 51558, - 'name': 'Stick_51558', - 'savables': {} - } - } - }, - 'Woodcut_Root_V1_T30': { - 'hash': 47612, - 'name': 'Woodcut_Root_V1_T30', - 'embedded': { - 'Top_7658': { - 'hash': 7658, - 'name': 'Top_7658', - 'savables': {} - } - } - }, - 'Woodcut_S-15_S-15': { - 'hash': 39282, - 'name': 'Woodcut S-15 S-15', - 'embedded': { - 'Top_1286': { - 'hash': 1286, - 'name': 'Top', - 'savables': {} - }, - 'Woodcut_S-15_S-15_45390': { - 'hash': 45390, - 'name': 'Woodcut S-15 S-15', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_S0_E': { - 'hash': 25704, - 'name': 'Woodcut_S0_E', - 'embedded': {} - }, - 'Woodcut_S0_S0': { - 'hash': 44986, - 'name': 'Woodcut_S0_S0', - 'embedded': { - 'Top_1286': { - 'hash': 1286, - 'name': 'Top_1286', - 'savables': {} - } - } - }, - 'Woodcut_S0_S0_S-30': { - 'hash': 25116, - 'name': 'Woodcut S0 S0 S-30', - 'embedded': { - 'Top_1_2062': { - 'hash': 2062, - 'name': 'Top 1', - 'savables': {} - }, - 'Top_2_60778': { - 'hash': 60778, - 'name': 'Top 2', - 'savables': {} - }, - 'Woodcut_S0_S0_S-30_64064': { - 'hash': 64064, - 'name': 'Woodcut S0 S0 S-30', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_S0_S0_S30': { - 'hash': 190, - 'name': 'Woodcut S0 S0 S30', - 'embedded': { - 'Top_1_2062': { - 'hash': 2062, - 'name': 'Top 1', - 'savables': {} - }, - 'Top_2_60778': { - 'hash': 60778, - 'name': 'Top 2', - 'savables': {} - }, - 'Woodcut_S0_S0_S30_64064': { - 'hash': 64064, - 'name': 'Woodcut S0 S0 S30', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_S0_S15_S15': { - 'hash': 62106, - 'name': 'Woodcut_S0_S15_S15', - 'embedded': { - 'Top_1_2062': { - 'hash': 2062, - 'name': 'Top_1_2062', - 'savables': {} - }, - 'Top_2_60778': { - 'hash': 60778, - 'name': 'Top_2_60778', - 'savables': {} - } - } - }, - 'Woodcut_S0_S30_S30': { - 'hash': 9058, - 'name': 'Woodcut S0 S30 S30', - 'embedded': { - 'Top_1_9064': { - 'hash': 9064, - 'name': 'Top 1', - 'savables': {} - }, - 'Top_2_9062': { - 'hash': 9062, - 'name': 'Top 2', - 'savables': {} - }, - 'Woodcut_S0_S30_S30_9060': { - 'hash': 9060, - 'name': 'Woodcut S0 S30 S30', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_S15_S15': { - 'hash': 19364, - 'name': 'Woodcut S15 S15', - 'embedded': { - 'Top_1286': { - 'hash': 1286, - 'name': 'Top', - 'savables': {} - }, - 'Woodcut_S15_S15_45390': { - 'hash': 45390, - 'name': 'Woodcut S15 S15', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_SL15_SL15': { - 'hash': 7464, - 'name': 'Woodcut SL15 SL15', - 'embedded': { - 'Top_1286': { - 'hash': 1286, - 'name': 'Top', - 'savables': {} - }, - 'Woodcut_SL15_SL15_7460': { - 'hash': 7460, - 'name': 'Woodcut SL15 SL15', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_SR15_SR15': { - 'hash': 53266, - 'name': 'Woodcut SR15 SR15', - 'embedded': { - 'Top_1286': { - 'hash': 1286, - 'name': 'Top', - 'savables': {} - }, - 'Woodcut_SR15_SR15_53262': { - 'hash': 53262, - 'name': 'Woodcut SR15 SR15', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_T0_B0_B30': { - 'hash': 35026, - 'name': 'Woodcut_T0_B0_B30', - 'embedded': { - 'Branch_1_4000': { - 'hash': 4000, - 'name': 'Branch_1_4000', - 'savables': {} - }, - 'Branch_2_3996': { - 'hash': 3996, - 'name': 'Branch_2_3996', - 'savables': {} - } - } - }, - 'Woodcut_T0_B15_B30': { - 'hash': 21794, - 'name': 'Woodcut_T0_B15_B30', - 'embedded': { - 'Branch_1_634': { - 'hash': 634, - 'name': 'Branch_1_634', - 'savables': {} - }, - 'Branch_2_636': { - 'hash': 636, - 'name': 'Branch_2_636', - 'savables': {} - } - } - }, - 'Woodcut_T0_B30_B30': { - 'hash': 26492, - 'name': 'Woodcut T0 B30 B30', - 'embedded': { - 'Branch_1_26494': { - 'hash': 26494, - 'name': 'Branch 1', - 'savables': {} - }, - 'Branch_2_26488': { - 'hash': 26488, - 'name': 'Branch 2', - 'savables': {} - }, - 'Woodcut_T0_B30_B30_26500': { - 'hash': 26500, - 'name': 'Woodcut T0 B30 B30', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_T0_B45_B45_B60': { - 'hash': 62378, - 'name': 'Woodcut T0 B45 B45 B60', - 'embedded': { - 'Branch_1_4000': { - 'hash': 4000, - 'name': 'Branch 1', - 'savables': {} - }, - 'Branch_2_20244': { - 'hash': 20244, - 'name': 'Branch 2', - 'savables': {} - }, - 'Branch_3_20258': { - 'hash': 20258, - 'name': 'Branch 3', - 'savables': {} - }, - 'Woodcut_T0_B45_B45_B60_35620': { - 'hash': 35620, - 'name': 'Woodcut T0 B45 B45 B60', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_T0_E': { - 'hash': 49440, - 'name': 'Woodcut_T0_E', - 'embedded': {} - }, - 'Woodcut_T0_T0': { - 'hash': 6554, - 'name': 'Woodcut_T0_T0', - 'embedded': { - 'Top_39100': { - 'hash': 39100, - 'name': 'Top_39100', - 'savables': {} - } - } - }, - 'Woodcut_T0_T0_B30': { - 'hash': 35016, - 'name': 'Woodcut_T0_T0_B30', - 'embedded': { - 'Top_34360': { - 'hash': 34360, - 'name': 'Top_34360', - 'savables': {} - }, - 'Branch_34356': { - 'hash': 34356, - 'name': 'Branch_34356', - 'savables': {} - } - } - }, - 'Woodcut_T0_T0_B45': { - 'hash': 52242, - 'name': 'Woodcut_T0_T0_B45', - 'embedded': { - 'Top_15160': { - 'hash': 15160, - 'name': 'Top_15160', - 'savables': {} - }, - 'Branch_15162': { - 'hash': 15162, - 'name': 'Branch_15162', - 'savables': {} - } - } - }, - 'Woodcut_T0_T0_B45_B45_B60': { - 'hash': 34502, - 'name': 'Woodcut T0 T0 B45 B45 B60', - 'embedded': { - 'Branch_1_15162': { - 'hash': 15162, - 'name': 'Branch 1', - 'savables': {} - }, - 'Branch_2_19850': { - 'hash': 19850, - 'name': 'Branch 2', - 'savables': {} - }, - 'Branch_3_19844': { - 'hash': 19844, - 'name': 'Branch 3', - 'savables': {} - }, - 'Top_15160': { - 'hash': 15160, - 'name': 'Top', - 'savables': {} - }, - 'Woodcut_T0_T0_B45_B45_B60_55228': { - 'hash': 55228, - 'name': 'Woodcut T0 T0 B45 B45 B60', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_T0_T0_B60': { - 'hash': 29162, - 'name': 'Woodcut T0 T0 B60', - 'embedded': { - 'Branch_15162': { - 'hash': 15162, - 'name': 'Branch', - 'savables': {} - }, - 'Top_15160': { - 'hash': 15160, - 'name': 'Top', - 'savables': {} - }, - 'Woodcut_T0_T0_B60_55228': { - 'hash': 55228, - 'name': 'Woodcut T0 T0 B60', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_T0_T0_S30': { - 'hash': 35022, - 'name': 'Woodcut_T0_T0_S30', - 'embedded': { - 'Top_45916': { - 'hash': 45916, - 'name': 'Top_45916', - 'savables': {} - }, - 'Stick_45912': { - 'hash': 45912, - 'name': 'Stick_45912', - 'savables': {} - } - } - }, - 'Woodcut_T0_T0_S30_S30_S30': { - 'hash': 33712, - 'name': 'Woodcut_T0_T0_S30_S30_S30', - 'embedded': { - 'Top_836': { - 'hash': 836, - 'name': 'Top_836', - 'savables': {} - }, - 'Stick_1_34724': { - 'hash': 34724, - 'name': 'Stick_1_34724', - 'savables': {} - }, - 'Stick_2_17522': { - 'hash': 17522, - 'name': 'Stick_2_17522', - 'savables': {} - }, - 'Stick_3_910': { - 'hash': 910, - 'name': 'Stick_3_910', - 'savables': {} - } - } - }, - 'Woodcut_T0_T30_B30': { - 'hash': 2712, - 'name': 'Woodcut T0 T30 B30', - 'embedded': { - 'Branch_15162': { - 'hash': 15162, - 'name': 'Branch', - 'savables': {} - }, - 'Top_15160': { - 'hash': 15160, - 'name': 'Top', - 'savables': {} - }, - 'Woodcut_T0_T30_B30_55228': { - 'hash': 55228, - 'name': 'Woodcut T0 T30 B30', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_T15_T15': { - 'hash': 40700, - 'name': 'Woodcut_T15_T15', - 'embedded': { - 'Top_30734': { - 'hash': 30734, - 'name': 'Top_30734', - 'savables': {} - } - } - }, - 'Woodcut_T30_T30': { - 'hash': 30226, - 'name': 'Woodcut_T30_T30', - 'embedded': { - 'Top_28372': { - 'hash': 28372, - 'name': 'Top_28372', - 'savables': {} - } - } - }, - 'Woodcut_T5_T5': { - 'hash': 18498, - 'name': 'Woodcut_T5_T5', - 'embedded': { - 'Top_32750': { - 'hash': 32750, - 'name': 'Top_32750', - 'savables': {} - } - } - }, - 'Woodcut_Training_Block': { - 'hash': 13392, - 'name': 'Woodcut Training Block', - 'embedded': { - 'Woodcut_Training_Block_11246': { - 'hash': 11246, - 'name': 'Woodcut Training Block', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - } - } - }, - 'Woodcut_Twigs_V1_-30': { - 'hash': 49360, - 'name': 'Woodcut_Twigs_V1_-30', - 'embedded': {} - }, - 'Woodcut_Twigs_V1_0': { - 'hash': 64824, - 'name': 'Woodcut_Twigs_V1_0', - 'embedded': {} - }, - 'Woodcut_Twigs_V1_30': { - 'hash': 19674, - 'name': 'Woodcut_Twigs_V1_30', - 'embedded': {} - }, - 'Woodcut_Twigs_V2_-30': { - 'hash': 63554, - 'name': 'Woodcut_Twigs_V2_-30', - 'embedded': {} - }, - 'Woodcut_Twigs_V2_0': { - 'hash': 1846, - 'name': 'Woodcut_Twigs_V2_0', - 'embedded': {} - }, - 'Woodcut_Twigs_V2_30': { - 'hash': 1452, - 'name': 'Woodcut_Twigs_V2_30', - 'embedded': {} - }, - 'Woodcut_Twigs_V3_-30': { - 'hash': 49972, - 'name': 'Woodcut_Twigs_V3_-30', - 'embedded': {} - }, - 'Woodcut_Twigs_V3_0': { - 'hash': 63168, - 'name': 'Woodcut_Twigs_V3_0', - 'embedded': {} - }, - 'Woodcut_Twigs_V3_30': { - 'hash': 15084, - 'name': 'Woodcut_Twigs_V3_30', - 'embedded': {} - }, - 'Woodcut_Twigs_V4_0': { - 'hash': 52628, - 'name': 'Woodcut_Twigs_V4_0', - 'embedded': {} - }, - 'Woodcut_Twigs_V4_30': { - 'hash': 31554, - 'name': 'Woodcut_Twigs_V4_30', - 'embedded': {} - }, - 'Woodcut_Twigs_V5_-15': { - 'hash': 16424, - 'name': 'Woodcut Twigs V5 -15', - 'embedded': { - 'Woodcut_Twigs_V5_-15_47386': { - 'hash': 47386, - 'name': 'Woodcut Twigs V5 -15', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_Twigs_V5_15': { - 'hash': 32642, - 'name': 'Woodcut Twigs V5 15', - 'embedded': { - 'Woodcut_Twigs_V5_15_32644': { - 'hash': 32644, - 'name': 'Woodcut Twigs V5 15', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_Twigs_V5_L15': { - 'hash': 40208, - 'name': 'Woodcut Twigs V5 L15', - 'embedded': { - 'Woodcut_Twigs_V5_L15_40210': { - 'hash': 40210, - 'name': 'Woodcut Twigs V5 L15', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_Twigs_V5_R15': { - 'hash': 25388, - 'name': 'Woodcut Twigs V5 R15', - 'embedded': { - 'Woodcut_Twigs_V5_R15_25390': { - 'hash': 25390, - 'name': 'Woodcut Twigs V5 R15', - 'savables': { - 'WoodcutPointCollection': { - 'hash': 276353327, - 'name': 'WoodcutPointCollection' - } - } - } - } - }, - 'Woodcut_Walnut_LeafClump_Base': { - 'hash': 47632, - 'name': 'Woodcut Walnut LeafClump Base', - 'embedded': { - 'Woodcut_Walnut_LeafClump_Base_47646': { - 'hash': 47646, - 'name': 'Woodcut Walnut LeafClump Base', - 'savables': {} - } - } - }, - 'Woodcut_Walnut_LeafClump_C1C1': { - 'hash': 29962, - 'name': 'Woodcut Walnut LeafClump C1C1', - 'embedded': { - 'Woodcut_Walnut_LeafClump_C1C1_29960': { - 'hash': 29960, - 'name': 'Woodcut Walnut LeafClump C1C1', - 'savables': {} - } - } - }, - 'Woodcut_Walnut_LeafClump_C1C1_E': { - 'hash': 2796, - 'name': 'Woodcut Walnut LeafClump C1C1 E', - 'embedded': { - 'Woodcut_Walnut_LeafClump_C1C1_E_2794': { - 'hash': 2794, - 'name': 'Woodcut Walnut LeafClump C1C1 E', - 'savables': {} - } - } - }, - 'Woodcut_Walnut_LeafClump_C1C2': { - 'hash': 8570, - 'name': 'Woodcut Walnut LeafClump C1C2', - 'embedded': { - 'Woodcut_Walnut_LeafClump_C1C2_8568': { - 'hash': 8568, - 'name': 'Woodcut Walnut LeafClump C1C2', - 'savables': {} - } - } - }, - 'Woodcut_Walnut_LeafClump_C1C2_E': { - 'hash': 54836, - 'name': 'Woodcut Walnut LeafClump C1C2 E', - 'embedded': { - 'Woodcut_Walnut_LeafClump_C1C2_E_54834': { - 'hash': 54834, - 'name': 'Woodcut Walnut LeafClump C1C2 E', - 'savables': {} - } - } - }, - 'Woodcut_Walnut_LeafClump_C2C2': { - 'hash': 8932, - 'name': 'Woodcut Walnut LeafClump C2C2', - 'embedded': { - 'Woodcut_Walnut_LeafClump_C2C2_8930': { - 'hash': 8930, - 'name': 'Woodcut Walnut LeafClump C2C2', - 'savables': {} - } - } - }, - 'Woodcut_Walnut_LeafClump_C2C2_E': { - 'hash': 1792, - 'name': 'Woodcut Walnut LeafClump C2C2 E', - 'embedded': { - 'Woodcut_Walnut_LeafClump_C2C2_E_1790': { - 'hash': 1790, - 'name': 'Woodcut Walnut LeafClump C2C2 E', - 'savables': {} - } - } - }, - 'Woodcut_Walnut_LeafClump_C2C3': { - 'hash': 47520, - 'name': 'Woodcut Walnut LeafClump C2C3', - 'embedded': { - 'Woodcut_Walnut_LeafClump_C2C3_47518': { - 'hash': 47518, - 'name': 'Woodcut Walnut LeafClump C2C3', - 'savables': {} - } - } - }, - 'Woodcut_Walnut_LeafClump_C2C3_E': { - 'hash': 46292, - 'name': 'Woodcut Walnut LeafClump C2C3 E', - 'embedded': { - 'Woodcut_Walnut_LeafClump_C2C3_E_46290': { - 'hash': 46290, - 'name': 'Woodcut Walnut LeafClump C2C3 E', - 'savables': {} - } - } - }, - 'Woodcut_Walnut_LeafClump_C3C3': { - 'hash': 54190, - 'name': 'Woodcut Walnut LeafClump C3C3', - 'embedded': { - 'Woodcut_Walnut_LeafClump_C3C3_54188': { - 'hash': 54188, - 'name': 'Woodcut Walnut LeafClump C3C3', - 'savables': {} - } - } - }, - 'Woodcut_Walnut_LeafClump_C3C3_E': { - 'hash': 8292, - 'name': 'Woodcut Walnut LeafClump C3C3 E', - 'embedded': { - 'Woodcut_Walnut_LeafClump_C3C3_E_8290': { - 'hash': 8290, - 'name': 'Woodcut Walnut LeafClump C3C3 E', - 'savables': {} - } - } - }, - 'Woodcut_Walnut_LeafClump_C3C4': { - 'hash': 57820, - 'name': 'Woodcut Walnut LeafClump C3C4', - 'embedded': { - 'Woodcut_Walnut_LeafClump_C3C4_57818': { - 'hash': 57818, - 'name': 'Woodcut Walnut LeafClump C3C4', - 'savables': {} - } - } - }, - 'Woodcut_Walnut_LeafClump_C3C4_E': { - 'hash': 1546, - 'name': 'Woodcut Walnut LeafClump C3C4 E', - 'embedded': { - 'Woodcut_Walnut_LeafClump_C3C4_E_1544': { - 'hash': 1544, - 'name': 'Woodcut Walnut LeafClump C3C4 E', - 'savables': {} - } - } - }, - 'Woodcut_Walnut_LeafClump_C4C4_E': { - 'hash': 44372, - 'name': 'Woodcut Walnut LeafClump C4C4 E', - 'embedded': { - 'Woodcut_Walnut_LeafClump_C4C4_E_44370': { - 'hash': 44370, - 'name': 'Woodcut Walnut LeafClump C4C4 E', - 'savables': {} - } - } - }, - 'Woodcut_Walnut_LeafClump_C4C5_E': { - 'hash': 6218, - 'name': 'Woodcut Walnut LeafClump C4C5 E', - 'embedded': { - 'Woodcut_Walnut_LeafClump_C4C5_E_6216': { - 'hash': 6216, - 'name': 'Woodcut Walnut LeafClump C4C5 E', - 'savables': {} - } - } - }, - 'Woodcut_Walnut_LeafClump_C5C5_E': { - 'hash': 9940, - 'name': 'Woodcut Walnut LeafClump C5C5 E', - 'embedded': { - 'Woodcut_Walnut_LeafClump_C5C5_E_9938': { - 'hash': 9938, - 'name': 'Woodcut Walnut LeafClump C5C5 E', - 'savables': {} - } - } - }, - 'Woodcut_Walnut_Seed_Spawner_Attachment': { - 'hash': 16040, - 'name': 'Woodcut Walnut Seed Spawner Attachment', - 'embedded': { - 'Woodcut_Walnut_Seed_Spawner_Attachment_36402': { - 'hash': 36402, - 'name': 'Woodcut Walnut Seed Spawner Attachment', - 'savables': {} - } - } - }, - 'Woodcut_Wedge': { - 'hash': 47118, - 'name': 'Woodcut Wedge', - 'embedded': { - 'Woodcut_Wedge_10506': { - 'hash': 10506, - 'name': 'Woodcut Wedge', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Woodcut_Wedge_Ashen': { - 'hash': 232, - 'name': 'Woodcut Wedge Ashen', - 'embedded': { - 'Woodcut_Wedge_Ashen_3674': { - 'hash': 3674, - 'name': 'Woodcut Wedge Ashen', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Woodcut_Wedge_Burnt': { - 'hash': 290, - 'name': 'Woodcut Wedge Burnt', - 'embedded': { - 'Woodcut_Wedge_Burnt_3674': { - 'hash': 3674, - 'name': 'Woodcut Wedge Burnt', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Woodcut_Wedge_Charred': { - 'hash': 58068, - 'name': 'Woodcut Wedge Charred', - 'embedded': { - 'Woodcut_Wedge_Charred_3674': { - 'hash': 3674, - 'name': 'Woodcut Wedge Charred', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Woodcut_Wedge_Storage': { - 'hash': 12512, - 'name': 'Woodcut Wedge Storage', - 'embedded': { - 'Filter_Dock_57214': { - 'hash': 57214, - 'name': 'Filter Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Interaction_Point_59032': { - 'hash': 59032, - 'name': 'Interaction Point', - 'savables': {} - }, - 'Internal_Dock_59328': { - 'hash': 59328, - 'name': 'Internal Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Withdraw_Dock_34750': { - 'hash': 34750, - 'name': 'Withdraw Dock', - 'savables': {} - }, - 'Woodcut_Wedge_Storage_12490': { - 'hash': 12490, - 'name': 'Woodcut Wedge Storage', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - }, - 'CommunalStorage': { - 'hash': 3084373371, - 'name': 'CommunalStorage' - }, - 'PlayerInteractionRestrictor': { - 'hash': 2951515968, - 'name': 'PlayerInteractionRestrictor' - } - } - } - } - }, - 'Woodcutting_Path': { - 'hash': 45418, - 'name': 'Woodcutting Path', - 'embedded': { - 'Woodcutting_Path_54368': { - 'hash': 54368, - 'name': 'Woodcutting Path', - 'savables': { - 'PopulationPath': { - 'hash': 7704646, - 'name': 'PopulationPath' - } - } - } - } - }, - 'Woodcutting_Vines_V1_Large': { - 'hash': 24682, - 'name': 'Woodcutting_Vines_V1_Large', - 'embedded': {} - }, - 'Woodcutting_Vines_V1_Small_V1': { - 'hash': 24686, - 'name': 'Woodcutting_Vines_V1_Small_V1', - 'embedded': {} - }, - 'Woodcutting_Vines_V1_Small_V2': { - 'hash': 24684, - 'name': 'Woodcutting_Vines_V1_Small_V2', - 'embedded': {} - }, - 'Woodcutting_Vines_V1_Small_V3': { - 'hash': 24688, - 'name': 'Woodcutting_Vines_V1_Small_V3', - 'embedded': {} - }, - 'Wooden_Bag': { - 'hash': 30060, - 'name': 'Wooden Bag', - 'embedded': { - 'Bag_Body_42972': { - 'hash': 42972, - 'name': 'Bag Body', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - }, - 'Dock_ML_42984': { - 'hash': 42984, - 'name': 'Dock ML', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_MM_42982': { - 'hash': 42982, - 'name': 'Dock MM', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_MR_42980': { - 'hash': 42980, - 'name': 'Dock MR', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_TL_42990': { - 'hash': 42990, - 'name': 'Dock TL', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_TM_42988': { - 'hash': 42988, - 'name': 'Dock TM', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Dock_TR_42986': { - 'hash': 42986, - 'name': 'Dock TR', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Wooden_Bag_43012': { - 'hash': 43012, - 'name': 'Wooden Bag', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'wooden_bag_back_straw_22280': { - 'hash': 22280, - 'name': 'wooden_bag_back_straw', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'wooden_bag_beam_01_22276': { - 'hash': 22276, - 'name': 'wooden_bag_beam_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'wooden_bag_beam_02_22320': { - 'hash': 22320, - 'name': 'wooden_bag_beam_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'wooden_bag_beam_03_22316': { - 'hash': 22316, - 'name': 'wooden_bag_beam_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'wooden_bag_beam_04_22308': { - 'hash': 22308, - 'name': 'wooden_bag_beam_04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'wooden_bag_beam_05_22304': { - 'hash': 22304, - 'name': 'wooden_bag_beam_05', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'wooden_bag_beam_06_22300': { - 'hash': 22300, - 'name': 'wooden_bag_beam_06', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'wooden_bag_beam_07_22296': { - 'hash': 22296, - 'name': 'wooden_bag_beam_07', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'wooden_bag_beam_curved_01_22292': { - 'hash': 22292, - 'name': 'wooden_bag_beam_curved_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'wooden_bag_beam_curved_02_22288': { - 'hash': 22288, - 'name': 'wooden_bag_beam_curved_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'wooden_bag_front_straw_22284': { - 'hash': 22284, - 'name': 'wooden_bag_front_straw', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'wooden_bag_handle_738': { - 'hash': 738, - 'name': 'wooden_bag_handle', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'wooden_bag_handle_wraps_742': { - 'hash': 742, - 'name': 'wooden_bag_handle_wraps', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'wooden_bag_lid_straw_22312': { - 'hash': 22312, - 'name': 'wooden_bag_lid_straw', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'wooden_bag_side_01_straw_22272': { - 'hash': 22272, - 'name': 'wooden_bag_side_01_straw', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'wooden_bag_side_02_straw_22268': { - 'hash': 22268, - 'name': 'wooden_bag_side_02_straw', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Wooden_Barrel': { - 'hash': 5890, - 'name': 'Wooden Barrel', - 'embedded': { - 'Handle_Pickup_13422': { - 'hash': 13422, - 'name': 'Handle Pickup', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - } - } - }, - 'Handle__58484': { - 'hash': 58484, - 'name': 'Handle ', - 'savables': {} - }, - 'Wooden_Barrel_11132': { - 'hash': 11132, - 'name': 'Wooden Barrel', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - }, - 'LiquidContainer': { - 'hash': 4179293747, - 'name': 'LiquidContainer' - } - } - } - } - }, - 'Wooden_Bowl': { - 'hash': 25908, - 'name': 'Wooden Bowl', - 'embedded': { - 'Wooden_Bowl_23250': { - 'hash': 23250, - 'name': 'Wooden Bowl', - 'savables': { - 'LiquidContainer': { - 'hash': 4179293747, - 'name': 'LiquidContainer' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Wooden_Bucket': { - 'hash': 63904, - 'name': 'Wooden Bucket', - 'embedded': { - 'Bucket_Wooden_Metal_Bottom_20258': { - 'hash': 20258, - 'name': 'Bucket Wooden Metal Bottom', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'Bucket_Wooden_Metal_Top_20246': { - 'hash': 20246, - 'name': 'Bucket Wooden Metal Top', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'Bucket_Wooden_Wood_20270': { - 'hash': 20270, - 'name': 'Bucket Wooden Wood', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'Bucket_Wooden_Wood_Bottom_20262': { - 'hash': 20262, - 'name': 'Bucket Wooden Wood Bottom', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'Handle_L__20254': { - 'hash': 20254, - 'name': 'Handle L ', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'Handle_R_20266': { - 'hash': 20266, - 'name': 'Handle R', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'Handle_Top_20250': { - 'hash': 20250, - 'name': 'Handle Top', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'Heat_47560': { - 'hash': 47560, - 'name': 'Heat', - 'savables': { - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'Wooden_Bucket_65316': { - 'hash': 65316, - 'name': 'Wooden Bucket', - 'savables': { - 'LiquidContainer': { - 'hash': 4179293747, - 'name': 'LiquidContainer' - }, - 'MultiHandPickup': { - 'hash': 1556697998, - 'name': 'MultiHandPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'cookingPot_plate_01_24': { - 'hash': 24, - 'name': 'cookingPot_plate_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'cookingPot_plate_02_28': { - 'hash': 28, - 'name': 'cookingPot_plate_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'cookingPot_plate_03_36': { - 'hash': 36, - 'name': 'cookingPot_plate_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'cookingPot_plate_04_32': { - 'hash': 32, - 'name': 'cookingPot_plate_04', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'cookingPot_plate_mid_01_48': { - 'hash': 48, - 'name': 'cookingPot_plate_mid_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'cookingPot_plate_mid_02_56': { - 'hash': 56, - 'name': 'cookingPot_plate_mid_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Wooden_Dice': { - 'hash': 45608, - 'name': 'Wooden Dice', - 'embedded': { - 'Wooden_Dice_45490': { - 'hash': 45490, - 'name': 'Wooden Dice', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Wooden_Ladle': { - 'hash': 15274, - 'name': 'Wooden Ladle', - 'embedded': { - 'Wooden_Ladle_16772': { - 'hash': 16772, - 'name': 'Wooden Ladle', - 'savables': { - 'LiquidContainer': { - 'hash': 4179293747, - 'name': 'LiquidContainer' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Wooden_Net': { - 'hash': 53540, - 'name': 'Wooden Net', - 'embedded': { - 'Dock_42390': { - 'hash': 42390, - 'name': 'Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'Insert_HammerType_End_Cap_7796': { - 'hash': 7796, - 'name': 'Insert HammerType End Cap', - 'savables': {} - }, - 'Wooden_Net_7480': { - 'hash': 7480, - 'name': 'Wooden Net', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - }, - 'woodenNet_basket_17034': { - 'hash': 17034, - 'name': 'woodenNet_basket', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'woodenNet_curvedFrame_01_17018': { - 'hash': 17018, - 'name': 'woodenNet_curvedFrame_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'woodenNet_curvedFrame_brace_01_17022': { - 'hash': 17022, - 'name': 'woodenNet_curvedFrame_brace_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'woodenNet_handle_01_17026': { - 'hash': 17026, - 'name': 'woodenNet_handle_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'woodenNet_knot_01_17038': { - 'hash': 17038, - 'name': 'woodenNet_knot_01', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'woodenNet_knot_02_17030': { - 'hash': 17030, - 'name': 'woodenNet_knot_02', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - }, - 'woodenNet_knot_03_17014': { - 'hash': 17014, - 'name': 'woodenNet_knot_03', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - } - } - } - } - }, - 'Wooden_Passage_Dynamic': { - 'hash': 43806, - 'name': 'Wooden Passage Dynamic', - 'embedded': { - 'Enemy_Spawn_28160': { - 'hash': 28160, - 'name': 'Enemy Spawn', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'SpawnArea': { - 'hash': 2617495528, - 'name': 'SpawnArea' - } - } - }, - 'Spawn_43748': { - 'hash': 43748, - 'name': 'Spawn', - 'savables': { - 'DirectionalBoundsSurface': { - 'hash': 1962842866, - 'name': 'DirectionalBoundsSurface' - }, - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - } - } - }, - 'Wooden_Passage_Dynamic_43790': { - 'hash': 43790, - 'name': 'Wooden Passage Dynamic', - 'savables': {} - } - } - }, - 'Wooden_Short_Sword': { - 'hash': 16448, - 'name': 'Wooden Short Sword', - 'embedded': { - 'Wooden_Short_Sword_18792': { - 'hash': 18792, - 'name': 'Wooden Short Sword', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Wooden_Stake': { - 'hash': 17262, - 'name': 'Wooden Stake', - 'embedded': { - 'Slot_Multi_11474': { - 'hash': 11474, - 'name': 'Slot Multi', - 'savables': {} - }, - 'Wooden_Stake_17052': { - 'hash': 17052, - 'name': 'Wooden Stake', - 'savables': { - 'DurabilityModule': { - 'hash': 1871432223, - 'name': 'DurabilityModule' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'RaycastCrafter': { - 'hash': 2815374842, - 'name': 'RaycastCrafter' - } - } - } - } - }, - 'Wooden_Stirring_Spoon': { - 'hash': 23950, - 'name': 'Wooden Stirring Spoon', - 'embedded': { - 'Wooden_Stirring_Spoon_26366': { - 'hash': 26366, - 'name': 'Wooden Stirring Spoon', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'Wyrm': { - 'hash': 21642, - 'name': 'Wyrm', - 'embedded': { - 'Animation_6144': { - 'hash': 6144, - 'name': 'Animation', - 'savables': {} - }, - 'Body_1052': { - 'hash': 1052, - 'name': 'Body', - 'savables': {} - }, - 'Gameplay_42330': { - 'hash': 42330, - 'name': 'Gameplay', - 'savables': {} - }, - 'Ground_58968': { - 'hash': 58968, - 'name': 'Ground', - 'savables': {} - }, - 'SlashDamage_L_57358': { - 'hash': 57358, - 'name': 'SlashDamage L', - 'savables': {} - }, - 'SlashDamage_R_59218': { - 'hash': 59218, - 'name': 'SlashDamage R', - 'savables': {} - }, - 'Spawner_240': { - 'hash': 240, - 'name': 'Spawner', - 'savables': {} - }, - 'Wyrm_37044': { - 'hash': 37044, - 'name': 'Wyrm', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Wyrm_AI_46146': { - 'hash': 46146, - 'name': 'Wyrm AI', - 'savables': {} - }, - 'scythe_l_jnt_544': { - 'hash': 544, - 'name': 'scythe_l_jnt', - 'savables': {} - }, - 'scythe_r_jnt_542': { - 'hash': 542, - 'name': 'scythe_r_jnt', - 'savables': {} - } - } - }, - 'Wyrm_(Trial)': { - 'hash': 6004, - 'name': 'Wyrm (Trial)', - 'embedded': { - 'Animation_6144': { - 'hash': 6144, - 'name': 'Animation', - 'savables': {} - }, - 'Body_1052': { - 'hash': 1052, - 'name': 'Body', - 'savables': {} - }, - 'Gameplay_42330': { - 'hash': 42330, - 'name': 'Gameplay', - 'savables': {} - }, - 'Ground_58968': { - 'hash': 58968, - 'name': 'Ground', - 'savables': {} - }, - 'SlashDamage_L_57358': { - 'hash': 57358, - 'name': 'SlashDamage L', - 'savables': {} - }, - 'SlashDamage_R_59218': { - 'hash': 59218, - 'name': 'SlashDamage R', - 'savables': {} - }, - 'Spawner_240': { - 'hash': 240, - 'name': 'Spawner', - 'savables': {} - }, - 'Wyrm_(Trial)_37044': { - 'hash': 37044, - 'name': 'Wyrm (Trial)', - 'savables': { - 'PhysicalMaterialPart': { - 'hash': 272188517, - 'name': 'PhysicalMaterialPart' - }, - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'Wyrm_AI_46146': { - 'hash': 46146, - 'name': 'Wyrm AI', - 'savables': {} - }, - 'scythe_l_jnt_544': { - 'hash': 544, - 'name': 'scythe_l_jnt', - 'savables': {} - }, - 'scythe_r_jnt_542': { - 'hash': 542, - 'name': 'scythe_r_jnt', - 'savables': {} - } - } - }, - 'Wyrm_Arm': { - 'hash': 46340, - 'name': 'Wyrm_Arm', - 'embedded': {} - }, - 'Wyrm_Boulder_01': { - 'hash': 37174, - 'name': 'Wyrm Boulder 01', - 'embedded': { - 'Wyrm_Boulder_01_62528': { - 'hash': 62528, - 'name': 'Wyrm Boulder 01', - 'savables': {} - }, - 'Wyrm_Spawner_63404': { - 'hash': 63404, - 'name': 'Wyrm Spawner', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'SpawnArea': { - 'hash': 2617495528, - 'name': 'SpawnArea' - } - } - } - } - }, - 'Wyrm_Crystal_Spit': { - 'hash': 37926, - 'name': 'Wyrm Crystal Spit', - 'embedded': { - 'CrystalBall_62940': { - 'hash': 62940, - 'name': 'CrystalBall', - 'savables': {} - }, - 'Wyrm_Crystal_Spit_62050': { - 'hash': 62050, - 'name': 'Wyrm Crystal Spit', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Wyrm_Spit': { - 'hash': 61454, - 'name': 'Wyrm Spit', - 'embedded': { - 'PoisonBall_34058': { - 'hash': 34058, - 'name': 'PoisonBall', - 'savables': {} - }, - 'Wyrm_Spit_62050': { - 'hash': 62050, - 'name': 'Wyrm Spit', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - } - } - } - } - }, - 'Xnor': { - 'hash': 42418, - 'name': 'Xnor', - 'embedded': {} - }, - 'Xor': { - 'hash': 42428, - 'name': 'Xor', - 'embedded': {} - }, - 'archery_target_puzzle_test': { - 'hash': 54358, - 'name': 'archery_target_puzzle_test', - 'embedded': {} - }, - 'cam': { - 'hash': 8760, - 'name': 'cam', - 'embedded': {} - }, - 'combat_dummy': { - 'hash': 57126, - 'name': 'combat_dummy', - 'embedded': { - 'combat_dummy_57314': { - 'hash': 57314, - 'name': 'combat_dummy', - 'savables': { - 'StatManager': { - 'hash': 2563567105, - 'name': 'StatManager' - } - } - }, - 'dummy_arm_l_01_jnt_46272': { - 'hash': 46272, - 'name': 'dummy_arm_l_01_jnt', - 'savables': {} - }, - 'dummy_arm_l_02_jnt_46248': { - 'hash': 46248, - 'name': 'dummy_arm_l_02_jnt', - 'savables': {} - }, - 'dummy_arm_l_03_jnt_46250': { - 'hash': 46250, - 'name': 'dummy_arm_l_03_jnt', - 'savables': {} - }, - 'dummy_arm_r_01_jnt_46246': { - 'hash': 46246, - 'name': 'dummy_arm_r_01_jnt', - 'savables': {} - }, - 'dummy_arm_r_02_jnt_46254': { - 'hash': 46254, - 'name': 'dummy_arm_r_02_jnt', - 'savables': {} - }, - 'dummy_arm_r_03_jnt_46256': { - 'hash': 46256, - 'name': 'dummy_arm_r_03_jnt', - 'savables': {} - }, - 'dummy_head_01_jnt_46270': { - 'hash': 46270, - 'name': 'dummy_head_01_jnt', - 'savables': {} - }, - 'dummy_head_02_jnt_46264': { - 'hash': 46264, - 'name': 'dummy_head_02_jnt', - 'savables': {} - }, - 'dummy_head_03_jnt_46262': { - 'hash': 46262, - 'name': 'dummy_head_03_jnt', - 'savables': {} - }, - 'dummy_neck_jnt_46268': { - 'hash': 46268, - 'name': 'dummy_neck_jnt', - 'savables': {} - }, - 'dummy_spineMid_jnt_46274': { - 'hash': 46274, - 'name': 'dummy_spineMid_jnt', - 'savables': {} - }, - 'dummy_spine_01_jnt_46258': { - 'hash': 46258, - 'name': 'dummy_spine_01_jnt', - 'savables': {} - }, - 'dummy_spine_02_jnt_46260': { - 'hash': 46260, - 'name': 'dummy_spine_02_jnt', - 'savables': {} - }, - 'dummy_spine_03_jnt_46266': { - 'hash': 46266, - 'name': 'dummy_spine_03_jnt', - 'savables': {} - }, - 'dummy_sternum_jnt_46252': { - 'hash': 46252, - 'name': 'dummy_sternum_jnt', - 'savables': {} - } - } - }, - 'item_pedestal_puzzle_base': { - 'hash': 27250, - 'name': 'item_pedestal_puzzle_base', - 'embedded': { - 'Pedestal_Dock_27002': { - 'hash': 27002, - 'name': 'Pedestal Dock', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - }, - 'PickupDockPedestalSpawn': { - 'hash': 2592242915, - 'name': 'PickupDockPedestalSpawn' - } - } - }, - 'item_pedestal_puzzle_base_27194': { - 'hash': 27194, - 'name': 'item_pedestal_puzzle_base', - 'savables': { - 'LogicBoolSender': { - 'hash': 1257282635, - 'name': 'LogicBoolSender' - }, - 'LogicIntSender': { - 'hash': 2880587164, - 'name': 'LogicIntSender' - }, - 'PlaceItemPuzzleLogic': { - 'hash': 1001395212, - 'name': 'PlaceItemPuzzleLogic' - } - } - } - } - }, - 'mrk_extensionBridge_01': { - 'hash': 34038, - 'name': 'mrk_extensionBridge_01', - 'embedded': { - 'mrk_extensionBridge_01_32324': { - 'hash': 32324, - 'name': 'mrk_extensionBridge_01', - 'savables': { - 'LogicFloatReceiver': { - 'hash': 3188272159, - 'name': 'LogicFloatReceiver' - }, - 'NetworkedFloatStream': { - 'hash': 2127962967, - 'name': 'NetworkedFloatStream' - } - } - }, - 'mrk_extensionBridge_bridge_01_21508': { - 'hash': 21508, - 'name': 'mrk_extensionBridge_bridge_01', - 'savables': {} - } - } - }, - 'mrk_large_lift_01': { - 'hash': 28708, - 'name': 'mrk_large_lift_01', - 'embedded': { - 'End_61234': { - 'hash': 61234, - 'name': 'End', - 'savables': {} - }, - 'Start_1586': { - 'hash': 1586, - 'name': 'Start', - 'savables': {} - }, - 'mrk_large_lift_01_49676': { - 'hash': 49676, - 'name': 'mrk_large_lift_01', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - } - } - }, - 'mrk_lift_platform_41794': { - 'hash': 41794, - 'name': 'mrk_lift_platform', - 'savables': { - 'CurveOutput': { - 'hash': 2576456808, - 'name': 'CurveOutput' - } - } - } - } - }, - 'mrk_lift_01': { - 'hash': 45646, - 'name': 'mrk_lift_01', - 'embedded': { - 'Network_Event_1_10242': { - 'hash': 10242, - 'name': 'Network Event 1', - 'savables': {} - }, - 'Network_Event_2_10094': { - 'hash': 10094, - 'name': 'Network Event 2', - 'savables': {} - }, - 'Reset_Receiver_54952': { - 'hash': 54952, - 'name': 'Reset Receiver', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - } - } - }, - 'mrk_lift_01_49676': { - 'hash': 49676, - 'name': 'mrk_lift_01', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - } - } - }, - 'mrk_lift_platform_41794': { - 'hash': 41794, - 'name': 'mrk_lift_platform', - 'savables': { - 'CurveOutput': { - 'hash': 2576456808, - 'name': 'CurveOutput' - } - } - } - } - }, - 'mrk_puzzleCore_symbol_01': { - 'hash': 48100, - 'name': 'mrk_puzzleCore_symbol_01', - 'embedded': { - 'Glow_End_49116': { - 'hash': 49116, - 'name': 'Glow End', - 'savables': {} - }, - 'Glow_Start_40754': { - 'hash': 40754, - 'name': 'Glow Start', - 'savables': {} - }, - 'mrk_puzzleCore_symbol_01_4198': { - 'hash': 4198, - 'name': 'mrk_puzzleCore_symbol_01', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - } - } - } - } - }, - 'mrk_puzzleCore_symbol_02': { - 'hash': 48102, - 'name': 'mrk_puzzleCore_symbol_02', - 'embedded': { - 'Glow_End_39528': { - 'hash': 39528, - 'name': 'Glow End', - 'savables': {} - }, - 'Glow_Start_39856': { - 'hash': 39856, - 'name': 'Glow Start', - 'savables': {} - }, - 'mrk_puzzleCore_symbol_02_4422': { - 'hash': 4422, - 'name': 'mrk_puzzleCore_symbol_02', - 'savables': { - 'LogicBoolReceiver': { - 'hash': 3751351177, - 'name': 'LogicBoolReceiver' - } - } - } - } - }, - 'ore_copper': { - 'hash': 22768, - 'name': 'ore_copper', - 'embedded': {} - }, - 'ore_gold': { - 'hash': 38596, - 'name': 'ore_gold', - 'embedded': {} - }, - 'ore_iron': { - 'hash': 60876, - 'name': 'ore_iron', - 'embedded': {} - }, - 'ore_mythril': { - 'hash': 18158, - 'name': 'ore_mythril', - 'embedded': {} - }, - 'ore_silver': { - 'hash': 26988, - 'name': 'ore_silver', - 'embedded': {} - }, - 'pot_01': { - 'hash': 44028, - 'name': 'pot_01', - 'embedded': {} - }, - 'pumpkin_flower': { - 'hash': 3116, - 'name': 'pumpkin_flower', - 'embedded': { - 'pumpkin_flower_3100': { - 'hash': 3100, - 'name': 'pumpkin_flower', - 'savables': {} - } - } - }, - 'pumpkin_full_burnt': { - 'hash': 5532, - 'name': 'pumpkin full burnt', - 'embedded': { - 'Cooking_29838': { - 'hash': 29838, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'pumpkin_full_burnt_5096': { - 'hash': 5096, - 'name': 'pumpkin full burnt', - 'savables': { - 'MultiHandPickup': { - 'hash': 1556697998, - 'name': 'MultiHandPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'pumpkin_full_cooked': { - 'hash': 5010, - 'name': 'pumpkin full cooked', - 'embedded': { - 'Cooking_29126': { - 'hash': 29126, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'pumpkin_full_cooked_4574': { - 'hash': 4574, - 'name': 'pumpkin full cooked', - 'savables': { - 'MultiHandPickup': { - 'hash': 1556697998, - 'name': 'MultiHandPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } - } - }, - 'pumpkin_full_ripe': { - 'hash': 4488, - 'name': 'pumpkin full ripe', - 'embedded': { - 'Chisel_Handler_32690': { - 'hash': 32690, - 'name': 'Chisel Handler', - 'savables': {} - }, - 'Cooking_28436': { - 'hash': 28436, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'pumpkin_full_ripe_4052': { - 'hash': 4052, - 'name': 'pumpkin full ripe', - 'savables': { - 'MultiHandPickup': { - 'hash': 1556697998, - 'name': 'MultiHandPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } + + let lastHash = 0; + + for (let index = 0; index < expectedCount; ++index) { + const isHash = index % 2 === 0; + + if (isHash) { + lastHash = Number(versionPairs[index]); + } else { + componentVersions.set(lastHash, Number(versionPairs[index])); } } } - }, - 'pumpkin_full_unripe': { - 'hash': 3966, - 'name': 'pumpkin full unripe', - 'embedded': { - 'pumpkin_full_unripe_3530': { - 'hash': 3530, - 'name': 'pumpkin full unripe', - 'savables': { - 'MultiHandPickup': { - 'hash': 1556697998, - 'name': 'MultiHandPickup' - }, - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers, options).toBinaryString(); + const reader = new BinaryReader(data); + + return Prefab.fromBinary(reader, componentVersions); + } + + /** + * Gets the spin (vector) on the prefab. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Stone'>.fromSaveString('...'); + * + * const angularVelocity = prefab.getAngularVelocity(); + * const { x, y, z } = angularVelocity; + */ + getAngularVelocity(): Velocity { + return this.components.NetworkRigidbody?.angularVelocity ?? { x: 0, y: 0, z: 0 }; + } + + /** + * Finds the first child prefab matching the given name. If there are multiple child prefabs with + * the same name, you can use the second argument to provide a parent hash to match against. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Handle_Short'); + * + * prefab.addChildPrefab('Slot_Large_SwordType_Craft_6134', new Prefab('Guard')); + * + * const childGuard = prefab.getChildPrefab('Guard'); + * // `childGuard` is an instance of `Prefab<'Guard'>` + * + * const childPommel = prefab.getChildPrefab('Pommel'); + * // `childPommel` is `undefined` + */ + getChildPrefab( + prefabName: TChildPrefabName, + parentHash?: number + ): Prefab | undefined { + const child = this.children.find(child => + child.prefab.name === prefabName && typeof parentHash === 'undefined' ? true : child.parentHash === parentHash + ); + + if (typeof child === 'undefined') return undefined; + + return child.prefab as Prefab; + } + + /** + * Gets a map of component hashes and the versions used on this prefab. Will throw an error if the + * prefab uses mixed versions of a particular component. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + * + * const componentVersions = prefab.getComponentVersions(); + */ + getComponentVersions(): Map { + const versions = new Map(); + + function setComponentVersion(hash: number, version: number): ReturnType['set']> { + const storedVersion = versions.get(hash); + + if (typeof storedVersion !== 'undefined' && storedVersion !== version) { + throw new Error( + `Component ${hash} exists with version ${storedVersion} and ${version}. All instances of a component must exist with the same version.` + ); } + + return versions.set(hash, version); } - }, - 'pumpkin_half_burnt': { - 'hash': 3444, - 'name': 'pumpkin half burnt', - 'embedded': { - 'Cooking_42504': { - 'hash': 42504, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'pumpkin_half_burnt_3136': { - 'hash': 3136, - 'name': 'pumpkin half burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } + + /* Get component versions from prefab components. */ + for (const component of Object.values(this.components)) { + if (Array.isArray(component)) { + for (const unknownComponent of component) { + setComponentVersion(unknownComponent.hash, unknownComponent.version); } + } else { + setComponentVersion(component.hash, component.version); } } - }, - 'pumpkin_half_cooked': { - 'hash': 3082, - 'name': 'pumpkin half cooked', - 'embedded': { - 'Cooking_41658': { - 'hash': 41658, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'pumpkin_half_cooked_2774': { - 'hash': 2774, - 'name': 'pumpkin half cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' + + /* Get component versions from prefab entities. */ + for (const entity of Object.values(this.entities)) { + for (const component of Object.values(entity.components)) { + if (Array.isArray(component)) { + for (const unknownComponent of component) { + setComponentVersion(unknownComponent.hash, unknownComponent.version); } + } else { + setComponentVersion(component.hash, component.version); } } } - }, - 'pumpkin_half_ripe': { - 'hash': 2720, - 'name': 'pumpkin half ripe', - 'embedded': { - 'Cooking_40786': { - 'hash': 40786, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'pumpkin_half_ripe_2412': { - 'hash': 2412, - 'name': 'pumpkin half ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } + + /* Get component versions from child prefabs. */ + for (const { prefab } of this.children) { + const componentVersions = prefab.getComponentVersions(); + + for (const [hash, version] of componentVersions.entries()) { + setComponentVersion(hash, version); } } - }, - 'pumpkin_half_unripe': { - 'hash': 2358, - 'name': 'pumpkin half unripe', - 'embedded': { - 'pumpkin_half_unripe_2050': { - 'hash': 2050, - 'name': 'pumpkin half unripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } + + return versions; + } + + /** + * Gets the gift sender's name, which is labeled on the gift. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Gift_Mail_Box'>.fromSaveString('...'); + * + * const giftBoxLabel = prefab.getGiftBoxLabel(); + */ + getGiftBoxLabel(): string { + return this.components.SentGift?.senderName ?? ''; + } + + /** + * Gets the prefab's physical integrity. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + * + * const integrity = prefab.getIntegrity(); + */ + getIntegrity(): number { + return this.components.DurabilityModule?.integrity ?? 1; + } + + /** + * Gets the {@link https://docs.unity3d.com/ScriptReference/Rigidbody-isKinematic.html kinematic} + * state of the prefab. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + * + * const isKinematic = prefab.getKinematic(); + */ + getKinematic(): boolean { + return this.components.NetworkRigidbody?.isKinematic ?? false; + } + + /** + * Gets the prefab's physical material. + * + * @example + * import { PhysicalMaterialPartHash, Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Guard'>.fromSaveString('...'); + * + * const materialHash = prefab.getMaterial(); + * const materialName = PhysicalMaterialPartHash[materialHash]; + */ + getMaterial(): PhysicalMaterialPartHash { + return this.components.PhysicalMaterialPart?.materialHash ?? 0; + } + + /** + * Gets the burning state of the prefab. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Grass_Clump'>.fromSaveString('...'); + * + * const isOnFire = prefab.getOnFire(); + */ + getOnFire(): boolean { + const fireEntity = Object.values(this.entities).find(entity => entity.name === 'Fire'); + + return fireEntity?.components.HeatSourceBase?.isLit ?? false; + } + + /** + * Gets the position of the prefab. If the prefab is a child of another prefab, then this position + * is local to that parent. Otherwise, this position is in world space. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + * + * const position = prefab.getPosition(); + * const { x, y, z } = position; + */ + getPosition(): Position { + return this.position; + } + + /** + * Gets the rotation of the prefab. If the prefab is a child of another prefab, then this rotation + * is local to that parent. Otherwise, this rotation is in world space. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + * + * const rotation = prefab.getRotation(); + * const { x, y, z, w } = rotation; + */ + getRotation(): Rotation { + return this.rotation; + } + + /** + * Gets the scale of the prefab. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + * + * const scale = prefab.getScale(); + */ + getScale(): number { + return this.scale; + } + + /** + * Gets the {@link https://docs.unity3d.com/Manual/RigidbodiesOverview.html sleeping} + * state of the prefab. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + * + * const isServerSleeping = prefab.getServerSleeping(); + */ + getServerSleeping(): boolean { + return this.components.NetworkRigidbody?.isServerSleeping ?? false; + } + + /** + * Gets the number of servings on a liquid container prefab. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Potion_Medium'>.fromSaveString('...'); + * + * const servings = prefab.getServings(); + */ + getServings(): number { + return this.components.LiquidContainer?.contentLevel ?? 0; + } + + /** + * Gets the name of the spawn area population, if there is one. Returns `undefined` otherwise. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Disk_Encounter'>.fromSaveString('...'); + * + * const populationName = prefab.getSpawnAreaPopulationName(); + */ + getSpawnAreaPopulationName(): 'Unknown' | PopulationDefinitionName | undefined { + const populationDefinitionHash = this.components.PopulationSpawnArea?.definition as + | PopulationDefinitionHash + | undefined; + const populationDefinitionName = + typeof populationDefinitionHash === 'undefined' + ? undefined + : (PopulationDefinitionHash[populationDefinitionHash] as PopulationDefinitionName | undefined) ?? 'Unknown'; + + return populationDefinitionName; + } + + /** + * Gets the direction (vector) on the prefab. Units are in metres per second. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Stone'>.fromSaveString('...'); + * + * const velocity = prefab.getVelocity(); + * const { x, y, z } = velocity; + */ + getVelocity(): Velocity { + return this.components.NetworkRigidbody?.velocity ?? { x: 0, y: 0, z: 0 }; + } + + /** + * Prints this prefab's data structure to the console. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + * + * prefab.inspect(); + */ + inspect(): Prefab> { + process.stdout.write(`${inspect(this, false, null)}\n`); + + return this; + } + + /** + * Prints this prefab's `SaveString` to the console. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + * + * prefab.print(); + */ + print(): Prefab> { + const saveString = this.toSaveString(); + process.stdout.write(`${saveString}\n`); + + return this; + } + + /** + * Removes all child `Prefab` from this prefab. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + * + * prefab.removeAllChildPrefabs(); + */ + removeAllChildPrefabs(): Prefab> { + this.children = []; + + return this; + } + + /** + * Removes all components on this prefab. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + * + * prefab.removeAllComponents(); + */ + removeAllComponents(): Prefab> { + this.components = { Unknown: [] }; + + return this; + } + + /** + * Removes all entities on this prefab. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + * + * prefab.removeAllEntities(); + */ + removeAllEntities(): Prefab> { + this.entities = {}; + + return this; + } + + /** + * Removes all gift `Prefab` from this prefab. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Gift_Mail_Box'>.fromSaveString('...'); + * + * prefab.removeAllGifts(); + */ + removeAllGifts(): Prefab> { + const sentGiftComponent = this.components.SentGift; + + if (typeof sentGiftComponent !== 'undefined') { + sentGiftComponent.gifts = []; } - }, - 'pumpkin_piece_burnt': { - 'hash': 42218, - 'name': 'pumpkin piece burnt', - 'embedded': { - 'Cooking_63858': { - 'hash': 63858, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'pumpkin_piece_burnt_41976': { - 'hash': 41976, - 'name': 'pumpkin piece burnt', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } + + return this; + } + + /** + * Removes the specified child `Prefab` from this prefab. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + * + * prefab.removeChildPrefab(51672); + * // or + * prefab.removeChildPrefab('Guard'); + */ + removeChildPrefab(prefabHash: ATTPrefabHash): Prefab>; + removeChildPrefab(prefabName: ATTPrefabName): Prefab>; + removeChildPrefab(prefabArg: ATTPrefabHash | ATTPrefabName): Prefab> { + if (typeof prefabArg === 'undefined') { + throw new Error('You must pass a child prefab hash or name to remove from this prefab.'); } - }, - 'pumpkin_piece_cooked': { - 'hash': 41930, - 'name': 'pumpkin piece cooked', - 'embedded': { - 'Cooking_65232': { - 'hash': 65232, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'pumpkin_piece_cooked_41654': { - 'hash': 41654, - 'name': 'pumpkin piece cooked', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } - } - } + + const key = typeof prefabArg === 'number' ? 'hash' : 'name'; + + this.children = [...this.children.filter(child => child.prefab[key] !== prefabArg)]; + + return this; + } + + /** + * Removes the specified component from this prefab. + * + * @example + * import { ComponentHash, Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + * + * prefab.removeComponent(ComponentHash.NetworkRigidbody); + * // or + * prefab.removeComponent('NetworkRigidbody'); + */ + removeComponent(componentHash: ComponentHash): Prefab>; + removeComponent(componentName: keyof Omit): Prefab>; + removeComponent( + componentArg: ComponentHash | keyof Omit + ): Prefab> { + if (typeof componentArg === 'undefined') { + throw new Error('You must pass a component hash or name to remove from this prefab.'); } - }, - 'pumpkin_piece_ripe': { - 'hash': 41608, - 'name': 'pumpkin piece ripe', - 'embedded': { - 'Cooking_26172': { - 'hash': 26172, - 'name': 'Cooking', - 'savables': { - 'Cookable': { - 'hash': 205333986, - 'name': 'Cookable' - }, - 'HeatPointCollection': { - 'hash': 1217391130, - 'name': 'HeatPointCollection' - } - } - }, - 'pumpkin_piece_ripe_41332': { - 'hash': 41332, - 'name': 'pumpkin piece ripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - } + + const componentName = + typeof componentArg === 'string' + ? componentArg + : (ComponentHash[componentArg] as keyof typeof ComponentHash | undefined); + + if (typeof componentName === 'undefined') { + for (const component of Object.values(this.components)) { + if (Array.isArray(component)) { + this.components.Unknown = component.filter(unknownComponent => unknownComponent.hash !== componentArg); + } else if (component.hash === componentArg) { + delete this.components[component.name as keyof Omit]; + } + } + } else { + if (componentName in this.components) { + delete this.components[componentName]; + } else { + const unknownComponentIndex = this.components.Unknown.findIndex(component => component.name === componentArg); + + if (unknownComponentIndex > -1) { + this.components.Unknown = this.components.Unknown.toSpliced(unknownComponentIndex, 1); } } } - }, - 'pumpkin_piece_unripe': { - 'hash': 41286, - 'name': 'pumpkin piece unripe', - 'embedded': { - 'pumpkin_piece_unripe_41010': { - 'hash': 41010, - 'name': 'pumpkin piece unripe', - 'savables': { - 'NetworkRigidbody': { - 'hash': 2290978823, - 'name': 'NetworkRigidbody' - }, - 'Pickup': { - 'hash': 1454441398, - 'name': 'Pickup' - }, - 'PickupDecay': { - 'hash': 2807522140, - 'name': 'PickupDecay' - }, - 'RaycastCrafter': { - 'hash': 2815374842, - 'name': 'RaycastCrafter' - } - } - } + + return this; + } + + /** + * Removes the specified entity from this prefab. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Handle_Short'>.fromSaveString('...'); + * + * prefab.removeEntity('Slot_Multi_6136'); + */ + removeEntity(entityKey: Exclude, 'Unknown'>): Prefab> { + if (typeof entityKey === 'undefined') { + throw new Error('You must pass an entity name to remove from this prefab.'); } - }, - 'ruins_orbBasin_01': { - 'hash': 27482, - 'name': 'ruins_orbBasin_01', - 'embedded': { - 'Hand_Touch_46540': { - 'hash': 46540, - 'name': 'Hand Touch', - 'savables': { - 'AddUnlockToPlayer': { - 'hash': 1756836969, - 'name': 'AddUnlockToPlayer' - }, - 'OrbBasinVfxController': { - 'hash': 715394364, - 'name': 'OrbBasinVfxController' - }, - 'PlayerUnlockStation': { - 'hash': 2912807649, - 'name': 'PlayerUnlockStation' - } - } - }, - 'ruins_orbBasin_01_24754': { - 'hash': 24754, - 'name': 'ruins_orbBasin_01', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - } + + delete this.entities[entityKey as string]; + + return this; + } + + /** + * Removes the specified gift `Prefab` from this prefab. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Gift_Mail_Box'>.fromSaveString('...'); + * + * prefab.removeGift(31326); + * // or + * prefab.removeGift('Dynamite'); + */ + removeGift(prefabHash: ATTPrefabHash): Prefab>; + removeGift(prefabName: ATTPrefabName): Prefab>; + removeGift(prefabArg: ATTPrefabHash | ATTPrefabName): Prefab> { + if (typeof prefabArg === 'undefined') { + throw new Error('You must pass a gift prefab hash or name to remove from this prefab.'); } - }, - 'ruins_orbBasin_01TEST': { - 'hash': 58180, - 'name': 'ruins_orbBasin_01TEST', - 'embedded': { - 'Hand_Touch_46540': { - 'hash': 46540, - 'name': 'Hand Touch', - 'savables': { - 'AddUnlockToPlayer': { - 'hash': 1756836969, - 'name': 'AddUnlockToPlayer' - }, - 'OrbBasinVfxController': { - 'hash': 715394364, - 'name': 'OrbBasinVfxController' - }, - 'PlayerUnlockStation': { - 'hash': 2912807649, - 'name': 'PlayerUnlockStation' - } - } - }, - 'ruins_orbBasin_01TEST_58178': { - 'hash': 58178, - 'name': 'ruins_orbBasin_01TEST', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - } + + const hash = + typeof prefabArg === 'number' ? prefabArg : (ATTPrefabs[prefabArg]?.hash as ATTPrefabHash | undefined) ?? 0; + + const sentGiftComponent = this.components.SentGift; + + if (typeof sentGiftComponent !== 'undefined') { + sentGiftComponent.gifts = [...sentGiftComponent.gifts.filter(gift => gift?.hash !== hash)]; } - }, - 'ruins_orbBasin_01_Variant': { - 'hash': 13294, - 'name': 'ruins_orbBasin_01 Variant', - 'embedded': { - 'Hand_Touch_46540': { - 'hash': 46540, - 'name': 'Hand Touch', - 'savables': { - 'AddUnlockToPlayer': { - 'hash': 1756836969, - 'name': 'AddUnlockToPlayer' - }, - 'OrbBasinVfxController': { - 'hash': 715394364, - 'name': 'OrbBasinVfxController' - }, - 'PlayerUnlockStation': { - 'hash': 2912807649, - 'name': 'PlayerUnlockStation' - } - } - }, - 'ruins_orbBasin_01_Variant_24754': { - 'hash': 24754, - 'name': 'ruins_orbBasin_01 Variant', - 'savables': { - 'AdditionalStaticContent': { - 'hash': 1908922854, - 'name': 'AdditionalStaticContent' - } - } - } + + return this; + } + + /** + * Removes the spawn area components from the prefab. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = Prefab<'Disk_Encounter'>.fromSaveString('...'); + * + * prefab.removeSpawnArea(); + */ + removeSpawnArea(): Prefab> { + delete this.components.PopulationSpawnArea; + delete this.components.SpawnArea; + + return this; + } + + /** + * Sets a spin (vector) on the prefab, causing the physics engine to apply a force to it when + * spawning. Units are in metres per second. Only works reliably on the parent prefab. Does not + * work on kinematic prefabs. Does not work on static prefabs. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Stone'); + * + * prefab.setAngularVelocity({ x: 420, y: 69, z: 1337 }); + */ + setAngularVelocity({ x, y, z }: AngularVelocity): Prefab> { + if (isSavableComponent('NetworkRigidbody', this.name)) { + const version = this.components.NetworkRigidbody?.version ?? FALLBACK_NETWORK_RIGIDBODY_VERSION; + const angularVelocity: AngularVelocity = { x, y, z }; + + this.components.NetworkRigidbody = new NetworkRigidbodyComponent({ + ...this.components.NetworkRigidbody, + version, + angularVelocity + }); } - }, - 'tallPot': { - 'hash': 23320, - 'name': 'tallPot', - 'embedded': {} - }, - 'timberBlock_1Long': { - 'hash': 34586, - 'name': 'timberBlock_1Long', - 'embedded': { - 'timberBlock_1Long_46178': { - 'hash': 46178, - 'name': 'timberBlock_1Long', - 'savables': {} - } + + return this; + } + + /** + * Sets the gift sender's name, which is labeled on the gift. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Gift_Mail_Box'); + * + * prefab.setGiftBoxLabel('topkek'); + */ + setGiftBoxLabel(label: string): Prefab> { + if (typeof label === 'undefined') { + throw new Error('You must pass a string to set as the gift box label.'); } - }, - 'timberBlock_2Long': { - 'hash': 1898, - 'name': 'timberBlock_2Long', - 'embedded': { - 'timberBlock_2Long_372': { - 'hash': 372, - 'name': 'timberBlock_2Long', - 'savables': {} - } + + if (isSavableComponent('SentGift', this.name)) { + const version = this.components.SentGift?.version ?? FALLBACK_SENT_GIFT_VERSION; + + this.components.SentGift = new SentGiftComponent({ + ...this.components.SentGift, + version, + senderName: label + }); } - }, - 'timberBlock_3Long': { - 'hash': 1900, - 'name': 'timberBlock_3Long', - 'embedded': { - 'timberBlock_3Long_376': { - 'hash': 376, - 'name': 'timberBlock_3Long', - 'savables': {} - } + + return this; + } + + /** + * Sets the prefab's integrity. This can change both its appearance and other qualities such as + * durability and the amount of materials recovered from recycling. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Handle_Short'); + * + * prefab.setIntegrity(0.69); + */ + setIntegrity(integrity: number): Prefab> { + if (typeof integrity === 'undefined') { + throw new Error('You must pass a number to set as the integrity.'); } - }, - 'woodenPlatform_1x1': { - 'hash': 50942, - 'name': 'woodenPlatform_1x1', - 'embedded': { - 'woodenPlatform_1x1_4914': { - 'hash': 4914, - 'name': 'woodenPlatform_1x1', - 'savables': {} - } + + if (isSavableComponent('DurabilityModule', this.name)) { + const version = this.components.DurabilityModule?.version ?? FALLBACK_DURABILITY_MODULE_VERSION; + + this.components.DurabilityModule = new DurabilityModuleComponent({ + ...this.components.DurabilityModule, + version, + integrity + }); } - }, - 'woodenPlatform_1x1_Torch': { - 'hash': 64260, - 'name': 'woodenPlatform_1x1 Torch', - 'embedded': { - 'Torch_Dock_15254': { - 'hash': 15254, - 'name': 'Torch Dock', - 'savables': { - 'PickupDock': { - 'hash': 2592242915, - 'name': 'PickupDock' - } - } - }, - 'woodenPlatform_1x1_Torch_64256': { - 'hash': 64256, - 'name': 'woodenPlatform_1x1 Torch', - 'savables': {} - } + + return this; + } + + /** + * Makes the prefab {@link https://docs.unity3d.com/ScriptReference/Rigidbody-isKinematic.html kinematic}. + * By default, a `new Prefab()` is not kinematic, but some prefabs require to be kinematic to work + * properly. You can optionally pass a boolean, for example `prefab.setKinematic(false)`. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Handle_Short'); + * + * prefab.setKinematic(true); + */ + setKinematic(isKinematic?: boolean): Prefab> { + if (isSavableComponent('NetworkRigidbody', this.name)) { + const version = this.components.NetworkRigidbody?.version ?? FALLBACK_NETWORK_RIGIDBODY_VERSION; + + this.components.NetworkRigidbody = new NetworkRigidbodyComponent({ + ...this.components.NetworkRigidbody, + version, + isKinematic: isKinematic ?? true + }); } - }, - 'woodenPlatform_1x2': { - 'hash': 50950, - 'name': 'woodenPlatform_1x2', - 'embedded': { - 'woodenPlatform_1x2_4598': { - 'hash': 4598, - 'name': 'woodenPlatform_1x2', - 'savables': {} - } + + return this; + } + + /** + * Sets the prefab's physical material. This can change both its appearance and other qualities such + * as durability, damage, heat retention and weight. + * + * @example + * import { PhysicalMaterialPartHash, Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Handle_Short'); + * + * prefab.setMaterial(PhysicalMaterialPartHash.Mythril); + * // or + * prefab.setMaterial('Mythril'); + */ + setMaterial(materialHash: PhysicalMaterialPartHash): Prefab>; + setMaterial(materialName: keyof typeof PhysicalMaterialPartHash): Prefab>; + setMaterial( + materialArg: PhysicalMaterialPartHash | keyof typeof PhysicalMaterialPartHash + ): Prefab> { + if (typeof materialArg === 'undefined') { + throw new Error('You must pass a PhysicalMaterialPartHash to set as the material.'); } - }, - 'woodenPlatform_Railings_1x1': { - 'hash': 50946, - 'name': 'woodenPlatform_Railings_1x1', - 'embedded': { - 'woodenPlatform_Railings_1x1_4200': { - 'hash': 4200, - 'name': 'woodenPlatform_Railings_1x1', - 'savables': {} - } + + if (isSavableComponent('PhysicalMaterialPart', this.name)) { + const version = this.components.PhysicalMaterialPart?.version ?? FALLBACK_PHYSICAL_MATERIAL_PART_VERSION; + const materialHash = typeof materialArg === 'number' ? materialArg : PhysicalMaterialPartHash[materialArg]; + + this.components.PhysicalMaterialPart = new PhysicalMaterialPartComponent({ + ...this.components.PhysicalMaterialPart, + version, + materialHash + }); } - }, - 'woodenPlatform_Stairs_02': { - 'hash': 50940, - 'name': 'woodenPlatform_Stairs_02', - 'embedded': { - 'woodenPlatform_Stairs_02_3900': { - 'hash': 3900, - 'name': 'woodenPlatform_Stairs_02', - 'savables': {} - } + + return this; + } + + /** + * Sets the prefab on fire, if it is capable of catching fire. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Grass_Clump'); + * + * prefab.setOnFire(true); + */ + setOnFire(isLit?: boolean): Prefab> { + const validFireEntity = Object.values<{ + hash: number; + name: string; + savables: Record; + }>(ATTPrefabs[this.name].embedded).find(entity => { + return Object.values(entity.savables).some(savable => ['Fire', 'FireDissolve'].includes(savable.name)); + }); + + if (typeof validFireEntity !== 'undefined') { + const currentFireEntity = Object.values(this.entities).find(entity => entity.name === validFireEntity.name); + const version = currentFireEntity?.components.HeatSourceBase?.version ?? FALLBACK_HEAT_SOURCE_BASE_VERSION; + const key = `${validFireEntity.name}_${validFireEntity.hash}`; + + this.entities[key] = new Entity(key as keyof (typeof ATTPrefabs)[TPrefabName]['embedded'], { + hash: validFireEntity.hash, + isAlive: true, + components: { + ...currentFireEntity?.components, + HeatSourceBase: new HeatSourceBaseComponent({ + version, + isLit: isLit ?? true + }) + } + }); } - }, - 'woodenPlatform_T2x1': { - 'hash': 50944, - 'name': 'woodenPlatform_T2x1', - 'embedded': { - 'woodenPlatform_T2x1_3592': { - 'hash': 3592, - 'name': 'woodenPlatform_T2x1', - 'savables': {} - } + + return this; + } + + /** + * Sets the position of the prefab. If the prefab is a child of another prefab, then this position + * is local to that parent. Otherwise, this position is in world space. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Stone'); + * + * prefab.setPosition({ x: 420, y: 69, z: 1337 }); + */ + setPosition({ x, y, z }: Position): Prefab> { + const position: Position = { x, y, z }; + this.position = position; + + if (isSavableComponent('NetworkRigidbody', this.name)) { + const version = this.components.NetworkRigidbody?.version ?? FALLBACK_NETWORK_RIGIDBODY_VERSION; + + this.components.NetworkRigidbody = new NetworkRigidbodyComponent({ + ...this.components.NetworkRigidbody, + version, + position + }); } - }, - 'woodenPlatform_T2x1_1': { - 'hash': 50930, - 'name': 'woodenPlatform_T2x1 1', - 'embedded': { - 'woodenPlatform_T2x1_1_3278': { - 'hash': 3278, - 'name': 'woodenPlatform_T2x1 1', - 'savables': {} - } + + return this; + } + + /** + * Sets the rotation of the prefab. If the prefab is a child of another prefab, then this rotation + * is local to that parent. Otherwise, this rotation is in world space. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Stone'); + * + * prefab.setRotation({ x: 0.42, y: -0.69, z: 0.1337, w: -0.88 }); + */ + setRotation({ x, y, z, w }: Rotation): Prefab> { + const rotation: Rotation = { x, y, z, w }; + this.rotation = rotation; + + if (isSavableComponent('NetworkRigidbody', this.name)) { + const version = this.components.NetworkRigidbody?.version ?? FALLBACK_NETWORK_RIGIDBODY_VERSION; + + this.components.NetworkRigidbody = new NetworkRigidbodyComponent({ + ...this.components.NetworkRigidbody, + version, + rotation + }); } - }, - 'woodenPlatform_W2x2': { - 'hash': 50932, - 'name': 'woodenPlatform_W2x2', - 'embedded': { - 'woodenPlatform_W2x2_2856': { - 'hash': 2856, - 'name': 'woodenPlatform_W2x2', - 'savables': {} - } + + return this; + } + + /** + * Sets the scale of the prefab. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Stone'); + * + * prefab.setScale(0.69); + */ + setScale(scale: number): Prefab> { + if (typeof scale === 'undefined') { + throw new Error('You must pass a number to set as the scale.'); } - }, - 'woodenPlatform_W2x3': { - 'hash': 10176, - 'name': 'woodenPlatform_W2x3', - 'embedded': { - 'Breakable_Population_Area_32244': { - 'hash': 32244, - 'name': 'Breakable Population Area', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'SpawnArea': { - 'hash': 2617495528, - 'name': 'SpawnArea' - } - } - }, - 'woodenPlatform_W2x3_10188': { - 'hash': 10188, - 'name': 'woodenPlatform_W2x3', - 'savables': {} - } + + this.scale = scale; + + return this; + } + + /** + * Makes the prefab {@link https://docs.unity3d.com/Manual/RigidbodiesOverview.html sleep}. + * By default, a `new Prefab()` is not sleeping. A sleeping prefab does not have its physics + * simulated until it receives a collision or force, such as touching it. You can optionally pass + * a boolean, for example `prefab.setServerSleeping(false)`. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Handle_Short'); + * + * prefab.setServerSleeping(true); + */ + setServerSleeping(isServerSleeping?: boolean): Prefab> { + if (isSavableComponent('NetworkRigidbody', this.name)) { + const version = this.components.NetworkRigidbody?.version ?? FALLBACK_NETWORK_RIGIDBODY_VERSION; + + this.components.NetworkRigidbody = new NetworkRigidbodyComponent({ + ...this.components.NetworkRigidbody, + version, + isServerSleeping: isServerSleeping ?? true + }); } - }, - 'woodenPlatform_W2x4': { - 'hash': 33664, - 'name': 'woodenPlatform_W2x4', - 'embedded': { - 'Breakable_Population_Area_35954': { - 'hash': 35954, - 'name': 'Breakable Population Area', - 'savables': { - 'PopulationSpawnArea': { - 'hash': 3070493599, - 'name': 'PopulationSpawnArea' - }, - 'SpawnArea': { - 'hash': 2617495528, - 'name': 'SpawnArea' - } - } - }, - 'woodenPlatform_W2x4_33680': { - 'hash': 33680, - 'name': 'woodenPlatform_W2x4', - 'savables': {} - } + + return this; + } + + /** + * Sets the number of servings on a liquid container prefab. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Potion_Medium'); + * + * prefab.setServings(69); + */ + setServings(servings: number): Prefab> { + if (typeof servings === 'undefined') { + throw new Error('You must pass a number to set as the amount of servings.'); + } + + if (isSavableComponent('LiquidContainer', this.name)) { + const version = this.components.LiquidContainer?.version ?? FALLBACK_LIQUID_CONTAINER_VERSION; + + this.components.LiquidContainer = new LiquidContainerComponent({ + ...this.components.LiquidContainer, + version, + contentLevel: Math.max(0, Math.ceil(servings)), + hasContent: Math.ceil(servings) > 0 + }); } + + return this; } -}; + + /** + * Sets a spawn area on the prefab with the given population and any additional configuration. + * + * @example + * import { PopulationDefinitionHash, Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Disk_Encounter'); + * + * prefab.setSpawnArea(PopulationDefinitionHash.WyrmPopulation, { + * currentPopulation: 5, + * isOneOff: false, + * isPopulationStarted: true, + * maxPopulation: 20, + * numberOfSpawnPoints: 40, + * size: 5, + * startingPopulation: 5 + * }); + */ + setSpawnArea( + populationDefinitionHash: PopulationDefinitionHash, + props?: SetSpawnAreaProps + ): Prefab>; + setSpawnArea( + populationDefinitionName: PopulationDefinitionName, + props?: SetSpawnAreaProps + ): Prefab>; + setSpawnArea( + populationDefinitionArg: PopulationDefinitionHash | PopulationDefinitionName, + props: SetSpawnAreaProps = {} + ): Prefab> { + if (typeof populationDefinitionArg === 'undefined') { + throw new Error('You must pass a population definition hash or name to set on this spawn area.'); + } + + if (isSavableComponent('PopulationSpawnArea', this.name) && isSavableComponent('SpawnArea', this.name)) { + const populationDefinitionHash = + typeof populationDefinitionArg === 'number' + ? populationDefinitionArg + : PopulationDefinitionHash[populationDefinitionArg]; + + this.components.PopulationSpawnArea = new PopulationSpawnAreaComponent({ + ...this.components.PopulationSpawnArea, + version: this.components.PopulationSpawnArea?.version ?? FALLBACK_POPULATION_SPAWN_AREA_VERSION, + definition: populationDefinitionHash, + isPopulationStarted: props.isPopulationStarted, + maxPopulation: props.maxPopulation, + currentPopulation: props.currentPopulation, + numberOfSpawnPoints: props.numberOfSpawnPoints, + startingPopulation: props.startingPopulation, + isOneOff: props.isOneOff + }); + + this.components.SpawnArea = new SpawnAreaComponent({ + ...this.components.SpawnArea, + version: this.components.SpawnArea?.version ?? FALLBACK_SPAWN_AREA_VERSION, + size: props.size + }); + } + + return this; + } + + /** + * Sets a direction (vector) on the prefab, causing the physics engine to apply a force to it when + * spawning. Units are in metres per second. Only works reliably on the parent prefab. Does not work + * on kinematic prefabs. Does not work on static prefabs. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Stone'); + * + * prefab.setVelocity({ x: 420, y: 69, z: 1337 }); + */ + setVelocity({ x, y, z }: Velocity): Prefab> { + if (isSavableComponent('NetworkRigidbody', this.name)) { + const version = this.components.NetworkRigidbody?.version ?? FALLBACK_NETWORK_RIGIDBODY_VERSION; + const velocity: Velocity = { x, y, z }; + + this.components.NetworkRigidbody = new NetworkRigidbodyComponent({ + ...this.components.NetworkRigidbody, + version, + velocity + }); + } + + return this; + } + + /** + * Returns a `BinaryString` representation of the prefab. + * + * @example + * import { ComponentHash, Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Stone'); + * + * const componentVersions = prefab.getComponentVersions(); + * // or + * const componentVersions = new Map([ + * [ComponentHash.NetworkRigidbody, 1], + * [ComponentHash.PhysicalMaterialPart, 1], + * [ComponentHash.Pickup, 2] + * // etc... + * ]); + * + * const binaryString = prefab.toBinary(componentVersions); + */ + toBinary(componentVersions: Map): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {number} hash + */ + writer.writeUnsignedInteger(this.hash); + + /** + * @property {Position} position + */ + writer.writeFloat(this.position.x); + writer.writeFloat(this.position.y); + writer.writeFloat(this.position.z); + + /** + * @property {Rotation} rotation + */ + writer.writeFloat(this.rotation.x); + writer.writeFloat(this.rotation.y); + writer.writeFloat(this.rotation.z); + writer.writeFloat(this.rotation.w); + + /** + * @property {float} scale + */ + writer.writeFloat(this.scale); + + /** + * @property {PrefabComponents} components + */ + writeComponents(writer, this.components, componentVersions); + + /** + * @property {PrefabEntities} entities + */ + writeEntities(writer, this.entities, componentVersions); + + /** + * @property {PrefabChild[]} children + */ + writeChildren(writer, this.children, componentVersions); + + return writer.flush(); + } + + /** + * Returns the `SaveString` to spawn this prefab in the game. You may pass additional options to + * change the output behaviour. + * + * @example + * import { Prefab } from 'att-string-transcoder'; + * + * const prefab = new Prefab('Stone'); + * + * const saveString = prefab.toSaveString(); + */ + toSaveString(options: ToSaveStringOptions = {}): SaveString { + const componentVersions = this.getComponentVersions(); + const data = this.toBinary(componentVersions); + + const hasIndeterminateVersions = [...componentVersions.values()].includes(0); + + if (hasIndeterminateVersions && !options.ignoreIndeterminateComponentVersions) { + throw new Error( + 'Prefab contains components with version `0`. Current in-game versions for those components are not available. The produced save string will not contain component versions and may not be spawnable in-game.\n\nYou may call `.toSaveString(true)` to force producing a save string with this limitation.\n' + ); + } + + /* Pad bits with trailing zeroes to make it % 32. */ + const roundedUpDataLength = data.length + (32 - (data.length % 32 === 0 ? 32 : data.length % 32)); + const paddedData = data.padEnd(roundedUpDataLength, '0'); + + /* Calculate byte size of padded binary. */ + const bytes = paddedData.length / 8; + + /* Convert binary to array of unsigned integers. */ + const unsignedIntegers = new BinaryData(paddedData).toUnsignedIntegerArray(); + + /* Construct the binary data string. */ + const binaryDataString = [this.hash, bytes, ...unsignedIntegers].join(','); + + /* Construct the versions string. */ + let componentVersionsString: string | undefined; + + if (!hasIndeterminateVersions && componentVersions.size > 0) { + componentVersionsString = `${componentVersions.size},${[...componentVersions.entries()].map( + ([componentHash, componentVersion]) => `${componentHash},${componentVersion}` + )}`; + } + + /* Return SaveString. */ + const strings = [binaryDataString, !options.excludeComponentVersions && componentVersionsString].filter(Boolean); + return `${strings.join(',|')},` as SaveString; + } +} diff --git a/src/components/BasicDecayComponent.test.ts b/src/components/BasicDecayComponent.test.ts new file mode 100644 index 0000000..7bc1c4f --- /dev/null +++ b/src/components/BasicDecayComponent.test.ts @@ -0,0 +1,131 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { BasicDecayComponent } from './BasicDecayComponent.js'; + +const componentHash = ComponentHash.BasicDecay; +const componentName = 'BasicDecay'; +const componentVersion = 3; +const componentProps = { + isDisabled: false, + timelineEntry: 133742069 +}; + +describe('new BasicDecayComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the BasicDecayComponent class', () => { + const component = new BasicDecayComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(BasicDecayComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the BasicDecayComponent class', () => { + const component = new BasicDecayComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(BasicDecayComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.isDisabled).toStrictEqual(componentProps.isDisabled); + expect(component.timelineEntry).toStrictEqual(componentProps.timelineEntry); + }); + }); +}); + +describe('BasicDecayComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('Grass_Clump', { + components: { + BasicDecay: new BasicDecayComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // BasicDecayComponent hash. + reader.readUnsignedInteger(); // BasicDecayComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the BasicDecayComponent class', () => { + const component = BasicDecayComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(BasicDecayComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.isDisabled).toStrictEqual(componentProps.isDisabled); + expect(component.timelineEntry).toStrictEqual(componentProps.timelineEntry); + }); +}); + +describe('BasicDecayComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new BasicDecayComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = '00000011111111000101111011111010100000000000000000000000000000000'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('BasicDecayComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new BasicDecayComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '111000101001001010010011010100100000000000000000000000000100000100000011111111000101111011111010100000000000000000000000000000000'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // BasicDecayComponent data length. + const isDisabled = reader.readBoolean(); + const timelineEntry = reader.readUnsignedLong(); + + expect(hash).toStrictEqual(componentHash); + expect(isDisabled).toStrictEqual(componentProps.isDisabled); + expect(timelineEntry).toStrictEqual(componentProps.timelineEntry); + }); +}); diff --git a/src/components/BasicDecayComponent.ts b/src/components/BasicDecayComponent.ts new file mode 100644 index 0000000..f3a65d5 --- /dev/null +++ b/src/components/BasicDecayComponent.ts @@ -0,0 +1,122 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type BasicDecayComponentPropsV3 = { + isDisabled?: boolean | undefined; + timelineEntry?: number | undefined; +}; + +export type BasicDecayComponentProps = BasicDecayComponentPropsV3; + +const HUNDRED_YEARS_TICKS = 31557600000000000; + +/** + * @see [Class: `BasicDecayComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/BasicDecayComponent.md) + * @since v3.0.0 + * @version 3 + * + * @example + * import { BasicDecayComponent } from 'att-string-transcoder'; + * + * const componentVersion = 3; + * const component = new BasicDecayComponent({ version: componentVersion }); + */ +export class BasicDecayComponent extends Component { + /** + * @since v3 + * + * @example + * import { BasicDecayComponent } from 'att-string-transcoder'; + * + * const componentVersion = 3; + * const component = new BasicDecayComponent({ version: componentVersion }); + * + * const isDisabled = component.isDisabled; + * // `isDisabled` is `true` + */ + isDisabled: boolean; + + /** + * @since v3 + * + * @example + * import { BasicDecayComponent } from 'att-string-transcoder'; + * + * const componentVersion = 3; + * const component = new BasicDecayComponent({ version: componentVersion }); + * + * const timelineEntry = component.timelineEntry; + * // `timelineEntry` is `31557600000000000` + */ + timelineEntry: number; + + /** + * @see [Class: `BasicDecayComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/BasicDecayComponent.md) + * @since v3.0.0 + * @version 3 + * + * @example + * import { BasicDecayComponent } from 'att-string-transcoder'; + * + * const componentVersion = 3; + * const component = new BasicDecayComponent({ version: componentVersion }); + */ + constructor({ version, isDisabled, timelineEntry }: ComponentProps & BasicDecayComponentProps) { + const hash = ComponentHash.BasicDecay; + const name = 'BasicDecay'; + + super({ hash, name, version }); + + this.isDisabled = isDisabled ?? true; + this.timelineEntry = timelineEntry ?? HUNDRED_YEARS_TICKS; + } + + static override fromBinary(reader: BinaryReader, version: number): BasicDecayComponent { + const props: ComponentProps & BasicDecayComponentProps = { version }; + + /** + * @property {boolean} isDisabled + * @since v3 + */ + if (props.version >= 3) { + props.isDisabled = reader.readBoolean(); + } + + /** + * @property {number} timelineEntry + * @since v3 + */ + if (props.version >= 3) { + props.timelineEntry = reader.readUnsignedLong(); + } + + return new BasicDecayComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {boolean} isDisabled + * @since v3 + */ + if (version >= 3) { + writer.writeBoolean(this.isDisabled); + } + + /** + * @property {number} timelineEntry + * @since v3 + */ + if (version >= 3) { + writer.writeUnsignedLong(this.timelineEntry); + } + + return writer.flush(); + } +} diff --git a/src/components/Component.test.ts b/src/components/Component.test.ts new file mode 100644 index 0000000..2d9a842 --- /dev/null +++ b/src/components/Component.test.ts @@ -0,0 +1,120 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; + +import { Component } from './Component.js'; + +describe('new Component()', () => { + describe('when given the required props', () => { + it('returns an instance of the Component class', () => { + const componentHash = 1337; + const componentName = 'topkek'; + const componentVersion = 1; + + const component = new Component({ + hash: componentHash, + name: componentName, + version: componentVersion + }); + + expect(component).toBeInstanceOf(Component); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); +}); + +describe('Component.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + const prefab = new Prefab('Grass_Clump'); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // Component hash. + reader.readUnsignedInteger(); // Component data length. + + fastForwardedReader = reader; + }); + + it('throws an error', () => { + const componentHash = 1337; + const componentName = 'topkek'; + const componentVersion = 1; + const expectedToThrow = () => { + return Component.fromBinary(fastForwardedReader, componentVersion, componentHash, componentName, 1337); + }; + const expectedError = new Error( + 'Cannot instantiate base Component class from binary string data. You must call the fromBinary() method on the derived Component class.' + ); + + expect(expectedToThrow).toThrowError(expectedError); + }); +}); + +describe('Component.toBinary()', () => { + it('throws an error', () => { + const componentHash = 1337; + const componentName = 'topkek'; + const componentVersion = 1; + + const component = new Component({ + hash: componentHash, + name: componentName, + version: componentVersion + }); + + const expectedToThrow = () => component.toBinary(); + const expectedError = new Error( + 'Cannot encode base Component class. You must call the toBinary() method on the derived Component class.' + ); + + expect(expectedToThrow).toThrowError(expectedError); + }); +}); + +describe('Component.write()', () => { + it('throws an error', () => { + const componentHash = 1337; + const componentName = 'topkek'; + const componentVersion = 1; + + const component = new Component({ + hash: componentHash, + name: componentName, + version: componentVersion + }); + + const writer = new BinaryWriter(); + + const expectedToThrow = () => component.write(writer); + const expectedError = new Error( + 'Cannot encode base Component class. You must call the toBinary() method on the derived Component class.' + ); + + expect(expectedToThrow).toThrowError(expectedError); + }); +}); diff --git a/src/components/Component.ts b/src/components/Component.ts new file mode 100644 index 0000000..88a8aa5 --- /dev/null +++ b/src/components/Component.ts @@ -0,0 +1,146 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; + +type BaseComponentProps = { + hash: number; + name: string; +}; + +export type ComponentProps = { + version: number; +}; + +/** + * Base class for all components. This class should not be used directly. Use any of its derived + * classes instead. + * + * @see [Class: `Component`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/Component.md) + * @see [API Reference Documentation](https://github.com/mdingena/att-string-transcoder/tree/main/docs/README.md) + */ +export class Component { + /** + * The hash of the component. + * + * @example + * import { DerivedComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new DerivedComponent({ version: componentVersion }); + * + * const hash = component.hash; + */ + hash: number; + + /** + * The name of the component. + * + * @example + * import { DerivedComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new DerivedComponent({ version: componentVersion }); + * + * const name = component.name; + */ + name: string; + + /** + * The version of the component. This controls the shape of the component data and its + * (de)serialisation sequence when reading or writing binary data. + * + * @example + * import { DerivedComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new DerivedComponent({ version: componentVersion }); + * + * const version = component.version; + * // `version` is `1` + */ + version: number; + + /** + * Creates a versioned component. This constructor is used internally. You shouldn't create any + * instances of this base class. + * + * @see [Class: `Component`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/Component.md) + * @see [API Reference Documentation](https://github.com/mdingena/att-string-transcoder/tree/main/docs/README.md) + */ + constructor({ hash, name, version }: ComponentProps & BaseComponentProps) { + this.hash = hash; + this.name = name; + this.version = version; + } + + /** + * Reads the binary string data and returns an instantiated component. + * + * @example + * import { BinaryReader, DerivedComponent } from 'att-string-transcoder'; + * + * const reader = new BinaryReader('...'); + * const componentVersion = 1; + * + * const component = DerivedComponent.fromBinary(reader, componentVersion); + */ + static fromBinary(reader: BinaryReader, version: number, hash: number, name: string, dataLength: number): Component; + // eslint-disable-next-line @typescript-eslint/no-unused-vars + static fromBinary(_reader: BinaryReader, _version: number): Component { + throw new Error( + 'Cannot instantiate base Component class from binary string data. You must call the fromBinary() method on the derived Component class.' + ); + } + + /** + * Returns a `BinaryString` representation of the component. + * + * @example + * import { DerivedComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new DerivedComponent({ version: componentVersion }); + * + * const binaryString = component.toBinary(componentVersion); + */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + toBinary(_version = this.version): BinaryString { + throw new Error( + 'Cannot encode base Component class. You must call the toBinary() method on the derived Component class.' + ); + } + + /** + * Writes a `BinaryString` representation of the component to the given `BinaryWriter`, including + * the component hash and data length. + * + * @example + * import { BinaryWriter, DerivedComponent } from 'att-string-transcoder'; + * + * const writer = new BinaryWriter(); + * const componentVersion = 1; + * + * const component = new DerivedComponent({ version: componentVersion }); + * + * component.write(writer, componentVersion); + */ + write(writer: BinaryWriter, version = this.version): void { + const data = this.toBinary(version); + + /** + * @property {number} hash + */ + writer.writeUnsignedInteger(this.hash); + + /** + * @property {number} dataLength + */ + writer.writeUnsignedInteger(data.length); + + /** + * @property {BinaryString} data + */ + writer.writeBits(data); + } +} diff --git a/src/components/ComponentVersion.ts b/src/components/ComponentVersion.ts deleted file mode 100644 index aa4ce88..0000000 --- a/src/components/ComponentVersion.ts +++ /dev/null @@ -1,164 +0,0 @@ -export const ComponentVersion = new Map([ - [7704646, 1], - [22446553, 2], - [34507654, 1], - [43510150, 2], - [70871065, 1], - [159391088, 1], - [200292695, 3], - [205333986, 1], - [237360636, 2], - [259381630, 1], - [272188517, 1], - [276353327, 1], - [277505782, 2], - [309083880, 1], - [320224849, 1], - [391977879, 2], - [392234266, 3], - [392344172, 1], - [403040752, 2], - [496827038, 1], - [566175523, 1], - [586602603, 1], - [623957243, 1], - [634164392, 5], - [654225716, 1], - [661497638, 1], - [701033518, 1], - [715394364, 2], - [751359624, 1], - [766675725, 1], - [775321715, 2], - [788405183, 1], - [830106687, 1], - [875684520, 1], - [902024186, 1], - [910018632, 2], - [963907309, 1], - [967932020, 1], - [1001395212, 2], - [1063725326, 1], - [1081247904, 1], - [1085701614, 1], - [1098050191, 3], - [1176706580, 2], - [1198377566, 1], - [1211178616, 1], - [1217391130, 1], - [1228539097, 1], - [1233775263, 1], - [1257282635, 2], - [1268269765, 1], - [1390862571, 1], - [1391720462, 2], - [1431397437, 2], - [1454441398, 2], - [1454955908, 1], - [1499506132, 1], - [1509838052, 1], - [1558189723, 1], - [1587058252, 1], - [1588536425, 1], - [1624211074, 1], - [1645673210, 2], - [1651678475, 1], - [1714180166, 2], - [1753993206, 2], - [1756836969, 1], - [1776498660, 3], - [1787084913, 4], - [1823429789, 1], - [1871432223, 1], - [1874870249, 2], - [1908922854, 1], - [1923918202, 3], - [1931537627, 1], - [1934129787, 1], - [1962842866, 1], - [1964978567, 1], - [2026743731, 1], - [2069630919, 1], - [2081565440, 2], - [2120963769, 1], - [2126500253, 1], - [2127962967, 1], - [2169673426, 1], - [2190886200, 1], - [2253011220, 1], - [2262399392, 2], - [2272630171, 1], - [2290978823, 1], - [2293737711, 1], - [2314081177, 1], - [2363255897, 1], - [2400796504, 1], - [2443660852, 1], - [2450553269, 1], - [2495475500, 2], - [2498617949, 1], - [2563434699, 1], - [2563567105, 2], - [2576456808, 1], - [2590537994, 2], - [2592242915, 2], - [2610542999, 1], - [2617495528, 1], - [2624099526, 1], - [2629079826, 1], - [2700376822, 1], - [2759613175, 1], - [2801168996, 2], - [2814234626, 1], - [2815374842, 1], - [2833060406, 1], - [2880587164, 1], - [2882590463, 1], - [2912807649, 3], - [2951515968, 1], - [2971871217, 1], - [2975913730, 1], - [2978042925, 1], - [2978388169, 1], - [3070493599, 2], - [3084373371, 1], - [3101665521, 1], - [3109677933, 2], - [3146178080, 1], - [3171294583, 1], - [3188272159, 1], - [3202828999, 1], - [3230087383, 1], - [3236280681, 3], - [3245685963, 1], - [3257374625, 1], - [3373651539, 1], - [3402094521, 1], - [3431876266, 1], - [3445325106, 1], - [3450348902, 1], - [3457519710, 2], - [3538443740, 1], - [3561515449, 1], - [3588929783, 1], - [3608460219, 1], - [3638500874, 2], - [3640332570, 1], - [3642863935, 2], - [3665939353, 1], - [3674519521, 1], - [3704379512, 1], - [3751351177, 1], - [3801256786, 3], - [3820454400, 4], - [3901697682, 1], - [3920618075, 1], - [3932346318, 1], - [4081488368, 1], - [4095875831, 1], - [4109360768, 2], - [4134534481, 1], - [4144776006, 3], - [4179293747, 1], - [4282337604, 1] -]); diff --git a/src/components/DoorComponent.test.ts b/src/components/DoorComponent.test.ts new file mode 100644 index 0000000..7ef6151 --- /dev/null +++ b/src/components/DoorComponent.test.ts @@ -0,0 +1,125 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { DoorComponent } from './DoorComponent.js'; + +const componentHash = ComponentHash.Door; +const componentName = 'Door'; +const componentVersion = 1; +const componentProps = { + isOpen: true +}; + +describe('new DoorComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the DoorComponent class', () => { + const component = new DoorComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(DoorComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the DoorComponent class', () => { + const component = new DoorComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(DoorComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.isOpen).toStrictEqual(componentProps.isOpen); + }); + }); +}); + +describe('DoorComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('Grass_Clump', { + components: { + Door: new DoorComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // DoorComponent hash. + reader.readUnsignedInteger(); // DoorComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the DoorComponent class', () => { + const component = DoorComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(DoorComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.isOpen).toStrictEqual(componentProps.isOpen); + }); +}); + +describe('DoorComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new DoorComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = '1'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('DoorComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new DoorComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = '10011100011010001001010011000110000000000000000000000000000000011'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // DoorComponent data length. + const isOpen = reader.readBoolean(); + + expect(hash).toStrictEqual(componentHash); + expect(isOpen).toStrictEqual(componentProps.isOpen); + }); +}); diff --git a/src/components/DoorComponent.ts b/src/components/DoorComponent.ts new file mode 100644 index 0000000..ad798b3 --- /dev/null +++ b/src/components/DoorComponent.ts @@ -0,0 +1,90 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type DoorComponentPropsV1 = { + isOpen?: boolean | undefined; +}; + +export type DoorComponentProps = DoorComponentPropsV1; + +/** + * @see [Class: `DoorComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/DoorComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { DoorComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new DoorComponent({ version: componentVersion }); + */ +export class DoorComponent extends Component { + /** + * Reveals the open state of this component's prefab. + * + * @since v1 + * + * @example + * import { DoorComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new DoorComponent({ version: componentVersion }); + * + * const isOpen = component.isOpen; + * // `isOpen` is `false` + */ + isOpen: boolean; + + /** + * @see [Class: `DoorComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/DoorComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { DoorComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new DoorComponent({ version: componentVersion }); + */ + constructor({ version, isOpen }: ComponentProps & DoorComponentProps) { + const hash = ComponentHash.Door; + const name = 'Door'; + + super({ hash, name, version }); + + this.isOpen = isOpen ?? false; + } + + static override fromBinary(reader: BinaryReader, version: number): DoorComponent { + const props: ComponentProps & DoorComponentProps = { version }; + + /** + * @property {boolean} isOpen + * @since v1 + */ + if (props.version >= 1) { + props.isOpen = reader.readBoolean(); + } + + return new DoorComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {boolean} isOpen + * @since v1 + */ + if (version >= 1) { + writer.writeBoolean(this.isOpen); + } + + return writer.flush(); + } +} diff --git a/src/components/DurabilityModuleComponent.test.ts b/src/components/DurabilityModuleComponent.test.ts new file mode 100644 index 0000000..416198a --- /dev/null +++ b/src/components/DurabilityModuleComponent.test.ts @@ -0,0 +1,126 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { DurabilityModuleComponent } from './DurabilityModuleComponent.js'; + +const componentHash = ComponentHash.DurabilityModule; +const componentName = 'DurabilityModule'; +const componentVersion = 1; +const componentProps = { + integrity: 0.69 +}; + +describe('new DurabilityModuleComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the DurabilityModuleComponent class', () => { + const component = new DurabilityModuleComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(DurabilityModuleComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the DurabilityModuleComponent class', () => { + const component = new DurabilityModuleComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(DurabilityModuleComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.integrity).toBeCloseTo(componentProps.integrity, 2); + }); + }); +}); + +describe('DurabilityModuleComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('Grass_Clump', { + components: { + DurabilityModule: new DurabilityModuleComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // DurabilityModuleComponent hash. + reader.readUnsignedInteger(); // DurabilityModuleComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the DurabilityModuleComponent class', () => { + const component = DurabilityModuleComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(DurabilityModuleComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.integrity).toBeCloseTo(componentProps.integrity, 2); + }); +}); + +describe('DurabilityModuleComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new DurabilityModuleComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = '00111111001100001010001111010111'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('DurabilityModuleComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new DurabilityModuleComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '011011111000101111001010000111110000000000000000000000000010000000111111001100001010001111010111'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // DurabilityModuleComponent data length. + const integrity = reader.readFloat(); + + expect(hash).toStrictEqual(componentHash); + expect(integrity).toBeCloseTo(componentProps.integrity, 2); + }); +}); diff --git a/src/components/DurabilityModuleComponent.ts b/src/components/DurabilityModuleComponent.ts new file mode 100644 index 0000000..88e458b --- /dev/null +++ b/src/components/DurabilityModuleComponent.ts @@ -0,0 +1,90 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type DurabilityModuleComponentPropsV1 = { + integrity?: number | undefined; +}; + +export type DurabilityModuleComponentProps = DurabilityModuleComponentPropsV1; + +/** + * @see [Class: `DurabilityModuleComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/DurabilityModuleComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { DurabilityModuleComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new DurabilityModuleComponent({ version: componentVersion }); + */ +export class DurabilityModuleComponent extends Component { + /** + * The integrity of the prefab this component is attached to. + * + * @since v1 + * + * @example + * import { DurabilityModuleComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new DurabilityModuleComponent({ version: componentVersion }); + * + * const integrity = component.integrity; + * // `integrity` is `1` + */ + integrity: number; + + /** + * @see [Class: `DurabilityModuleComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/DurabilityModuleComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { DurabilityModuleComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new DurabilityModuleComponent({ version: componentVersion }); + */ + constructor({ version, integrity }: ComponentProps & DurabilityModuleComponentProps) { + const hash = ComponentHash.DurabilityModule; + const name = 'DurabilityModule'; + + super({ hash, name, version }); + + this.integrity = integrity ?? 1; + } + + static override fromBinary(reader: BinaryReader, version: number): DurabilityModuleComponent { + const props: ComponentProps & DurabilityModuleComponentProps = { version }; + + /** + * @property {float} integrity + * @since v1 + */ + if (props.version >= 1) { + props.integrity = reader.readFloat(); + } + + return new DurabilityModuleComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {float} integrity + * @since v1 + */ + if (version >= 1) { + writer.writeFloat(this.integrity); + } + + return writer.flush(); + } +} diff --git a/src/components/FireComponent.test.ts b/src/components/FireComponent.test.ts new file mode 100644 index 0000000..90fba3a --- /dev/null +++ b/src/components/FireComponent.test.ts @@ -0,0 +1,126 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { FireComponent } from './FireComponent.js'; + +const componentHash = ComponentHash.Fire; +const componentName = 'Fire'; +const componentVersion = 1; +const componentProps = { + fuelConsumptionProgress: 0.69 +}; + +describe('new FireComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the FireComponent class', () => { + const component = new FireComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(FireComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the FireComponent class', () => { + const component = new FireComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(FireComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.fuelConsumptionProgress).toBeCloseTo(componentProps.fuelConsumptionProgress, 2); + }); + }); +}); + +describe('FireComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('Grass_Clump', { + components: { + Fire: new FireComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // FireComponent hash. + reader.readUnsignedInteger(); // FireComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the FireComponent class', () => { + const component = FireComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(FireComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.fuelConsumptionProgress).toBeCloseTo(componentProps.fuelConsumptionProgress, 2); + }); +}); + +describe('FireComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new FireComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = '00111111001100001010001111010111'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('FireComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new FireComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '110011100001010110010000010111100000000000000000000000000010000000111111001100001010001111010111'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // FireComponent data length. + const fuelConsumptionProgress = reader.readFloat(); + + expect(hash).toStrictEqual(componentHash); + expect(fuelConsumptionProgress).toBeCloseTo(componentProps.fuelConsumptionProgress, 2); + }); +}); diff --git a/src/components/FireComponent.ts b/src/components/FireComponent.ts new file mode 100644 index 0000000..af51a00 --- /dev/null +++ b/src/components/FireComponent.ts @@ -0,0 +1,90 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type FireComponentPropsV1 = { + fuelConsumptionProgress?: number | undefined; +}; + +export type FireComponentProps = FireComponentPropsV1; + +/** + * @see [Class: `FireComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/FireComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { FireComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new FireComponent({ version: componentVersion }); + */ +export class FireComponent extends Component { + /** + * The progress of the consumption of fuel attached to this component's prefab. + * + * @since v1 + * + * @example + * import { FireComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new FireComponent({ version: componentVersion }); + * + * const fuelConsumptionProgress = component.fuelConsumptionProgress; + * // `fuelConsumptionProgress` is `1` + */ + fuelConsumptionProgress: number; + + /** + * @see [Class: `FireComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/FireComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { FireComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new FireComponent({ version: componentVersion }); + */ + constructor({ version, fuelConsumptionProgress }: ComponentProps & FireComponentProps) { + const hash = ComponentHash.Fire; + const name = 'Fire'; + + super({ hash, name, version }); + + this.fuelConsumptionProgress = fuelConsumptionProgress ?? 1; + } + + static override fromBinary(reader: BinaryReader, version: number): FireComponent { + const props: ComponentProps & FireComponentProps = { version }; + + /** + * @property {float} fuelConsumptionProgress + * @since v1 + */ + if (props.version >= 1) { + props.fuelConsumptionProgress = reader.readFloat(); + } + + return new FireComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {float} fuelConsumptionProgress + * @since v1 + */ + if (version >= 1) { + writer.writeFloat(this.fuelConsumptionProgress); + } + + return writer.flush(); + } +} diff --git a/src/components/FuseComponent.test.ts b/src/components/FuseComponent.test.ts new file mode 100644 index 0000000..078e72b --- /dev/null +++ b/src/components/FuseComponent.test.ts @@ -0,0 +1,136 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { FuseComponent } from './FuseComponent.js'; + +const componentHash = ComponentHash.Fuse; +const componentName = 'Fuse'; +const componentVersion = 1; +const componentProps = { + isFinished: false, + isLit: true, + currentFuseAmount: 0.69 +}; + +describe('new FuseComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the FuseComponent class', () => { + const component = new FuseComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(FuseComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the FuseComponent class', () => { + const component = new FuseComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(FuseComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.isFinished).toStrictEqual(componentProps.isFinished); + expect(component.isLit).toStrictEqual(componentProps.isLit); + expect(component.currentFuseAmount).toBeCloseTo(componentProps.currentFuseAmount, 2); + }); + }); +}); + +describe('FuseComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('Grass_Clump', { + components: { + Fuse: new FuseComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // FuseComponent hash. + reader.readUnsignedInteger(); // FuseComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the FuseComponent class', () => { + const component = FuseComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(FuseComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.isFinished).toStrictEqual(componentProps.isFinished); + expect(component.isLit).toStrictEqual(componentProps.isLit); + expect(component.currentFuseAmount).toBeCloseTo(componentProps.currentFuseAmount, 2); + }); +}); + +describe('FuseComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new FuseComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = '0100111111001100001010001111010111'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('FuseComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new FuseComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '11011010100000011100101110011001000000000000000000000000001000100100111111001100001010001111010111'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // FuseComponent data length. + const isFinished = reader.readBoolean(); + const isLit = reader.readBoolean(); + const currentFuseAmount = reader.readFloat(); + + expect(hash).toStrictEqual(componentHash); + expect(isFinished).toStrictEqual(componentProps.isFinished); + expect(isLit).toStrictEqual(componentProps.isLit); + expect(currentFuseAmount).toBeCloseTo(componentProps.currentFuseAmount, 2); + }); +}); diff --git a/src/components/FuseComponent.ts b/src/components/FuseComponent.ts new file mode 100644 index 0000000..8f8aa70 --- /dev/null +++ b/src/components/FuseComponent.ts @@ -0,0 +1,158 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type FuseComponentPropsV1 = { + isFinished?: boolean | undefined; + isLit?: boolean | undefined; + currentFuseAmount?: number | undefined; +}; + +export type FuseComponentProps = FuseComponentPropsV1; + +/** + * @see [Class: `FuseComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/FuseComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { FuseComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new FuseComponent({ version: componentVersion }); + */ +export class FuseComponent extends Component { + /** + * Whether the fuse is finished or not. + * + * @since v1 + * + * @example + * import { FuseComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new FuseComponent({ version: componentVersion }); + * + * const isFinished = component.isFinished; + * // `isFinished` is `false` + */ + isFinished: boolean; + + /** + * Whether the fuse is lit or not. + * + * @since v1 + * + * @example + * import { FuseComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new FuseComponent({ version: componentVersion }); + * + * const isLit = component.isLit; + * // `isLit` is `false` + */ + isLit: boolean; + + /** + * How much of the fuse is left. + * + * @since v1 + * + * @example + * import { FuseComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new FuseComponent({ version: componentVersion }); + * + * const currentFuseAmount = component.currentFuseAmount; + * // `currentFuseAmount` is `1` + */ + currentFuseAmount: number; + + /** + * @see [Class: `FuseComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/FuseComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { FuseComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new FuseComponent({ version: componentVersion }); + */ + constructor({ version, isFinished, isLit, currentFuseAmount }: ComponentProps & FuseComponentProps) { + const hash = ComponentHash.Fuse; + const name = 'Fuse'; + + super({ hash, name, version }); + + this.isFinished = isFinished ?? false; + this.isLit = isLit ?? false; + this.currentFuseAmount = currentFuseAmount ?? 1; + } + + static override fromBinary(reader: BinaryReader, version: number): FuseComponent { + const props: ComponentProps & FuseComponentProps = { version }; + + /** + * @property {boolean} isFinished + * @since v1 + */ + if (props.version >= 1) { + props.isFinished = reader.readBoolean(); + } + + /** + * @property {boolean} isLit + * @since v1 + */ + if (props.version >= 1) { + props.isLit = reader.readBoolean(); + } + + /** + * @property {float} currentFuseAmount + * @since v1 + */ + if (props.version >= 1) { + props.currentFuseAmount = reader.readFloat(); + } + + return new FuseComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {boolean} isFinished + * @since v1 + */ + if (version >= 1) { + writer.writeBoolean(this.isFinished); + } + + /** + * @property {boolean} isLit + * @since v1 + */ + if (version >= 1) { + writer.writeBoolean(this.isLit); + } + + /** + * @property {float} currentFuseAmount + * @since v1 + */ + if (version >= 1) { + writer.writeFloat(this.currentFuseAmount); + } + + return writer.flush(); + } +} diff --git a/src/components/HeatSourceBaseComponent.test.ts b/src/components/HeatSourceBaseComponent.test.ts new file mode 100644 index 0000000..78ce28d --- /dev/null +++ b/src/components/HeatSourceBaseComponent.test.ts @@ -0,0 +1,137 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { HeatSourceBaseComponent } from './HeatSourceBaseComponent.js'; + +const componentHash = ComponentHash.HeatSourceBase; +const componentName = 'HeatSourceBase'; +const componentVersion = 1; +const componentProps = { + isLit: true, + progress: 0.69, + time: 133742069 +}; + +describe('new HeatSourceBaseComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the HeatSourceBaseComponent class', () => { + const component = new HeatSourceBaseComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(HeatSourceBaseComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the HeatSourceBaseComponent class', () => { + const component = new HeatSourceBaseComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(HeatSourceBaseComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.isLit).toStrictEqual(componentProps.isLit); + expect(component.progress).toBeCloseTo(componentProps.progress, 2); + expect(component.time).toStrictEqual(componentProps.time); + }); + }); +}); + +describe('HeatSourceBaseComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('Grass_Clump', { + components: { + HeatSourceBase: new HeatSourceBaseComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // HeatSourceBaseComponent hash. + reader.readUnsignedInteger(); // HeatSourceBaseComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the HeatSourceBaseComponent class', () => { + const component = HeatSourceBaseComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(HeatSourceBaseComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.isLit).toStrictEqual(componentProps.isLit); + expect(component.progress).toBeCloseTo(componentProps.progress, 2); + expect(component.time).toStrictEqual(componentProps.time); + }); +}); + +describe('HeatSourceBaseComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new HeatSourceBaseComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = + '1001111110011000010100011110101110000011111111000101111011111010100000000000000000000000000000000'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('HeatSourceBaseComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new HeatSourceBaseComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '11110100111011111101111010000000000000000000000000000000011000011001111110011000010100011110101110000011111111000101111011111010100000000000000000000000000000000'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // HeatSourceBaseComponent data length. + const isLit = reader.readBoolean(); + const progress = reader.readFloat(); + const time = reader.readUnsignedLong(); + + expect(hash).toStrictEqual(componentHash); + expect(isLit).toStrictEqual(componentProps.isLit); + expect(progress).toBeCloseTo(componentProps.progress, 2); + expect(time).toStrictEqual(componentProps.time); + }); +}); diff --git a/src/components/HeatSourceBaseComponent.ts b/src/components/HeatSourceBaseComponent.ts new file mode 100644 index 0000000..976379f --- /dev/null +++ b/src/components/HeatSourceBaseComponent.ts @@ -0,0 +1,157 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type HeatSourceBaseComponentPropsV1 = { + isLit?: boolean | undefined; + progress?: number | undefined; + time?: number | undefined; +}; + +export type HeatSourceBaseComponentProps = HeatSourceBaseComponentPropsV1; + +const HUNDRED_YEARS_TICKS = 31557600000000000; + +/** + * @see [Class: `HeatSourceBaseComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/HeatSourceBaseComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { HeatSourceBaseComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new HeatSourceBaseComponent({ version: componentVersion }); + */ +export class HeatSourceBaseComponent extends Component { + /** + * Whether this heat source is lit and active or not. + * + * @since v1 + * + * @example + * import { HeatSourceBaseComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new HeatSourceBaseComponent({ version: componentVersion }); + * + * const isLit = component.isLit; + */ + isLit: boolean; + + /** + * Progress of the heat source until extinguishing. + * + * @since v1 + * + * @example + * import { HeatSourceBaseComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new HeatSourceBaseComponent({ version: componentVersion }); + * + * const progress = component.progress; + * // `progress` is `0` + */ + progress: number; + + /** + * @since v1 + * + * @example + * import { HeatSourceBaseComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new HeatSourceBaseComponent({ version: componentVersion }); + * + * const time = component.time; + * // `time` is `31557600000000000` + */ + time: number; + + /** + * @see [Class: `HeatSourceBaseComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/HeatSourceBaseComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { HeatSourceBaseComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new HeatSourceBaseComponent({ version: componentVersion }); + */ + constructor({ version, isLit, progress, time }: ComponentProps & HeatSourceBaseComponentProps) { + const hash = ComponentHash.HeatSourceBase; + const name = 'HeatSourceBase'; + + super({ hash, name, version }); + + this.isLit = isLit ?? true; + this.progress = progress ?? 0; + this.time = time ?? HUNDRED_YEARS_TICKS; + } + + static override fromBinary(reader: BinaryReader, version: number): HeatSourceBaseComponent { + const props: ComponentProps & HeatSourceBaseComponentProps = { version }; + + /** + * @property {boolean} isLit + * @since v1 + */ + if (props.version >= 1) { + props.isLit = reader.readBoolean(); + } + + /** + * @property {float} progress + * @since v1 + */ + if (props.version >= 1) { + props.progress = reader.readFloat(); + } + + /** + * @property {number} time + * @since v1 + */ + if (props.version >= 1) { + props.time = reader.readUnsignedLong(); + } + + return new HeatSourceBaseComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {boolean} isLit + * @since v1 + */ + if (version >= 1) { + writer.writeBoolean(this.isLit); + } + + /** + * @property {float} progress + * @since v1 + */ + if (version >= 1) { + writer.writeFloat(this.progress); + } + + /** + * @property {number} time + * @since v1 + */ + if (version >= 1) { + writer.writeUnsignedLong(this.time); + } + + return writer.flush(); + } +} diff --git a/src/components/LiquidContainerComponent.test.ts b/src/components/LiquidContainerComponent.test.ts new file mode 100644 index 0000000..1f46a48 --- /dev/null +++ b/src/components/LiquidContainerComponent.test.ts @@ -0,0 +1,318 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; +import { PresetHash } from '../types/PresetHash.js'; + +import { LiquidContainerComponent, type LiquidContainerComponentProps } from './LiquidContainerComponent.js'; + +const componentHash = ComponentHash.LiquidContainer; +const componentName = 'LiquidContainer'; +const componentVersion = 1; + +const effect = { + hash: 420, + strengthMultiplier: 69 +}; + +const customData = { + color: { r: 0, g: 111, b: 222, a: 128 }, + isConsumableThroughSkin: false, + visualDataHash: 1337, + effects: [effect], + foodChunks: [1337, 420, 69] +}; + +const componentProps: LiquidContainerComponentProps = { + canAddTo: true, + canRemoveFrom: true, + contentLevel: 42, + hasContent: true, + isCustom: true, + presetHash: 0, + customData +}; + +beforeEach(() => { + customData.effects = [effect]; + componentProps.customData = customData; +}); + +describe('new LiquidContainerComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the LiquidContainerComponent class', () => { + const component = new LiquidContainerComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(LiquidContainerComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the LiquidContainerComponent class', () => { + const component = new LiquidContainerComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(LiquidContainerComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.canAddTo).toStrictEqual(componentProps.canAddTo); + expect(component.canRemoveFrom).toStrictEqual(componentProps.canRemoveFrom); + expect(component.contentLevel).toStrictEqual(componentProps.contentLevel); + expect(component.hasContent).toStrictEqual(componentProps.hasContent); + expect(component.isCustom).toStrictEqual(componentProps.isCustom); + expect(component.presetHash).toStrictEqual(componentProps.presetHash); + expect(component.customData).toStrictEqual(componentProps.customData); + }); + }); +}); + +describe('LiquidContainerComponent.fromBinary()', () => { + describe('when all component props are given', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('Grass_Clump', { + components: { + LiquidContainer: new LiquidContainerComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // LiquidContainerComponent hash. + reader.readUnsignedInteger(); // LiquidContainerComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the LiquidContainerComponent class', () => { + const component = LiquidContainerComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(LiquidContainerComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.canAddTo).toStrictEqual(componentProps.canAddTo); + expect(component.canRemoveFrom).toStrictEqual(componentProps.canRemoveFrom); + expect(component.contentLevel).toStrictEqual(componentProps.contentLevel); + expect(component.hasContent).toStrictEqual(componentProps.hasContent); + expect(component.isCustom).toStrictEqual(componentProps.isCustom); + expect(component.presetHash).toStrictEqual(componentProps.presetHash); + expect(component.customData).toStrictEqual(componentProps.customData); + }); + }); + + describe('when CustomData is null', () => { + let fastForwardedReader: BinaryReader; + + beforeEach(() => { + componentProps.isCustom = false; + componentProps.presetHash = PresetHash.TeleportationPotion; + componentProps.customData = null; + + const prefab = new Prefab('Grass_Clump', { + components: { + LiquidContainer: new LiquidContainerComponent({ version: componentVersion, ...componentProps }) + } + }); + + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // LiquidContainerComponent hash. + reader.readUnsignedInteger(); // LiquidContainerComponent data length. + + fastForwardedReader = reader; + }); + + afterEach(() => { + componentProps.isCustom = true; + componentProps.presetHash = 0; + componentProps.customData = customData; + }); + + it('returns an instance of the LiquidContainerComponent class', () => { + const component = LiquidContainerComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(LiquidContainerComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.canAddTo).toStrictEqual(componentProps.canAddTo); + expect(component.canRemoveFrom).toStrictEqual(componentProps.canRemoveFrom); + expect(component.contentLevel).toStrictEqual(componentProps.contentLevel); + expect(component.hasContent).toStrictEqual(componentProps.hasContent); + expect(component.isCustom).toStrictEqual(componentProps.isCustom); + expect(component.presetHash).toStrictEqual(componentProps.presetHash); + expect(component.customData).toStrictEqual(componentProps.customData); + }); + }); + + describe('when effect is null', () => { + let fastForwardedReader: BinaryReader; + + beforeEach(() => { + componentProps.customData = { + ...customData, + effects: [null, effect] + }; + + const prefab = new Prefab('Grass_Clump', { + components: { + LiquidContainer: new LiquidContainerComponent({ version: componentVersion, ...componentProps }) + } + }); + + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // LiquidContainerComponent hash. + reader.readUnsignedInteger(); // LiquidContainerComponent data length. + + fastForwardedReader = reader; + }); + + afterEach(() => { + componentProps.customData = customData; + }); + + it('returns an instance of the LiquidContainerComponent class', () => { + const component = LiquidContainerComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(LiquidContainerComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.canAddTo).toStrictEqual(componentProps.canAddTo); + expect(component.canRemoveFrom).toStrictEqual(componentProps.canRemoveFrom); + expect(component.contentLevel).toStrictEqual(componentProps.contentLevel); + expect(component.hasContent).toStrictEqual(componentProps.hasContent); + expect(component.isCustom).toStrictEqual(componentProps.isCustom); + expect(component.presetHash).toStrictEqual(componentProps.presetHash); + expect(component.customData).toStrictEqual(componentProps.customData); + }); + }); +}); + +describe('LiquidContainerComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new LiquidContainerComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = + '11100000000000000000000000001010101100000000000000000000000000000000000000000000000000000000000000000010000101101111000000000000000000100001101011110000000000000000001000011000000000000000000000000000000000000000000000010100111001000000000000000000000000000000010000000000000000000000001101001000100001010001010000000000000000000000000000000000000000000000011000000000000000000000101001110010000000000000000000000011010010000000000000000000000000001000101'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('LiquidContainerComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new LiquidContainerComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '111110010001101011110110001100110000000000000000000000011100011111100000000000000000000000001010101100000000000000000000000000000000000000000000000000000000000000000010000101101111000000000000000000100001101011110000000000000000001000011000000000000000000000000000000000000000000000010100111001000000000000000000000000000000010000000000000000000000001101001000100001010001010000000000000000000000000000000000000000000000011000000000000000000000101001110010000000000000000000000011010010000000000000000000000000001000101'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // LiquidContainerComponent data length. + const canAddTo = reader.readBoolean(); + const canRemoveFrom = reader.readBoolean(); + const contentLevel = reader.readSignedInteger(); + const hasContent = reader.readBoolean(); + const isCustom = reader.readBoolean(); + const presetHash = reader.readUnsignedInteger(); + const customDataNullBit = reader.readBoolean(); + const r = reader.readFloat(); + const g = reader.readFloat(); + const b = reader.readFloat(); + const a = reader.readFloat(); + + expect(hash).toStrictEqual(componentHash); + expect(canAddTo).toStrictEqual(componentProps.canAddTo); + expect(canRemoveFrom).toStrictEqual(componentProps.canRemoveFrom); + expect(contentLevel).toStrictEqual(componentProps.contentLevel); + expect(hasContent).toStrictEqual(componentProps.hasContent); + expect(isCustom).toStrictEqual(componentProps.isCustom); + expect(presetHash).toStrictEqual(componentProps.presetHash); + expect(customDataNullBit).toStrictEqual(false); + expect(r).toStrictEqual(componentProps.customData?.color.r); + expect(g).toStrictEqual(componentProps.customData?.color.g); + expect(b).toStrictEqual(componentProps.customData?.color.b); + expect(a).toStrictEqual(componentProps.customData?.color.a); + }); +}); diff --git a/src/components/LiquidContainerComponent.ts b/src/components/LiquidContainerComponent.ts new file mode 100644 index 0000000..29137d8 --- /dev/null +++ b/src/components/LiquidContainerComponent.ts @@ -0,0 +1,480 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type Color = { + r: number; + g: number; + b: number; + a: number; +}; + +type Effect = null | { + hash: number; + strengthMultiplier: number; +}; + +type FoodChunk = number; + +type CustomData = null | { + color: Color; + isConsumableThroughSkin: boolean; + visualDataHash: number; + effects: Effect[]; + foodChunks: FoodChunk[]; +}; + +type LiquidContainerComponentPropsV1 = { + canAddTo?: boolean | undefined; + canRemoveFrom?: boolean | undefined; + contentLevel?: number | undefined; + hasContent?: boolean | undefined; + isCustom?: boolean | undefined; + presetHash?: number | undefined; + customData?: CustomData | undefined; +}; + +export type LiquidContainerComponentProps = LiquidContainerComponentPropsV1; + +/** + * @see [Class: `LiquidContainerComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/LiquidContainerComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { LiquidContainerComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LiquidContainerComponent({ version: componentVersion }); + */ +export class LiquidContainerComponent extends Component { + /** + * Whether any content can be added to the liquid container or not. + * + * @since v1 + * + * @example + * import { LiquidContainerComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LiquidContainerComponent({ version: componentVersion }); + * + * const canAddTo = component.canAddTo; + * // `canAddTo` is `false` + */ + canAddTo: boolean; + + /** + * Whether any content can be removed from the liquid container or not. + * + * @since v1 + * + * @example + * import { LiquidContainerComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LiquidContainerComponent({ version: componentVersion }); + * + * const canRemoveFrom = component.canRemoveFrom; + * // `canRemoveFrom` is `false` + */ + canRemoveFrom: boolean; + + /** + * The amount of content stored inside the liquid container. + * + * @since v1 + * + * @example + * import { LiquidContainerComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LiquidContainerComponent({ version: componentVersion }); + * + * const contentLevel = component.contentLevel; + * // `contentLevel` is `0` + */ + contentLevel: number; + + /** + * Whether any content is stored in the liquid container or not. + * + * @since v1 + * + * @example + * import { LiquidContainerComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LiquidContainerComponent({ version: componentVersion }); + * + * const hasContent = component.hasContent; + * // `hasContent` is `false` + */ + hasContent: boolean; + + /** + * Whether the content stored in the liquid container is custom or a preset. + * + * @since v1 + * + * @example + * import { LiquidContainerComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LiquidContainerComponent({ version: componentVersion }); + * + * const isCustom = component.isCustom; + * // `isCustom` is `false` + */ + isCustom: boolean; + + /** + * The hash of the preset of the contents stored in the liquid container. Is `0` when no preset is used (uses `CustomData` instead). + * + * @since v1 + * + * @example + * import { LiquidContainerComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LiquidContainerComponent({ version: componentVersion }); + * + * const presetHash = component.presetHash; + * // `presetHash` is `0` + */ + presetHash: number; + + /** + * The data to use as the customised contents of the liquid container. + * + * @since v1 + * + * @example + * import { LiquidContainerComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LiquidContainerComponent({ version: componentVersion }); + * + * const customData = component.customData; + * // `customData` is `null` + */ + customData: null | CustomData; + + /** + * @see [Class: `LiquidContainerComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/LiquidContainerComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { LiquidContainerComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LiquidContainerComponent({ version: componentVersion }); + */ + constructor({ + version, + canAddTo, + canRemoveFrom, + contentLevel, + customData, + hasContent, + isCustom, + presetHash + }: ComponentProps & LiquidContainerComponentProps) { + const hash = ComponentHash.LiquidContainer; + const name = 'LiquidContainer'; + + super({ hash, name, version }); + + this.canAddTo = canAddTo ?? false; + this.canRemoveFrom = canRemoveFrom ?? false; + this.contentLevel = Math.round(contentLevel ?? 0); + this.hasContent = hasContent ?? (contentLevel ?? 0) > 0; + this.isCustom = isCustom ?? false; + this.presetHash = presetHash ?? 0; + this.customData = customData ?? null; + } + + static override fromBinary(reader: BinaryReader, version: number): LiquidContainerComponent { + const props: ComponentProps & LiquidContainerComponentProps = { version }; + + /** + * @property {boolean} canAddTo + * @since v1 + */ + if (props.version >= 1) { + props.canAddTo = reader.readBoolean(); + } + + /** + * @property {boolean} canRemoveFrom + * @since v1 + */ + if (props.version >= 1) { + props.canRemoveFrom = reader.readBoolean(); + } + + /** + * @property {number} contentLevel + * @since v1 + */ + if (props.version >= 1) { + props.contentLevel = reader.readSignedInteger(); + } + + /** + * @property {boolean} hasContent + * @since v1 + */ + if (props.version >= 1) { + props.hasContent = reader.readBoolean(); + } + + /** + * @property {boolean} isCustom + * @since v1 + */ + if (props.version >= 1) { + props.isCustom = reader.readBoolean(); + } + + /** + * @property {number} presetHash + * @since v1 + */ + if (props.version >= 1) { + props.presetHash = reader.readUnsignedInteger(); + } + + /** + * @property {null | CustomData} customData + * @since v1 + */ + if (props.version >= 1) { + /** + * @property {boolean} isNull + * @since v1 + */ + const isNull = reader.readBoolean(); + + if (isNull) { + props.customData = null; + } else { + props.customData = {} as Exclude; + + /** + * @property {Color} color + * @since v1 + */ + props.customData.color = { + r: reader.readFloat(), + g: reader.readFloat(), + b: reader.readFloat(), + a: reader.readFloat() + }; + + /** + * @property {boolean} isConsumableThroughSkin + * @since v1 + */ + props.customData.isConsumableThroughSkin = reader.readBoolean(); + + /** + * @property {number} visualDataHash + * @since v1 + */ + props.customData.visualDataHash = reader.readUnsignedInteger(); + + /** + * @property {number} effectsLength + * @since v1 + */ + const effectsLength = reader.readUnsignedInteger(); + props.customData.effects = []; + + for (let index = 0; index < effectsLength; ++index) { + /** + * @property {boolean} isNull + * @since v1 + */ + const isNull = reader.readBoolean(); + + if (isNull) { + props.customData.effects.push(null); + continue; + } + + props.customData.effects.push({ + /** + * @property {number} hash + * @since v1 + */ + hash: reader.readUnsignedInteger(), + + /** + * @property {float} strengthMultiplier + * @since v1 + */ + strengthMultiplier: reader.readFloat() + }); + } + + /** + * @property {number} foodChunksLength + * @since v1 + */ + const foodChunksLength = reader.readUnsignedInteger(); + props.customData.foodChunks = []; + + for (let index = 0; index < foodChunksLength; ++index) { + /** + * @property {number} foodChunkHash + * @since v1 + */ + props.customData.foodChunks.push(reader.readUnsignedInteger()); + } + } + } + + return new LiquidContainerComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {boolean} canAddTo + * @since v1 + */ + if (version >= 1) { + writer.writeBoolean(this.canAddTo); + } + + /** + * @property {boolean} canRemoveFrom + * @since v1 + */ + if (version >= 1) { + writer.writeBoolean(this.canRemoveFrom); + } + + /** + * @property {number} contentLevel + * @since v1 + */ + if (version >= 1) { + writer.writeSignedInteger(this.contentLevel); + } + + /** + * @property {boolean} hasContent + * @since v1 + */ + if (version >= 1) { + writer.writeBoolean(this.hasContent); + } + + /** + * @property {boolean} isCustom + * @since v1 + */ + if (version >= 1) { + writer.writeBoolean(this.isCustom); + } + + /** + * @property {number} presetHash + * @since v1 + */ + if (version >= 1) { + writer.writeUnsignedInteger(this.presetHash); + } + + /** + * @property {null | CustomData} customData + * @since v1 + */ + if (version >= 1) { + const isNull = this.customData === null; + + /** + * @property {boolean} isNull + * @since v1 + */ + writer.writeBoolean(isNull); + + if (this.customData !== null) { + /** + * @property {Color} color + * @since v1 + */ + writer.writeFloat(this.customData.color.r); + writer.writeFloat(this.customData.color.g); + writer.writeFloat(this.customData.color.b); + writer.writeFloat(this.customData.color.a); + + /** + * @property {boolean} isConsumableThroughSkin + * @since v1 + */ + writer.writeBoolean(this.customData.isConsumableThroughSkin); + + /** + * @property {number} visualDataHash + * @since v1 + */ + writer.writeUnsignedInteger(this.customData.visualDataHash); + + /** + * @property {number} effectsLength + * @since v1 + */ + writer.writeUnsignedInteger(this.customData.effects.length); + + for (const effect of this.customData.effects) { + const isNull = effect === null; + + /** + * @property {boolean} isNull + * @since v1 + */ + writer.writeBoolean(isNull); + + if (!isNull) { + /** + * @property {number} hash + * @since v1 + */ + writer.writeUnsignedInteger(effect.hash); + + /** + * @property {float} strengthMultiplier + * @since v1 + */ + writer.writeFloat(effect.strengthMultiplier); + } + } + + /** + * @property {number} foodChunksLength + * @since v1 + */ + writer.writeUnsignedInteger(this.customData.foodChunks.length); + + for (const foodChunkHash of this.customData.foodChunks) { + /** + * @property {number} foodChunkHash + * @since v1 + */ + writer.writeUnsignedInteger(foodChunkHash); + } + } + } + + return writer.flush(); + } +} diff --git a/src/components/LogicBoolReceiverComponent.test.ts b/src/components/LogicBoolReceiverComponent.test.ts new file mode 100644 index 0000000..e7f76fd --- /dev/null +++ b/src/components/LogicBoolReceiverComponent.test.ts @@ -0,0 +1,126 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { LogicBoolReceiverComponent } from './LogicBoolReceiverComponent.js'; + +const componentHash = ComponentHash.LogicBoolReceiver; +const componentName = 'LogicBoolReceiver'; +const componentVersion = 1; +const componentProps = { + sender: 1337 +}; + +describe('new LogicBoolReceiverComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the LogicBoolReceiverComponent class', () => { + const component = new LogicBoolReceiverComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(LogicBoolReceiverComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the LogicBoolReceiverComponent class', () => { + const component = new LogicBoolReceiverComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(LogicBoolReceiverComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.sender).toStrictEqual(componentProps.sender); + }); + }); +}); + +describe('LogicBoolReceiverComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('MRK_Small_Lever', { + components: { + LogicBoolReceiver: new LogicBoolReceiverComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // LogicBoolReceiverComponent hash. + reader.readUnsignedInteger(); // LogicBoolReceiverComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the LogicBoolReceiverComponent class', () => { + const component = LogicBoolReceiverComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(LogicBoolReceiverComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.sender).toStrictEqual(componentProps.sender); + }); +}); + +describe('LogicBoolReceiverComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new LogicBoolReceiverComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = '00000000000000000000010100111001'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('LogicBoolReceiverComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new LogicBoolReceiverComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '110111111001100100010011100010010000000000000000000000000010000000000000000000000000010100111001'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // LogicBoolReceiverComponent data length. + const sender = reader.readUnsignedInteger(); + + expect(hash).toStrictEqual(componentHash); + expect(sender).toStrictEqual(componentProps.sender); + }); +}); diff --git a/src/components/LogicBoolReceiverComponent.ts b/src/components/LogicBoolReceiverComponent.ts new file mode 100644 index 0000000..da3bf5e --- /dev/null +++ b/src/components/LogicBoolReceiverComponent.ts @@ -0,0 +1,90 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type LogicBoolReceiverComponentPropsV1 = { + sender?: number | undefined; +}; + +export type LogicBoolReceiverComponentProps = LogicBoolReceiverComponentPropsV1; + +/** + * @see [Class: `LogicBoolReceiverComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/LogicBoolReceiverComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { LogicBoolReceiverComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicBoolReceiverComponent({ version: componentVersion }); + */ +export class LogicBoolReceiverComponent extends Component { + /** + * The identifier of the `LogicBoolSender` that is connected to this `LogicBoolReceiver`. + * + * @since v1 + * + * @example + * import { LogicBoolReceiverComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicBoolReceiverComponent({ version: componentVersion }); + * + * const sender = component.sender; + * // `sender` is `0` + */ + sender: number; + + /** + * @see [Class: `LogicBoolReceiverComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/LogicBoolReceiverComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { LogicBoolReceiverComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicBoolReceiverComponent({ version: componentVersion }); + */ + constructor({ version, sender }: ComponentProps & LogicBoolReceiverComponentProps) { + const hash = ComponentHash.LogicBoolReceiver; + const name = 'LogicBoolReceiver'; + + super({ hash, name, version }); + + this.sender = sender ?? 0; + } + + static override fromBinary(reader: BinaryReader, version: number): LogicBoolReceiverComponent { + const props: ComponentProps & LogicBoolReceiverComponentProps = { version }; + + /** + * @property {number} sender + * @since v1 + */ + if (props.version >= 1) { + props.sender = reader.readUnsignedInteger(); + } + + return new LogicBoolReceiverComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {number} sender + * @since v1 + */ + if (version >= 1) { + writer.writeUnsignedInteger(this.sender); + } + + return writer.flush(); + } +} diff --git a/src/components/LogicBoolSenderComponent.test.ts b/src/components/LogicBoolSenderComponent.test.ts new file mode 100644 index 0000000..6f34c17 --- /dev/null +++ b/src/components/LogicBoolSenderComponent.test.ts @@ -0,0 +1,142 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { LogicBoolSenderComponent } from './LogicBoolSenderComponent.js'; + +const componentHash = ComponentHash.LogicBoolSender; +const componentName = 'LogicBoolSender'; +const componentVersion = 2; +const componentProps = { + updatedValue: 1337, + changedExternally: 420, + identifier: 69, + value: true +}; + +describe('new LogicBoolSenderComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the LogicBoolSenderComponent class', () => { + const component = new LogicBoolSenderComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(LogicBoolSenderComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the LogicBoolSenderComponent class', () => { + const component = new LogicBoolSenderComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(LogicBoolSenderComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.updatedValue).toStrictEqual(componentProps.updatedValue); + expect(component.changedExternally).toStrictEqual(componentProps.changedExternally); + expect(component.identifier).toStrictEqual(componentProps.identifier); + expect(component.value).toStrictEqual(componentProps.value); + }); + }); +}); + +describe('LogicBoolSenderComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('MRK_Small_Lever', { + components: { + LogicBoolSender: new LogicBoolSenderComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // LogicBoolSenderComponent hash. + reader.readUnsignedInteger(); // LogicBoolSenderComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the LogicBoolSenderComponent class', () => { + const component = LogicBoolSenderComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(LogicBoolSenderComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.updatedValue).toStrictEqual(componentProps.updatedValue); + expect(component.changedExternally).toStrictEqual(componentProps.changedExternally); + expect(component.identifier).toStrictEqual(componentProps.identifier); + expect(component.value).toStrictEqual(componentProps.value); + }); +}); + +describe('LogicBoolSenderComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new LogicBoolSenderComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = + '0000000000000000000001010011100100000000000000000000000110100100000000000000000000000000010001011'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('LogicBoolSenderComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new LogicBoolSenderComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '01001010111100001001110001001011000000000000000000000000011000010000000000000000000001010011100100000000000000000000000110100100000000000000000000000000010001011'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // LogicBoolSenderComponent data length. + const updatedValue = reader.readUnsignedInteger(); + const changedExternally = reader.readUnsignedInteger(); + const identifier = reader.readUnsignedInteger(); + const value = reader.readBoolean(); + + expect(hash).toStrictEqual(componentHash); + expect(updatedValue).toStrictEqual(componentProps.updatedValue); + expect(changedExternally).toStrictEqual(componentProps.changedExternally); + expect(identifier).toStrictEqual(componentProps.identifier); + expect(value).toStrictEqual(componentProps.value); + }); +}); diff --git a/src/components/LogicBoolSenderComponent.ts b/src/components/LogicBoolSenderComponent.ts new file mode 100644 index 0000000..86a51bc --- /dev/null +++ b/src/components/LogicBoolSenderComponent.ts @@ -0,0 +1,198 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type LogicBoolSenderComponentPropsV2 = { + updatedValue?: number | undefined; + changedExternally?: number | undefined; + identifier?: number | undefined; + value?: boolean | undefined; +}; + +export type LogicBoolSenderComponentProps = LogicBoolSenderComponentPropsV2; + +/** + * @see [Class: `LogicBoolSenderComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/LogicBoolSenderComponent.md) + * @since v3.0.0 + * @version 2 + * + * @example + * import { LogicBoolSenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new LogicBoolSenderComponent({ version: componentVersion }); + */ +export class LogicBoolSenderComponent extends Component { + /** + * We're not quite sure what this property does. + * + * @since v2 + * + * @example + * import { LogicBoolSenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new LogicBoolSenderComponent({ version: componentVersion }); + * + * const updatedValue = component.updatedValue; + * // `updatedValue` is `3171294583` + */ + updatedValue: number; + + /** + * We're not quite sure what this property does. + * + * @since v2 + * + * @example + * import { LogicBoolSenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new LogicBoolSenderComponent({ version: componentVersion }); + * + * const changedExternally = component.changedExternally; + * // `changedExternally` is `32` + */ + changedExternally: number; + + /** + * The identifier of this `LogicBoolSender` that a `LogicBoolReceiver` connects to. + * + * @since v2 + * + * @example + * import { LogicBoolSenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new LogicBoolSenderComponent({ version: componentVersion }); + * + * const identifier = component.identifier; + * // `identifier` is `0` + */ + identifier: number; + + /** + * The output value of this `LogicBoolSender` that a `LogicBoolReceiver` reads as its input. + * + * @since v2 + * + * @example + * import { LogicBoolSenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new LogicBoolSenderComponent({ version: componentVersion }); + * + * const value = component.value; + * // `value` is `false` + */ + value: boolean; + + /** + * @see [Class: `LogicBoolSenderComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/LogicBoolSenderComponent.md) + * @since v3.0.0 + * @version 2 + * + * @example + * import { LogicBoolSenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new LogicBoolSenderComponent({ version: componentVersion }); + */ + constructor({ + version, + updatedValue, + changedExternally, + identifier, + value + }: ComponentProps & LogicBoolSenderComponentProps) { + const hash = ComponentHash.LogicBoolSender; + const name = 'LogicBoolSender'; + + super({ hash, name, version }); + + this.updatedValue = updatedValue ?? 3171294583; + this.changedExternally = changedExternally ?? 32; + this.identifier = identifier ?? 0; + this.value = value ?? false; + } + + static override fromBinary(reader: BinaryReader, version: number): LogicBoolSenderComponent { + const props: ComponentProps & LogicBoolSenderComponentProps = { version }; + + /** + * @property {number} updatedValue + * @since v2 + */ + if (props.version >= 2) { + props.updatedValue = reader.readUnsignedInteger(); + } + + /** + * @property {number} changedExternally + * @since v2 + */ + if (props.version >= 2) { + props.changedExternally = reader.readUnsignedInteger(); + } + + /** + * @property {number} identifier + * @since v2 + */ + if (props.version >= 2) { + props.identifier = reader.readUnsignedInteger(); + } + + /** + * @property {boolean} value + * @since v2 + */ + if (props.version >= 2) { + props.value = reader.readBoolean(); + } + + return new LogicBoolSenderComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {number} updatedValue + * @since v2 + */ + if (version >= 2) { + writer.writeUnsignedInteger(this.updatedValue); + } + + /** + * @property {number} changedExternally + * @since v2 + */ + if (version >= 2) { + writer.writeUnsignedInteger(this.changedExternally); + } + + /** + * @property {number} identifier + * @since v2 + */ + if (version >= 2) { + writer.writeUnsignedInteger(this.identifier); + } + + /** + * @property {boolean} value + * @since v2 + */ + if (version >= 2) { + writer.writeBoolean(this.value); + } + + return writer.flush(); + } +} diff --git a/src/components/LogicFloatReceiverComponent.test.ts b/src/components/LogicFloatReceiverComponent.test.ts new file mode 100644 index 0000000..db23c4a --- /dev/null +++ b/src/components/LogicFloatReceiverComponent.test.ts @@ -0,0 +1,126 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { LogicFloatReceiverComponent } from './LogicFloatReceiverComponent.js'; + +const componentHash = ComponentHash.LogicFloatReceiver; +const componentName = 'LogicFloatReceiver'; +const componentVersion = 1; +const componentProps = { + sender: 1337 +}; + +describe('new LogicFloatReceiverComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the LogicFloatReceiverComponent class', () => { + const component = new LogicFloatReceiverComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(LogicFloatReceiverComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the LogicFloatReceiverComponent class', () => { + const component = new LogicFloatReceiverComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(LogicFloatReceiverComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.sender).toStrictEqual(componentProps.sender); + }); + }); +}); + +describe('LogicFloatReceiverComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('MRK_Small_Lever', { + components: { + LogicFloatReceiver: new LogicFloatReceiverComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // LogicFloatReceiverComponent hash. + reader.readUnsignedInteger(); // LogicFloatReceiverComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the LogicFloatReceiverComponent class', () => { + const component = LogicFloatReceiverComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(LogicFloatReceiverComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.sender).toStrictEqual(componentProps.sender); + }); +}); + +describe('LogicFloatReceiverComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new LogicFloatReceiverComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = '00000000000000000000010100111001'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('LogicFloatReceiverComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new LogicFloatReceiverComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '101111100000100100101100000111110000000000000000000000000010000000000000000000000000010100111001'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // LogicFloatReceiverComponent data length. + const sender = reader.readUnsignedInteger(); + + expect(hash).toStrictEqual(componentHash); + expect(sender).toStrictEqual(componentProps.sender); + }); +}); diff --git a/src/components/LogicFloatReceiverComponent.ts b/src/components/LogicFloatReceiverComponent.ts new file mode 100644 index 0000000..15fe7b4 --- /dev/null +++ b/src/components/LogicFloatReceiverComponent.ts @@ -0,0 +1,90 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type LogicFloatReceiverComponentPropsV1 = { + sender?: number | undefined; +}; + +export type LogicFloatReceiverComponentProps = LogicFloatReceiverComponentPropsV1; + +/** + * @see [Class: `LogicFloatReceiverComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/LogicFloatReceiverComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { LogicFloatReceiverComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicFloatReceiverComponent({ version: componentVersion }); + */ +export class LogicFloatReceiverComponent extends Component { + /** + * The identifier of the `LogicFloatSender` that is connected to this `LogicFloatReceiver`. + * + * @since v1 + * + * @example + * import { LogicFloatReceiverComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicFloatReceiverComponent({ version: componentVersion }); + * + * const sender = component.sender; + * // `sender` is `0` + */ + sender: number; + + /** + * @see [Class: `LogicFloatReceiverComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/LogicFloatReceiverComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { LogicFloatReceiverComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicFloatReceiverComponent({ version: componentVersion }); + */ + constructor({ version, sender }: ComponentProps & LogicFloatReceiverComponentProps) { + const hash = ComponentHash.LogicFloatReceiver; + const name = 'LogicFloatReceiver'; + + super({ hash, name, version }); + + this.sender = sender ?? 0; + } + + static override fromBinary(reader: BinaryReader, version: number): LogicFloatReceiverComponent { + const props: ComponentProps & LogicFloatReceiverComponentProps = { version }; + + /** + * @property {number} sender + * @since v1 + */ + if (props.version >= 1) { + props.sender = reader.readUnsignedInteger(); + } + + return new LogicFloatReceiverComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {number} sender + * @since v1 + */ + if (version >= 1) { + writer.writeUnsignedInteger(this.sender); + } + + return writer.flush(); + } +} diff --git a/src/components/LogicFloatSenderComponent.test.ts b/src/components/LogicFloatSenderComponent.test.ts new file mode 100644 index 0000000..178455b --- /dev/null +++ b/src/components/LogicFloatSenderComponent.test.ts @@ -0,0 +1,142 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { LogicFloatSenderComponent } from './LogicFloatSenderComponent.js'; + +const componentHash = ComponentHash.LogicFloatSender; +const componentName = 'LogicFloatSender'; +const componentVersion = 1; +const componentProps = { + updatedValue: 1337, + changedExternally: 420, + identifier: 69, + value: 0.69 +}; + +describe('new LogicFloatSenderComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the LogicFloatSenderComponent class', () => { + const component = new LogicFloatSenderComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(LogicFloatSenderComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the LogicFloatSenderComponent class', () => { + const component = new LogicFloatSenderComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(LogicFloatSenderComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.updatedValue).toStrictEqual(componentProps.updatedValue); + expect(component.changedExternally).toStrictEqual(componentProps.changedExternally); + expect(component.identifier).toStrictEqual(componentProps.identifier); + expect(component.value).toBeCloseTo(componentProps.value, 2); + }); + }); +}); + +describe('LogicFloatSenderComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('MRK_Small_Lever', { + components: { + LogicFloatSender: new LogicFloatSenderComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // LogicFloatSenderComponent hash. + reader.readUnsignedInteger(); // LogicFloatSenderComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the LogicFloatSenderComponent class', () => { + const component = LogicFloatSenderComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(LogicFloatSenderComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.updatedValue).toStrictEqual(componentProps.updatedValue); + expect(component.changedExternally).toStrictEqual(componentProps.changedExternally); + expect(component.identifier).toStrictEqual(componentProps.identifier); + expect(component.value).toBeCloseTo(componentProps.value, 2); + }); +}); + +describe('LogicFloatSenderComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new LogicFloatSenderComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = + '00000000000000000000010100111001000000000000000000000001101001000000000000000000000000000100010100111111001100001010001111010111'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('LogicFloatSenderComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new LogicFloatSenderComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '011111100110101101010110101110010000000000000000000000001000000000000000000000000000010100111001000000000000000000000001101001000000000000000000000000000100010100111111001100001010001111010111'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // LogicFloatSenderComponent data length. + const updatedValue = reader.readUnsignedInteger(); + const changedExternally = reader.readUnsignedInteger(); + const identifier = reader.readUnsignedInteger(); + const value = reader.readFloat(); + + expect(hash).toStrictEqual(componentHash); + expect(updatedValue).toStrictEqual(componentProps.updatedValue); + expect(changedExternally).toStrictEqual(componentProps.changedExternally); + expect(identifier).toStrictEqual(componentProps.identifier); + expect(value).toBeCloseTo(componentProps.value, 2); + }); +}); diff --git a/src/components/LogicFloatSenderComponent.ts b/src/components/LogicFloatSenderComponent.ts new file mode 100644 index 0000000..160f61e --- /dev/null +++ b/src/components/LogicFloatSenderComponent.ts @@ -0,0 +1,198 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type LogicFloatSenderComponentPropsV1 = { + updatedValue?: number | undefined; + changedExternally?: number | undefined; + identifier?: number | undefined; + value?: number | undefined; +}; + +export type LogicFloatSenderComponentProps = LogicFloatSenderComponentPropsV1; + +/** + * @see [Class: `LogicFloatSenderComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/LogicFloatSenderComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { LogicFloatSenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicFloatSenderComponent({ version: componentVersion }); + */ +export class LogicFloatSenderComponent extends Component { + /** + * We're not quite sure what this property does. + * + * @since v1 + * + * @example + * import { LogicFloatSenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicFloatSenderComponent({ version: componentVersion }); + * + * const updatedValue = component.updatedValue; + * // `updatedValue` is `3171294583` + */ + updatedValue: number; + + /** + * We're not quite sure what this property does. + * + * @since v1 + * + * @example + * import { LogicFloatSenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicFloatSenderComponent({ version: componentVersion }); + * + * const changedExternally = component.changedExternally; + * // `changedExternally` is `32` + */ + changedExternally: number; + + /** + * The identifier of this `LogicFloatSender` that a `LogicFloatReceiver` connects to. + * + * @since v1 + * + * @example + * import { LogicFloatSenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicFloatSenderComponent({ version: componentVersion }); + * + * const identifier = component.identifier; + * // `identifier` is `0` + */ + identifier: number; + + /** + * The output value of this `LogicFloatSender` that a `LogicFloatReceiver` reads as its input. + * + * @since v1 + * + * @example + * import { LogicFloatSenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicFloatSenderComponent({ version: componentVersion }); + * + * const value = component.value; + * // `value` is `0` + */ + value: number; + + /** + * @see [Class: `LogicFloatSenderComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/LogicFloatSenderComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { LogicFloatSenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicFloatSenderComponent({ version: componentVersion }); + */ + constructor({ + version, + updatedValue, + changedExternally, + identifier, + value + }: ComponentProps & LogicFloatSenderComponentProps) { + const hash = ComponentHash.LogicFloatSender; + const name = 'LogicFloatSender'; + + super({ hash, name, version }); + + this.updatedValue = updatedValue ?? 3171294583; + this.changedExternally = changedExternally ?? 32; + this.identifier = identifier ?? 0; + this.value = value ?? 0; + } + + static override fromBinary(reader: BinaryReader, version: number): LogicFloatSenderComponent { + const props: ComponentProps & LogicFloatSenderComponentProps = { version }; + + /** + * @property {number} updatedValue + * @since v1 + */ + if (props.version >= 1) { + props.updatedValue = reader.readUnsignedInteger(); + } + + /** + * @property {number} changedExternally + * @since v1 + */ + if (props.version >= 1) { + props.changedExternally = reader.readUnsignedInteger(); + } + + /** + * @property {number} identifier + * @since v1 + */ + if (props.version >= 1) { + props.identifier = reader.readUnsignedInteger(); + } + + /** + * @property {float} value + * @since v1 + */ + if (props.version >= 1) { + props.value = reader.readFloat(); + } + + return new LogicFloatSenderComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {number} updatedValue + * @since v1 + */ + if (version >= 1) { + writer.writeUnsignedInteger(this.updatedValue); + } + + /** + * @property {number} changedExternally + * @since v1 + */ + if (version >= 1) { + writer.writeUnsignedInteger(this.changedExternally); + } + + /** + * @property {number} identifier + * @since v1 + */ + if (version >= 1) { + writer.writeUnsignedInteger(this.identifier); + } + + /** + * @property {boolean} value + * @since v1 + */ + if (version >= 1) { + writer.writeFloat(this.value); + } + + return writer.flush(); + } +} diff --git a/src/components/LogicGateReceiverComponent.test.ts b/src/components/LogicGateReceiverComponent.test.ts new file mode 100644 index 0000000..f605b69 --- /dev/null +++ b/src/components/LogicGateReceiverComponent.test.ts @@ -0,0 +1,143 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; +import { LogicOperator } from '../types/LogicOperator.js'; + +import { LogicGateReceiverComponent } from './LogicGateReceiverComponent.js'; + +const componentHash = ComponentHash.LogicGateReceiver; +const componentName = 'LogicGateReceiver'; +const componentVersion = 2; +const componentProps = { + senders: [69, 420, 1337], + operationType: LogicOperator.Xor, + isInversedOutputSaved: true +}; + +describe('new LogicGateReceiverComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the LogicGateReceiverComponent class', () => { + const component = new LogicGateReceiverComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(LogicGateReceiverComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the LogicGateReceiverComponent class', () => { + const component = new LogicGateReceiverComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(LogicGateReceiverComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.senders).toStrictEqual(componentProps.senders); + expect(component.operationType).toStrictEqual(componentProps.operationType); + expect(component.isInversedOutputSaved).toStrictEqual(componentProps.isInversedOutputSaved); + }); + }); +}); + +describe('LogicGateReceiverComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('MRK_Small_Lever', { + components: { + LogicGateReceiver: new LogicGateReceiverComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // LogicGateReceiverComponent hash. + reader.readUnsignedInteger(); // LogicGateReceiverComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the LogicGateReceiverComponent class', () => { + const component = LogicGateReceiverComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(LogicGateReceiverComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.senders).toStrictEqual(componentProps.senders); + expect(component.operationType).toStrictEqual(componentProps.operationType); + expect(component.isInversedOutputSaved).toStrictEqual(componentProps.isInversedOutputSaved); + }); +}); + +describe('LogicGateReceiverComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new LogicGateReceiverComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = + '00000000000000000000000000000011000000000000000000000000010001010000000000000000000000011010010000000000000000000000010100111001100000000000000000000000000000101'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('LogicGateReceiverComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new LogicGateReceiverComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '010100101111001111111000000011100000000000000000000000001010000100000000000000000000000000000011000000000000000000000000010001010000000000000000000000011010010000000000000000000000010100111001100000000000000000000000000000101'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // LogicGateReceiverComponent data length. + reader.readUnsignedInteger(); // Senders array length. + const sender1 = reader.readUnsignedInteger(); + const sender2 = reader.readUnsignedInteger(); + const sender3 = reader.readUnsignedInteger(); + const operationType = reader.readSignedInteger(); + const isInversedOutputSaved = reader.readBoolean(); + + expect(hash).toStrictEqual(componentHash); + expect(sender1).toStrictEqual(componentProps.senders[0]); + expect(sender2).toStrictEqual(componentProps.senders[1]); + expect(sender3).toStrictEqual(componentProps.senders[2]); + expect(operationType).toStrictEqual(componentProps.operationType); + expect(isInversedOutputSaved).toStrictEqual(componentProps.isInversedOutputSaved); + }); +}); diff --git a/src/components/LogicGateReceiverComponent.ts b/src/components/LogicGateReceiverComponent.ts new file mode 100644 index 0000000..f8165f0 --- /dev/null +++ b/src/components/LogicGateReceiverComponent.ts @@ -0,0 +1,181 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; +import { LogicOperator } from '../types/LogicOperator.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type LogicGateReceiverComponentPropsV2 = { + senders?: number[] | undefined; + operationType?: LogicOperator | undefined; + isInversedOutputSaved?: boolean | undefined; +}; + +export type LogicGateReceiverComponentProps = LogicGateReceiverComponentPropsV2; + +/** + * @see [Class: `LogicGateReceiverComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/LogicGateReceiverComponent.md) + * @since v3.0.0 + * @version 2 + * + * @example + * import { LogicGateReceiverComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new LogicGateReceiverComponent({ version: componentVersion }); + */ +export class LogicGateReceiverComponent extends Component { + /** + * The identifiers of the `Logic*Sender` components that are connected to this `LogicGateReceiver`. + * + * @since v2 + * + * @example + * import { LogicGateReceiverComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new LogicGateReceiverComponent({ version: componentVersion }); + * + * const senders = component.senders; + * // `senders` is `[]` + */ + senders: number[]; + + /** + * The type of operation to perform on the received inputs. + * + * @since v2 + * + * @example + * import { LogicGateReceiverComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new LogicGateReceiverComponent({ version: componentVersion }); + * + * const operationType = component.operationType; + * // `operationType` is `0` (AND) + */ + operationType: LogicOperator; + + /** + * Whether to inverse the output of this gate. + * + * @since v2 + * + * @example + * import { LogicGateReceiverComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new LogicGateReceiverComponent({ version: componentVersion }); + * + * const isInversedOutputSaved = component.isInversedOutputSaved; + * // `isInversedOutputSaved` is `false` + */ + isInversedOutputSaved: boolean; + + /** + * @see [Class: `LogicGateReceiverComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/LogicGateReceiverComponent.md) + * @since v3.0.0 + * @version 2 + * + * @example + * import { LogicGateReceiverComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new LogicGateReceiverComponent({ version: componentVersion }); + */ + constructor({ + version, + senders, + operationType, + isInversedOutputSaved + }: ComponentProps & LogicGateReceiverComponentProps) { + const hash = ComponentHash.LogicGateReceiver; + const name = 'LogicGateReceiver'; + + super({ hash, name, version }); + + this.senders = senders ?? []; + this.operationType = operationType ?? LogicOperator.And; + this.isInversedOutputSaved = isInversedOutputSaved ?? false; + } + + static override fromBinary(reader: BinaryReader, version: number): LogicGateReceiverComponent { + const props: ComponentProps & LogicGateReceiverComponentProps = { version }; + + /** + * @property {number[]} senders + * @since v2 + */ + if (props.version >= 2) { + const sendersLength = reader.readUnsignedInteger(); + props.senders = []; + + for (let sendersIndex = 0; sendersIndex < sendersLength; ++sendersIndex) { + /** + * @property {number} sender + * @since v2 + */ + props.senders.push(reader.readUnsignedInteger()); + } + } + + /** + * @property {number} operationType + * @since v2 + */ + if (props.version >= 2) { + props.operationType = reader.readSignedInteger(); + } + + /** + * @property {number} isInversedOutputSaved + * @since v2 + */ + if (props.version >= 2) { + props.isInversedOutputSaved = reader.readBoolean(); + } + + return new LogicGateReceiverComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {number[]} senders + * @since v2 + */ + if (version >= 2) { + writer.writeUnsignedInteger(this.senders.length); + + for (const sender of this.senders) { + /** + * @property {number} sender + * @since v2 + */ + writer.writeUnsignedInteger(sender); + } + } + + /** + * @property {number} operationType + * @since v2 + */ + if (version >= 2) { + writer.writeSignedInteger(this.operationType); + } + + /** + * @property {number} isInversedOutputSaved + * @since v2 + */ + if (version >= 2) { + writer.writeBoolean(this.isInversedOutputSaved); + } + + return writer.flush(); + } +} diff --git a/src/components/LogicIntReceiverComponent.test.ts b/src/components/LogicIntReceiverComponent.test.ts new file mode 100644 index 0000000..92af469 --- /dev/null +++ b/src/components/LogicIntReceiverComponent.test.ts @@ -0,0 +1,126 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { LogicIntReceiverComponent } from './LogicIntReceiverComponent.js'; + +const componentHash = ComponentHash.LogicIntReceiver; +const componentName = 'LogicIntReceiver'; +const componentVersion = 1; +const componentProps = { + sender: 1337 +}; + +describe('new LogicIntReceiverComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the LogicIntReceiverComponent class', () => { + const component = new LogicIntReceiverComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(LogicIntReceiverComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the LogicIntReceiverComponent class', () => { + const component = new LogicIntReceiverComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(LogicIntReceiverComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.sender).toStrictEqual(componentProps.sender); + }); + }); +}); + +describe('LogicIntReceiverComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('MRK_Small_Lever', { + components: { + LogicIntReceiver: new LogicIntReceiverComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // LogicIntReceiverComponent hash. + reader.readUnsignedInteger(); // LogicIntReceiverComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the LogicIntReceiverComponent class', () => { + const component = LogicIntReceiverComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(LogicIntReceiverComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.sender).toStrictEqual(componentProps.sender); + }); +}); + +describe('LogicIntReceiverComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new LogicIntReceiverComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = '00000000000000000000010100111001'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('LogicIntReceiverComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new LogicIntReceiverComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '010000000111001010001000101000000000000000000000000000000010000000000000000000000000010100111001'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // LogicIntReceiverComponent data length. + const sender = reader.readUnsignedInteger(); + + expect(hash).toStrictEqual(componentHash); + expect(sender).toStrictEqual(componentProps.sender); + }); +}); diff --git a/src/components/LogicIntReceiverComponent.ts b/src/components/LogicIntReceiverComponent.ts new file mode 100644 index 0000000..76c298a --- /dev/null +++ b/src/components/LogicIntReceiverComponent.ts @@ -0,0 +1,90 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type LogicIntReceiverComponentPropsV1 = { + sender?: number | undefined; +}; + +export type LogicIntReceiverComponentProps = LogicIntReceiverComponentPropsV1; + +/** + * @see [Class: `LogicIntReceiverComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/LogicIntReceiverComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { LogicIntReceiverComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicIntReceiverComponent({ version: componentVersion }); + */ +export class LogicIntReceiverComponent extends Component { + /** + * The identifier of the `LogicIntSender` that is connected to this `LogicIntReceiver`. + * + * @since v1 + * + * @example + * import { LogicIntReceiverComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicIntReceiverComponent({ version: componentVersion }); + * + * const sender = component.sender; + * // `sender` is `0` + */ + sender: number; + + /** + * @see [Class: `LogicIntReceiverComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/LogicIntReceiverComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { LogicIntReceiverComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicIntReceiverComponent({ version: componentVersion }); + */ + constructor({ version, sender }: ComponentProps & LogicIntReceiverComponentProps) { + const hash = ComponentHash.LogicIntReceiver; + const name = 'LogicIntReceiver'; + + super({ hash, name, version }); + + this.sender = sender ?? 0; + } + + static override fromBinary(reader: BinaryReader, version: number): LogicIntReceiverComponent { + const props: ComponentProps & LogicIntReceiverComponentProps = { version }; + + /** + * @property {number} sender + * @since v1 + */ + if (props.version >= 1) { + props.sender = reader.readUnsignedInteger(); + } + + return new LogicIntReceiverComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {number} sender + * @since v1 + */ + if (version >= 1) { + writer.writeUnsignedInteger(this.sender); + } + + return writer.flush(); + } +} diff --git a/src/components/LogicIntSenderComponent.test.ts b/src/components/LogicIntSenderComponent.test.ts new file mode 100644 index 0000000..d0d3cf8 --- /dev/null +++ b/src/components/LogicIntSenderComponent.test.ts @@ -0,0 +1,142 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { LogicIntSenderComponent } from './LogicIntSenderComponent.js'; + +const componentHash = ComponentHash.LogicIntSender; +const componentName = 'LogicIntSender'; +const componentVersion = 1; +const componentProps = { + updatedValue: 1337, + changedExternally: 420, + identifier: 69, + value: -420 +}; + +describe('new LogicIntSenderComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the LogicIntSenderComponent class', () => { + const component = new LogicIntSenderComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(LogicIntSenderComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the LogicIntSenderComponent class', () => { + const component = new LogicIntSenderComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(LogicIntSenderComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.updatedValue).toStrictEqual(componentProps.updatedValue); + expect(component.changedExternally).toStrictEqual(componentProps.changedExternally); + expect(component.identifier).toStrictEqual(componentProps.identifier); + expect(component.value).toStrictEqual(componentProps.value); + }); + }); +}); + +describe('LogicIntSenderComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('MRK_Small_Lever', { + components: { + LogicIntSender: new LogicIntSenderComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // LogicIntSenderComponent hash. + reader.readUnsignedInteger(); // LogicIntSenderComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the LogicIntSenderComponent class', () => { + const component = LogicIntSenderComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(LogicIntSenderComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.updatedValue).toStrictEqual(componentProps.updatedValue); + expect(component.changedExternally).toStrictEqual(componentProps.changedExternally); + expect(component.identifier).toStrictEqual(componentProps.identifier); + expect(component.value).toStrictEqual(componentProps.value); + }); +}); + +describe('LogicIntSenderComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new LogicIntSenderComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = + '00000000000000000000010100111001000000000000000000000001101001000000000000000000000000000100010101111111111111111111111001011100'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('LogicIntSenderComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new LogicIntSenderComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '101010111011001001000101100111000000000000000000000000001000000000000000000000000000010100111001000000000000000000000001101001000000000000000000000000000100010101111111111111111111111001011100'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // LogicIntSenderComponent data length. + const updatedValue = reader.readUnsignedInteger(); + const changedExternally = reader.readUnsignedInteger(); + const identifier = reader.readUnsignedInteger(); + const value = reader.readSignedInteger(); + + expect(hash).toStrictEqual(componentHash); + expect(updatedValue).toStrictEqual(componentProps.updatedValue); + expect(changedExternally).toStrictEqual(componentProps.changedExternally); + expect(identifier).toStrictEqual(componentProps.identifier); + expect(value).toStrictEqual(componentProps.value); + }); +}); diff --git a/src/components/LogicIntSenderComponent.ts b/src/components/LogicIntSenderComponent.ts new file mode 100644 index 0000000..76224d0 --- /dev/null +++ b/src/components/LogicIntSenderComponent.ts @@ -0,0 +1,198 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type LogicIntSenderComponentPropsV2 = { + updatedValue?: number | undefined; + changedExternally?: number | undefined; + identifier?: number | undefined; + value?: number | undefined; +}; + +export type LogicIntSenderComponentProps = LogicIntSenderComponentPropsV2; + +/** + * @see [Class: `LogicIntSenderComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/LogicIntSenderComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { LogicIntSenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicIntSenderComponent({ version: componentVersion }); + */ +export class LogicIntSenderComponent extends Component { + /** + * We're not quite sure what this property does. + * + * @since v1 + * + * @example + * import { LogicIntSenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicIntSenderComponent({ version: componentVersion }); + * + * const updatedValue = component.updatedValue; + * // `updatedValue` is `3171294583` + */ + updatedValue: number; + + /** + * We're not quite sure what this property does. + * + * @since v1 + * + * @example + * import { LogicIntSenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicIntSenderComponent({ version: componentVersion }); + * + * const changedExternally = component.changedExternally; + * // `changedExternally` is `32` + */ + changedExternally: number; + + /** + * The identifier of this `LogicIntSender` that a `LogicIntReceiver` connects to. + * + * @since v1 + * + * @example + * import { LogicIntSenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicIntSenderComponent({ version: componentVersion }); + * + * const identifier = component.identifier; + * // `identifier` is `0` + */ + identifier: number; + + /** + * The output value of this `LogicIntSender` that a `LogicIntReceiver` reads as its input. + * + * @since v1 + * + * @example + * import { LogicIntSenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicIntSenderComponent({ version: componentVersion }); + * + * const value = component.value; + * // `value` is `0` + */ + value: number; + + /** + * @see [Class: `LogicIntSenderComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/LogicIntSenderComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { LogicIntSenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicIntSenderComponent({ version: componentVersion }); + */ + constructor({ + version, + updatedValue, + changedExternally, + identifier, + value + }: ComponentProps & LogicIntSenderComponentProps) { + const hash = ComponentHash.LogicIntSender; + const name = 'LogicIntSender'; + + super({ hash, name, version }); + + this.updatedValue = updatedValue ?? 3171294583; + this.changedExternally = changedExternally ?? 32; + this.identifier = identifier ?? 0; + this.value = value ?? 0; + } + + static override fromBinary(reader: BinaryReader, version: number): LogicIntSenderComponent { + const props: ComponentProps & LogicIntSenderComponentProps = { version }; + + /** + * @property {number} updatedValue + * @since v1 + */ + if (props.version >= 1) { + props.updatedValue = reader.readUnsignedInteger(); + } + + /** + * @property {number} changedExternally + * @since v1 + */ + if (props.version >= 1) { + props.changedExternally = reader.readUnsignedInteger(); + } + + /** + * @property {number} identifier + * @since v1 + */ + if (props.version >= 1) { + props.identifier = reader.readUnsignedInteger(); + } + + /** + * @property {number} value + * @since v1 + */ + if (props.version >= 1) { + props.value = reader.readSignedInteger(); + } + + return new LogicIntSenderComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {number} updatedValue + * @since v1 + */ + if (version >= 1) { + writer.writeUnsignedInteger(this.updatedValue); + } + + /** + * @property {number} changedExternally + * @since v1 + */ + if (version >= 1) { + writer.writeUnsignedInteger(this.changedExternally); + } + + /** + * @property {number} identifier + * @since v1 + */ + if (version >= 1) { + writer.writeUnsignedInteger(this.identifier); + } + + /** + * @property {number} value + * @since v1 + */ + if (version >= 1) { + writer.writeSignedInteger(this.value); + } + + return writer.flush(); + } +} diff --git a/src/components/LogicVector3ReceiverComponent.test.ts b/src/components/LogicVector3ReceiverComponent.test.ts new file mode 100644 index 0000000..79fab5a --- /dev/null +++ b/src/components/LogicVector3ReceiverComponent.test.ts @@ -0,0 +1,126 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { LogicVector3ReceiverComponent } from './LogicVector3ReceiverComponent.js'; + +const componentHash = ComponentHash.LogicVector3Receiver; +const componentName = 'LogicVector3Receiver'; +const componentVersion = 1; +const componentProps = { + sender: 1337 +}; + +describe('new LogicVector3ReceiverComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the LogicVector3ReceiverComponent class', () => { + const component = new LogicVector3ReceiverComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(LogicVector3ReceiverComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the LogicVector3ReceiverComponent class', () => { + const component = new LogicVector3ReceiverComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(LogicVector3ReceiverComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.sender).toStrictEqual(componentProps.sender); + }); + }); +}); + +describe('LogicVector3ReceiverComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('MRK_Small_Lever', { + components: { + LogicVector3Receiver: new LogicVector3ReceiverComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // LogicVector3ReceiverComponent hash. + reader.readUnsignedInteger(); // LogicVector3ReceiverComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the LogicVector3ReceiverComponent class', () => { + const component = LogicVector3ReceiverComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(LogicVector3ReceiverComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.sender).toStrictEqual(componentProps.sender); + }); +}); + +describe('LogicVector3ReceiverComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new LogicVector3ReceiverComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = '00000000000000000000010100111001'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('LogicVector3ReceiverComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new LogicVector3ReceiverComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '010010010011101000000100110110010000000000000000000000000010000000000000000000000000010100111001'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // LogicVector3ReceiverComponent data length. + const sender = reader.readUnsignedInteger(); + + expect(hash).toStrictEqual(componentHash); + expect(sender).toStrictEqual(componentProps.sender); + }); +}); diff --git a/src/components/LogicVector3ReceiverComponent.ts b/src/components/LogicVector3ReceiverComponent.ts new file mode 100644 index 0000000..10aa42e --- /dev/null +++ b/src/components/LogicVector3ReceiverComponent.ts @@ -0,0 +1,90 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type LogicVector3ReceiverComponentPropsV1 = { + sender?: number | undefined; +}; + +export type LogicVector3ReceiverComponentProps = LogicVector3ReceiverComponentPropsV1; + +/** + * @see [Class: `LogicVector3ReceiverComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/LogicVector3ReceiverComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { LogicVector3ReceiverComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicVector3ReceiverComponent({ version: componentVersion }); + */ +export class LogicVector3ReceiverComponent extends Component { + /** + * The identifier of the `LogicVector3Sender` that is connected to this `LogicVector3Receiver`. + * + * @since v1 + * + * @example + * import { LogicVector3ReceiverComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicVector3ReceiverComponent({ version: componentVersion }); + * + * const sender = component.sender; + * // `sender` is `0` + */ + sender: number; + + /** + * @see [Class: `LogicVector3ReceiverComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/LogicVector3ReceiverComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { LogicVector3ReceiverComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicVector3ReceiverComponent({ version: componentVersion }); + */ + constructor({ version, sender }: ComponentProps & LogicVector3ReceiverComponentProps) { + const hash = ComponentHash.LogicVector3Receiver; + const name = 'LogicVector3Receiver'; + + super({ hash, name, version }); + + this.sender = sender ?? 0; + } + + static override fromBinary(reader: BinaryReader, version: number): LogicVector3ReceiverComponent { + const props: ComponentProps & LogicVector3ReceiverComponentProps = { version }; + + /** + * @property {number} sender + * @since v1 + */ + if (props.version >= 1) { + props.sender = reader.readUnsignedInteger(); + } + + return new LogicVector3ReceiverComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {number} sender + * @since v1 + */ + if (version >= 1) { + writer.writeUnsignedInteger(this.sender); + } + + return writer.flush(); + } +} diff --git a/src/components/LogicVector3SenderComponent.test.ts b/src/components/LogicVector3SenderComponent.test.ts new file mode 100644 index 0000000..c383ce4 --- /dev/null +++ b/src/components/LogicVector3SenderComponent.test.ts @@ -0,0 +1,146 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { LogicVector3SenderComponent } from './LogicVector3SenderComponent.js'; + +const componentHash = ComponentHash.LogicVector3Sender; +const componentName = 'LogicVector3Sender'; +const componentVersion = 1; +const componentProps = { + updatedValue: 1337, + changedExternally: 420, + identifier: 69, + value: { x: 69, y: 420, z: 1337 } +}; + +describe('new LogicVector3SenderComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the LogicVector3SenderComponent class', () => { + const component = new LogicVector3SenderComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(LogicVector3SenderComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the LogicVector3SenderComponent class', () => { + const component = new LogicVector3SenderComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(LogicVector3SenderComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.updatedValue).toStrictEqual(componentProps.updatedValue); + expect(component.changedExternally).toStrictEqual(componentProps.changedExternally); + expect(component.identifier).toStrictEqual(componentProps.identifier); + expect(component.value).toStrictEqual(componentProps.value); + }); + }); +}); + +describe('LogicVector3SenderComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('MRK_Small_Lever', { + components: { + LogicVector3Sender: new LogicVector3SenderComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // LogicVector3SenderComponent hash. + reader.readUnsignedInteger(); // LogicVector3SenderComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the LogicVector3SenderComponent class', () => { + const component = LogicVector3SenderComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(LogicVector3SenderComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.updatedValue).toStrictEqual(componentProps.updatedValue); + expect(component.changedExternally).toStrictEqual(componentProps.changedExternally); + expect(component.identifier).toStrictEqual(componentProps.identifier); + expect(component.value).toStrictEqual(componentProps.value); + }); +}); + +describe('LogicVector3SenderComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new LogicVector3SenderComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = + '000000000000000000000101001110010000000000000000000000011010010000000000000000000000000001000101010000101000101000000000000000000100001111010010000000000000000001000100101001110010000000000000'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('LogicVector3SenderComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new LogicVector3SenderComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '0111100011001101101001111011001100000000000000000000000011000000000000000000000000000101001110010000000000000000000000011010010000000000000000000000000001000101010000101000101000000000000000000100001111010010000000000000000001000100101001110010000000000000'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // LogicVector3SenderComponent data length. + const updatedValue = reader.readUnsignedInteger(); + const changedExternally = reader.readUnsignedInteger(); + const identifier = reader.readUnsignedInteger(); + const value = { + x: reader.readFloat(), + y: reader.readFloat(), + z: reader.readFloat() + }; + + expect(hash).toStrictEqual(componentHash); + expect(updatedValue).toStrictEqual(componentProps.updatedValue); + expect(changedExternally).toStrictEqual(componentProps.changedExternally); + expect(identifier).toStrictEqual(componentProps.identifier); + expect(value).toStrictEqual(componentProps.value); + }); +}); diff --git a/src/components/LogicVector3SenderComponent.ts b/src/components/LogicVector3SenderComponent.ts new file mode 100644 index 0000000..f10c663 --- /dev/null +++ b/src/components/LogicVector3SenderComponent.ts @@ -0,0 +1,206 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type Vector3 = { x: number; y: number; z: number }; + +type LogicVector3SenderComponentPropsV1 = { + updatedValue?: number | undefined; + changedExternally?: number | undefined; + identifier?: number | undefined; + value?: Vector3 | undefined; +}; + +export type LogicVector3SenderComponentProps = LogicVector3SenderComponentPropsV1; + +/** + * @see [Class: `LogicVector3SenderComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/LogicVector3SenderComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { LogicVector3SenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicVector3SenderComponent({ version: componentVersion }); + */ +export class LogicVector3SenderComponent extends Component { + /** + * We're not quite sure what this property does. + * + * @since v1 + * + * @example + * import { LogicVector3SenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicVector3SenderComponent({ version: componentVersion }); + * + * const updatedValue = component.updatedValue; + * // `updatedValue` is `3171294583` + */ + updatedValue: number; + + /** + * We're not quite sure what this property does. + * + * @since v1 + * + * @example + * import { LogicVector3SenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicVector3SenderComponent({ version: componentVersion }); + * + * const changedExternally = component.changedExternally; + * // `changedExternally` is `32` + */ + changedExternally: number; + + /** + * The identifier of this `LogicVector3Sender` that a `LogicVector3Receiver` connects to. + * + * @since v1 + * + * @example + * import { LogicVector3SenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicVector3SenderComponent({ version: componentVersion }); + * + * const identifier = component.identifier; + * // `identifier` is `0` + */ + identifier: number; + + /** + * The output value of this `LogicVector3Sender` that a `LogicVector3Receiver` reads as its input. + * + * @since v1 + * + * @example + * import { LogicVector3SenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicVector3SenderComponent({ version: componentVersion }); + * + * const value = component.value; + * // `value` is `{ x: 0, y: 0, z: 0 }` + */ + value: Vector3; + + /** + * @see [Class: `LogicVector3SenderComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/LogicVector3SenderComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { LogicVector3SenderComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new LogicVector3SenderComponent({ version: componentVersion }); + */ + constructor({ + version, + updatedValue, + changedExternally, + identifier, + value + }: ComponentProps & LogicVector3SenderComponentProps) { + const hash = ComponentHash.LogicVector3Sender; + const name = 'LogicVector3Sender'; + + super({ hash, name, version }); + + this.updatedValue = updatedValue ?? 3171294583; + this.changedExternally = changedExternally ?? 32; + this.identifier = identifier ?? 0; + this.value = value ?? { x: 0, y: 0, z: 0 }; + } + + static override fromBinary(reader: BinaryReader, version: number): LogicVector3SenderComponent { + const props: ComponentProps & LogicVector3SenderComponentProps = { version }; + + /** + * @property {number} updatedValue + * @since v1 + */ + if (props.version >= 1) { + props.updatedValue = reader.readUnsignedInteger(); + } + + /** + * @property {number} changedExternally + * @since v1 + */ + if (props.version >= 1) { + props.changedExternally = reader.readUnsignedInteger(); + } + + /** + * @property {number} identifier + * @since v1 + */ + if (props.version >= 1) { + props.identifier = reader.readUnsignedInteger(); + } + + /** + * @property {Vector3} value + * @since v1 + */ + if (props.version >= 1) { + props.value = { + x: reader.readFloat(), + y: reader.readFloat(), + z: reader.readFloat() + }; + } + + return new LogicVector3SenderComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {number} updatedValue + * @since v1 + */ + if (version >= 1) { + writer.writeUnsignedInteger(this.updatedValue); + } + + /** + * @property {number} changedExternally + * @since v1 + */ + if (version >= 1) { + writer.writeUnsignedInteger(this.changedExternally); + } + + /** + * @property {number} identifier + * @since v1 + */ + if (version >= 1) { + writer.writeUnsignedInteger(this.identifier); + } + + /** + * @property {Vector3} value + * @since v1 + */ + if (version >= 1) { + writer.writeFloat(this.value.x); + writer.writeFloat(this.value.y); + writer.writeFloat(this.value.z); + } + + return writer.flush(); + } +} diff --git a/src/components/NetworkRigidbodyComponent.test.ts b/src/components/NetworkRigidbodyComponent.test.ts new file mode 100644 index 0000000..a1b53c9 --- /dev/null +++ b/src/components/NetworkRigidbodyComponent.test.ts @@ -0,0 +1,169 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { NetworkRigidbodyComponent } from './NetworkRigidbodyComponent.js'; + +const componentHash = ComponentHash.NetworkRigidbody; +const componentName = 'NetworkRigidbody'; +const componentVersion = 1; +const componentProps = { + position: { x: 1337, y: 420, z: 69 }, + rotation: { x: 1337, y: 420, z: 69, w: 1 }, + isKinematic: true, + isServerSleeping: false, + velocity: { x: 1337, y: 420, z: 69 }, + angularVelocity: { x: 1337, y: 420, z: 69 } +}; + +describe('new NetworkRigidbodyComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the NetworkRigidbodyComponent class', () => { + const component = new NetworkRigidbodyComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(NetworkRigidbodyComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the NetworkRigidbodyComponent class', () => { + const component = new NetworkRigidbodyComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(NetworkRigidbodyComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.position).toStrictEqual(componentProps.position); + expect(component.rotation).toStrictEqual(componentProps.rotation); + expect(component.isKinematic).toStrictEqual(componentProps.isKinematic); + expect(component.isServerSleeping).toStrictEqual(componentProps.isServerSleeping); + expect(component.velocity).toStrictEqual(componentProps.velocity); + expect(component.angularVelocity).toStrictEqual(componentProps.angularVelocity); + }); + }); +}); + +describe('NetworkRigidbodyComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('Grass_Clump', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // NetworkRigidbodyComponent hash. + reader.readUnsignedInteger(); // NetworkRigidbodyComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the NetworkRigidbodyComponent class', () => { + const component = NetworkRigidbodyComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(NetworkRigidbodyComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.position).toStrictEqual(componentProps.position); + expect(component.rotation).toStrictEqual(componentProps.rotation); + expect(component.isKinematic).toStrictEqual(componentProps.isKinematic); + expect(component.isServerSleeping).toStrictEqual(componentProps.isServerSleeping); + expect(component.velocity).toStrictEqual(componentProps.velocity); + expect(component.angularVelocity).toStrictEqual(componentProps.angularVelocity); + }); +}); + +describe('NetworkRigidbodyComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new NetworkRigidbodyComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = + '0100010010100111001000000000000001000011110100100000000000000000010000101000101000000000000000000100010010100111001000000000000001000011110100100000000000000000010000101000101000000000000000000011111110000000000000000000000010010001001010011100100000000000000100001111010010000000000000000001000010100010100000000000000000010001001010011100100000000000000100001111010010000000000000000001000010100010100000000000000000'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('NetworkRigidbodyComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new NetworkRigidbodyComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '10001000100011011001000000000111000000000000000000000001101000100100010010100111001000000000000001000011110100100000000000000000010000101000101000000000000000000100010010100111001000000000000001000011110100100000000000000000010000101000101000000000000000000011111110000000000000000000000010010001001010011100100000000000000100001111010010000000000000000001000010100010100000000000000000010001001010011100100000000000000100001111010010000000000000000001000010100010100000000000000000'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // NetworkRigidbodyComponent data length. + const position = { + x: reader.readFloat(), + y: reader.readFloat(), + z: reader.readFloat() + }; + const rotation = { + x: reader.readFloat(), + y: reader.readFloat(), + z: reader.readFloat(), + w: reader.readFloat() + }; + const isKinematic = reader.readBoolean(); + const isServerSleeping = reader.readBoolean(); + const velocity = { + x: reader.readFloat(), + y: reader.readFloat(), + z: reader.readFloat() + }; + const angularVelocity = { + x: reader.readFloat(), + y: reader.readFloat(), + z: reader.readFloat() + }; + + expect(hash).toStrictEqual(componentHash); + expect(position).toStrictEqual(componentProps.position); + expect(rotation).toStrictEqual(componentProps.rotation); + expect(isKinematic).toStrictEqual(componentProps.isKinematic); + expect(isServerSleeping).toStrictEqual(componentProps.isServerSleeping); + expect(velocity).toStrictEqual(componentProps.velocity); + expect(angularVelocity).toStrictEqual(componentProps.angularVelocity); + }); +}); diff --git a/src/components/NetworkRigidbodyComponent.ts b/src/components/NetworkRigidbodyComponent.ts new file mode 100644 index 0000000..7a6c067 --- /dev/null +++ b/src/components/NetworkRigidbodyComponent.ts @@ -0,0 +1,300 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { AngularVelocity } from '../types/AngularVelocity.js'; +import type { BinaryString } from '../types/BinaryString.js'; +import type { Position } from '../types/Position.js'; +import type { Rotation } from '../types/Rotation.js'; +import type { Velocity } from '../types/Velocity.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type NetworkRigidbodyComponentPropsV1 = { + position?: Position | undefined; + rotation?: Rotation | undefined; + isKinematic?: boolean | undefined; + isServerSleeping?: boolean | undefined; + velocity?: Velocity | undefined; + angularVelocity?: AngularVelocity | undefined; +}; + +export type NetworkRigidbodyComponentProps = NetworkRigidbodyComponentPropsV1; + +/** + * Controls physical behaviour of the `Prefab` it is attached to. + * + * @see [Class: `NetworkRigidbodyComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/NetworkRigidbodyComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { NetworkRigidbodyComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new NetworkRigidbodyComponent({ version: componentVersion }); + */ +export class NetworkRigidbodyComponent extends Component { + /** + * Position of the prefab this component is attached to. + * + * @since v1 + * + * @example + * import { NetworkRigidbodyComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new NetworkRigidbodyComponent({ version: componentVersion }); + * + * const position = component.position; + * // `position` is `{ x: 0, y: 0, z: 0 }` + */ + position: Position; + + /** + * Rotation of the prefab this component is attached to. + * + * @since v1 + * + * @example + * import { NetworkRigidbodyComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new NetworkRigidbodyComponent({ version: componentVersion }); + * + * const rotation = component.rotation; + * // `rotation` is `{ x: 0, y: 0, z: 0, w: 1 }` + */ + rotation: Rotation; + + /** + * Whether the prefab this component is attached to is [kinematic](https://docs.unity3d.com/ScriptReference/Rigidbody-isKinematic.html) or not. + * + * @since v1 + * + * @example + * import { NetworkRigidbodyComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new NetworkRigidbodyComponent({ version: componentVersion }); + * + * const isKinematic = component.isKinematic; + * // `isKinematic` is `false` + */ + isKinematic: boolean; + + /** + * Whether the prefab this component is attached to is [sleeping](https://docs.unity3d.com/Manual/RigidbodiesOverview.html) or not. + * + * @since v1 + * + * @example + * import { NetworkRigidbodyComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new NetworkRigidbodyComponent({ version: componentVersion }); + * + * const isServerSleeping = component.isServerSleeping; + * // `isServerSleeping` is `false` + */ + isServerSleeping: boolean; + + /** + * Velocity of the prefab this component is attached to. + * + * @since v1 + * + * @example + * import { NetworkRigidbodyComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new NetworkRigidbodyComponent({ version: componentVersion }); + * + * const velocity = component.velocity; + * // `velocity` is `{ x: 0, y: 0, z: 0 }` + */ + velocity: Velocity; + + /** + * Angular velocity of the prefab this component is attached to. + * + * @since v1 + * + * @example + * import { NetworkRigidbodyComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new NetworkRigidbodyComponent({ version: componentVersion }); + * + * const angularVelocity = component.angularVelocity; + * // `angularVelocity` is `{ x: 0, y: 0, z: 0 }` + */ + angularVelocity: AngularVelocity; + + /** + * @see [Class: `NetworkRigidbodyComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/NetworkRigidbodyComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { NetworkRigidbodyComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new NetworkRigidbodyComponent({ version: componentVersion }); + */ + constructor({ + version, + position, + rotation, + isKinematic, + isServerSleeping, + velocity, + angularVelocity + }: ComponentProps & NetworkRigidbodyComponentProps) { + const hash = ComponentHash.NetworkRigidbody; + const name = 'NetworkRigidbody'; + + super({ hash, name, version }); + + this.position = position ?? { x: 0, y: 0, z: 0 }; + this.rotation = rotation ?? { x: 0, y: 0, z: 0, w: 1 }; + this.isKinematic = isKinematic ?? false; + this.isServerSleeping = isServerSleeping ?? false; + this.velocity = velocity ?? { x: 0, y: 0, z: 0 }; + this.angularVelocity = angularVelocity ?? { x: 0, y: 0, z: 0 }; + } + + static override fromBinary(reader: BinaryReader, version: number): NetworkRigidbodyComponent { + const props: ComponentProps & NetworkRigidbodyComponentProps = { version }; + + /** + * @property {Position} position + * @since v1 + */ + if (props.version >= 1) { + props.position = { + x: reader.readFloat(), + y: reader.readFloat(), + z: reader.readFloat() + }; + } + + /** + * @property {Rotation} rotation + * @since v1 + */ + if (props.version >= 1) { + props.rotation = { + x: reader.readFloat(), + y: reader.readFloat(), + z: reader.readFloat(), + w: reader.readFloat() + }; + } + + /** + * @property {boolean} isKinematic + * @since v1 + */ + if (props.version >= 1) { + props.isKinematic = reader.readBoolean(); + } + + /** + * @property {boolean} isServerSleeping + * @since v1 + */ + if (props.version >= 1) { + props.isServerSleeping = reader.readBoolean(); + } + + /** + * @property {Velocity} velocity + * @since v1 + */ + if (props.version >= 1) { + props.velocity = { + x: reader.readFloat(), + y: reader.readFloat(), + z: reader.readFloat() + }; + } + + /** + * @property {AngularVelocity} angularVelocity + * @since v1 + */ + if (props.version >= 1) { + props.angularVelocity = { + x: reader.readFloat(), + y: reader.readFloat(), + z: reader.readFloat() + }; + } + + return new NetworkRigidbodyComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {Position} position + * @since v1 + */ + if (version >= 1) { + writer.writeFloat(this.position.x); + writer.writeFloat(this.position.y); + writer.writeFloat(this.position.z); + } + + /** + * @property {Rotation} rotation + * @since v1 + */ + if (version >= 1) { + writer.writeFloat(this.rotation.x); + writer.writeFloat(this.rotation.y); + writer.writeFloat(this.rotation.z); + writer.writeFloat(this.rotation.w); + } + + /** + * @property {boolean} isKinematic + * @since v1 + */ + if (version >= 1) { + writer.writeBoolean(this.isKinematic); + } + + /** + * @property {boolean} isServerSleeping + * @since v1 + */ + if (version >= 1) { + writer.writeBoolean(this.isServerSleeping); + } + + /** + * @property {Velocity} velocity + * @since v1 + */ + if (version >= 1) { + writer.writeFloat(this.velocity.x); + writer.writeFloat(this.velocity.y); + writer.writeFloat(this.velocity.z); + } + + /** + * @property {AngularVelocity} angularVelocity + * @since v1 + */ + if (version >= 1) { + writer.writeFloat(this.angularVelocity.x); + writer.writeFloat(this.angularVelocity.y); + writer.writeFloat(this.angularVelocity.z); + } + + return writer.flush(); + } +} diff --git a/src/components/PhysicalMaterialPartComponent.test.ts b/src/components/PhysicalMaterialPartComponent.test.ts new file mode 100644 index 0000000..dbdf3c8 --- /dev/null +++ b/src/components/PhysicalMaterialPartComponent.test.ts @@ -0,0 +1,126 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { PhysicalMaterialPartComponent } from './PhysicalMaterialPartComponent.js'; + +const componentHash = ComponentHash.PhysicalMaterialPart; +const componentName = 'PhysicalMaterialPart'; +const componentVersion = 1; +const componentProps = { + materialHash: 1337 +}; + +describe('new PhysicalMaterialPartComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the PhysicalMaterialPartComponent class', () => { + const component = new PhysicalMaterialPartComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(PhysicalMaterialPartComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the PhysicalMaterialPartComponent class', () => { + const component = new PhysicalMaterialPartComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(PhysicalMaterialPartComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.materialHash).toStrictEqual(componentProps.materialHash); + }); + }); +}); + +describe('PhysicalMaterialPartComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('Grass_Clump', { + components: { + PhysicalMaterialPart: new PhysicalMaterialPartComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // PhysicalMaterialPartComponent hash. + reader.readUnsignedInteger(); // PhysicalMaterialPartComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the PhysicalMaterialPartComponent class', () => { + const component = PhysicalMaterialPartComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(PhysicalMaterialPartComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.materialHash).toStrictEqual(componentProps.materialHash); + }); +}); + +describe('PhysicalMaterialPartComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new PhysicalMaterialPartComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = '00000000000000000000010100111001'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('PhysicalMaterialPartComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new PhysicalMaterialPartComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '000100000011100101000100011001010000000000000000000000000010000000000000000000000000010100111001'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // PhysicalMaterialPartComponent data length. + const materialHash = reader.readUnsignedInteger(); + + expect(hash).toStrictEqual(componentHash); + expect(materialHash).toStrictEqual(componentProps.materialHash); + }); +}); diff --git a/src/components/PhysicalMaterialPartComponent.ts b/src/components/PhysicalMaterialPartComponent.ts new file mode 100644 index 0000000..b6f16bd --- /dev/null +++ b/src/components/PhysicalMaterialPartComponent.ts @@ -0,0 +1,93 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; +import { PhysicalMaterialPartHash } from '../types/PhysicalMaterialPartHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type PhysicalMaterialPartComponentPropsV1 = { + materialHash?: number | undefined; +}; + +export type PhysicalMaterialPartComponentProps = PhysicalMaterialPartComponentPropsV1; + +/** + * Controls physical appearance of the `Prefab` it is attached to. + * + * @see [Class: `PhysicalMaterialPartComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/PhysicalMaterialPartComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { PhysicalMaterialPartComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new PhysicalMaterialPartComponent({ version: componentVersion }); + */ +export class PhysicalMaterialPartComponent extends Component { + /** + * The hash of the physical material of the prefab this component is attached to. + * + * @since v1 + * + * @example + * import { PhysicalMaterialPartComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new PhysicalMaterialPartComponent({ version: componentVersion }); + * + * const materialHash = component.materialHash; + * // `materialHash` is `1` + */ + materialHash: number; + + /** + * @see [Class: `PhysicalMaterialPartComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/PhysicalMaterialPartComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { PhysicalMaterialPartComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new PhysicalMaterialPartComponent({ version: componentVersion }); + */ + constructor({ version, materialHash }: ComponentProps & PhysicalMaterialPartComponentProps) { + const hash = ComponentHash.PhysicalMaterialPart; + const name = 'PhysicalMaterialPart'; + + super({ hash, name, version }); + + this.materialHash = materialHash ?? PhysicalMaterialPartHash.Iron; + } + + static override fromBinary(reader: BinaryReader, version: number): PhysicalMaterialPartComponent { + const props: ComponentProps & PhysicalMaterialPartComponentProps = { version }; + + /** + * @property {number} materialHash + * @since v1 + */ + if (props.version >= 1) { + props.materialHash = reader.readUnsignedInteger(); + } + + return new PhysicalMaterialPartComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {number} materialHash + * @since v1 + */ + if (version >= 1) { + writer.writeUnsignedInteger(this.materialHash); + } + + return writer.flush(); + } +} diff --git a/src/components/PickupComponent.test.ts b/src/components/PickupComponent.test.ts new file mode 100644 index 0000000..9b24fca --- /dev/null +++ b/src/components/PickupComponent.test.ts @@ -0,0 +1,366 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { PickupComponent, type PickupComponentProps } from './PickupComponent.js'; + +const componentHash = ComponentHash.Pickup; +const componentName = 'Pickup'; + +const grabPointParameters = { + grabPointIndex: -420, + lastLinearPosition: 0.69, + lastPosition: { + x: 1337, + y: 420, + z: 69 + }, + lastRotation: { + x: 1337, + y: 420, + z: 69, + w: 1 + } +}; + +const componentPropsV1 = { + lastInteractorPlayerId: 1337 +}; + +const componentPropsV2 = { + lastInteractorPlayerId: 1337, + dockedMemory: [grabPointParameters] +}; + +describe('new PickupComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the PickupComponent class', () => { + const componentVersion = 2; + const component = new PickupComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(PickupComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + describe('for version 1', () => { + const componentVersion = 1; + const componentProps = componentPropsV1; + + it('returns an instance of the PickupComponent class', () => { + const component = new PickupComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(PickupComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.lastInteractorPlayerId).toStrictEqual(componentProps.lastInteractorPlayerId); + }); + }); + + describe('for version 2', () => { + const componentVersion = 2; + const componentProps = componentPropsV2; + + it('returns an instance of the PickupComponent class', () => { + const component = new PickupComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(PickupComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.lastInteractorPlayerId).toStrictEqual(componentProps.lastInteractorPlayerId); + expect(component.dockedMemory).toStrictEqual(componentProps.dockedMemory); + }); + }); + }); +}); + +describe('PickupComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + describe('for version 1', () => { + const componentVersion = 1; + const componentProps = componentPropsV1; + + const prefab = new Prefab('Grass_Clump', { + components: { + Pickup: new PickupComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // PickupComponent hash. + reader.readUnsignedInteger(); // PickupComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the PickupComponent class', () => { + const component = PickupComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(PickupComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.lastInteractorPlayerId).toStrictEqual(componentProps.lastInteractorPlayerId); + }); + }); + + describe('for version 2', () => { + describe('when all component props are given', () => { + const componentVersion = 2; + const componentProps = componentPropsV2; + + const prefab = new Prefab('Grass_Clump', { + components: { + Pickup: new PickupComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // PickupComponent hash. + reader.readUnsignedInteger(); // PickupComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the PickupComponent class', () => { + const component = PickupComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(PickupComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.lastInteractorPlayerId).toStrictEqual(componentProps.lastInteractorPlayerId); + expect(component.dockedMemory[0]?.grabPointIndex).toStrictEqual(componentProps.dockedMemory[0]?.grabPointIndex); + expect(component.dockedMemory[0]?.lastLinearPosition).toBeCloseTo( + componentProps.dockedMemory[0]?.lastLinearPosition ?? 0, + 2 + ); + expect(component.dockedMemory[0]?.lastPosition).toStrictEqual(componentProps.dockedMemory[0]?.lastPosition); + expect(component.dockedMemory[0]?.lastRotation).toStrictEqual(componentProps.dockedMemory[0]?.lastRotation); + }); + }); + + describe('when GrabPointParameters is null', () => { + const componentVersion = 2; + let componentProps: PickupComponentProps; + + beforeEach(() => { + componentProps = componentPropsV2; + componentProps.dockedMemory = [null]; + + const prefab = new Prefab('Grass_Clump', { + components: { + Pickup: new PickupComponent({ version: componentVersion, ...componentProps }) + } + }); + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // PickupComponent hash. + reader.readUnsignedInteger(); // PickupComponent data length. + + fastForwardedReader = reader; + }); + + afterEach(() => { + componentProps.dockedMemory = [grabPointParameters]; + }); + + it('returns an instance of the PickupComponent class', () => { + const component = PickupComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(PickupComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.lastInteractorPlayerId).toStrictEqual(componentProps.lastInteractorPlayerId); + expect(component.dockedMemory).toStrictEqual([null]); + }); + }); + }); +}); + +describe('PickupComponent.toBinary()', () => { + describe('for version 1', () => { + const componentVersion = 1; + const componentProps = componentPropsV1; + + it('returns a BinaryString representation of the component', () => { + const component = new PickupComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = '10000000000000000000010100111001'; + + expect(data).toStrictEqual(expectedData); + }); + }); + + describe('for version 2', () => { + const componentVersion = 2; + const componentProps = componentPropsV2; + + it('returns a BinaryString representation of the component', () => { + const component = new PickupComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = + '10000000000000000000010100111001000000000000000000000000000000010011111111111111111111110010111000011111100110000101000111101011101000100101001110010000000000000010000111101001000000000000000000100001010001010000000000000000001000100101001110010000000000000010000111101001000000000000000000100001010001010000000000000000000111111100000000000000000000000'; + + expect(data).toStrictEqual(expectedData); + }); + }); +}); + +describe('PickupComponent.write()', () => { + describe('for version 1', () => { + const componentVersion = 1; + const componentProps = componentPropsV1; + + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new PickupComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '010101101011000100000011101101100000000000000000000000000010000010000000000000000000010100111001'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // PickupComponent data length. + const lastInteractorPlayerId = reader.readSignedInteger(); + + expect(hash).toStrictEqual(componentHash); + expect(lastInteractorPlayerId).toStrictEqual(componentProps.lastInteractorPlayerId); + }); + }); + + describe('for version 2', () => { + const componentVersion = 2; + const componentProps = componentPropsV2; + + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new PickupComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '010101101011000100000011101101100000000000000000000000010110000110000000000000000000010100111001000000000000000000000000000000010011111111111111111111110010111000011111100110000101000111101011101000100101001110010000000000000010000111101001000000000000000000100001010001010000000000000000001000100101001110010000000000000010000111101001000000000000000000100001010001010000000000000000000111111100000000000000000000000'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // PickupComponent data length. + const lastInteractorPlayerId = reader.readSignedInteger(); + reader.readUnsignedInteger(); // GrabPointParameters array length. + const isNullBit = reader.readBoolean(); + const grabPointIndex = reader.readSignedInteger(); + const lastLinearPosition = reader.readFloat(); + const lastPosition = { + x: reader.readFloat(), + y: reader.readFloat(), + z: reader.readFloat() + }; + const lastRotation = { + x: reader.readFloat(), + y: reader.readFloat(), + z: reader.readFloat(), + w: reader.readFloat() + }; + + expect(hash).toStrictEqual(componentHash); + expect(lastInteractorPlayerId).toStrictEqual(componentProps.lastInteractorPlayerId); + expect(isNullBit).toStrictEqual(false); + expect(grabPointIndex).toStrictEqual(componentProps.dockedMemory[0]?.grabPointIndex); + expect(lastLinearPosition).toBeCloseTo(componentProps.dockedMemory[0]?.lastLinearPosition ?? 0, 2); + expect(lastPosition).toStrictEqual(componentProps.dockedMemory[0]?.lastPosition); + expect(lastRotation).toStrictEqual(componentProps.dockedMemory[0]?.lastRotation); + }); + }); +}); diff --git a/src/components/PickupComponent.ts b/src/components/PickupComponent.ts new file mode 100644 index 0000000..319fed0 --- /dev/null +++ b/src/components/PickupComponent.ts @@ -0,0 +1,230 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; +import type { Position } from '../types/Position.js'; +import type { Rotation } from '../types/Rotation.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type GrabPointParameters = null | { + grabPointIndex: number; + lastLinearPosition: number; + lastPosition: Position; + lastRotation: Rotation; +}; + +type PickupComponentPropsV1 = { + lastInteractorPlayerId?: number | undefined; + dockedMemory?: never; +}; + +type PickupComponentPropsV2 = { + lastInteractorPlayerId?: number | undefined; + dockedMemory?: GrabPointParameters[] | undefined; +}; + +export type PickupComponentProps = PickupComponentPropsV1 | PickupComponentPropsV2; + +/** + * @see [Class: `BasicDecayComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/BasicDecayComponent.md) + * @since v3.0.0 + * @version 2 + * + * @example + * import { PickupComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new PickupComponent({ version: componentVersion }); + */ +export class PickupComponent extends Component { + /** + * The ID of the player that last interacted with the prefab that this component is attached to. + * + * @since v1 + * + * @example + * import { PickupComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new PickupComponent({ version: componentVersion }); + * + * const lastInteractorPlayerId = component.lastInteractorPlayerId; + * // `lastInteractorPlayerId` is `0` + */ + lastInteractorPlayerId: number; + + /** + * An array of `` that describes the orientation of prefabs when they were + * docked. Used to control in which orientation pickups should be held when grabbed from the dock + * attached to the same prefab this component is attached to. + * + * @since v2 + * + * @example + * import { PickupComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new PickupComponent({ version: componentVersion }); + * + * const dockedMemory = component.dockedMemory; + * // `dockedMemory` is `[]` + */ + dockedMemory: GrabPointParameters[]; + + /** + * @see [Class: `BasicDecayComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/BasicDecayComponent.md) + * @since v3.0.0 + * @version 2 + * + * @example + * import { PickupComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new PickupComponent({ version: componentVersion }); + */ + constructor({ version, lastInteractorPlayerId, dockedMemory }: ComponentProps & PickupComponentProps) { + const hash = ComponentHash.Pickup; + const name = 'Pickup'; + + super({ hash, name, version }); + + this.lastInteractorPlayerId = lastInteractorPlayerId ?? 0; + this.dockedMemory = dockedMemory ?? []; + } + + static override fromBinary(reader: BinaryReader, version: number): PickupComponent { + const props: ComponentProps & PickupComponentProps = { version }; + + /** + * @property {number} lastInteractorPlayerId + * @since v1 + */ + if (props.version >= 1) { + props.lastInteractorPlayerId = reader.readSignedInteger(); + } + + /** + * @property {GrabPointParameters[]} dockedMemory + * @since v2 + */ + if (props.version >= 2) { + const grabPointParametersLength = reader.readUnsignedInteger(); + props.dockedMemory = []; + + for (let index = 0; index < grabPointParametersLength; ++index) { + /** + * @property {boolean} isNull + * @since v2 + */ + const isNull = reader.readBoolean(); + + if (isNull) { + props.dockedMemory.push(null); + continue; + } + + props.dockedMemory.push({ + /** + * @property {number} grabPointIndex + * @since v2 + */ + grabPointIndex: reader.readSignedInteger(), + + /** + * @property {float} lastLinearPosition + * @since v2 + */ + lastLinearPosition: reader.readFloat(), + + /** + * @property {Position} lastPosition + * @since v2 + */ + lastPosition: { + x: reader.readFloat(), + y: reader.readFloat(), + z: reader.readFloat() + }, + + /** + * @property {Rotation} lastRotation + * @since v2 + */ + lastRotation: { + x: reader.readFloat(), + y: reader.readFloat(), + z: reader.readFloat(), + w: reader.readFloat() + } + }); + } + } + + return new PickupComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {number} lastInteractorPlayerId + * @since v1 + */ + if (version >= 1) { + writer.writeSignedInteger(this.lastInteractorPlayerId); + } + + /** + * @property {GrabPointParameters[]} dockedMemory + * @since v2 + */ + if (version >= 2) { + writer.writeUnsignedInteger(this.dockedMemory.length); + + for (const grabPointParameters of this.dockedMemory) { + const isNull = grabPointParameters === null; + + /** + * @property {boolean} isNull + * @since v2 + */ + writer.writeBoolean(isNull); + + if (!isNull) { + /** + * @property {number} grabPointIndex + * @since v2 + */ + writer.writeSignedInteger(grabPointParameters.grabPointIndex); + + /** + * @property {float} lastLinearPosition + * @since v2 + */ + writer.writeFloat(grabPointParameters.lastLinearPosition); + + /** + * @property {Position} lastPosition + * @since v2 + */ + writer.writeFloat(grabPointParameters.lastPosition.x); + writer.writeFloat(grabPointParameters.lastPosition.y); + writer.writeFloat(grabPointParameters.lastPosition.z); + + /** + * @property {Rotation} lastRotation + * @since v2 + */ + writer.writeFloat(grabPointParameters.lastRotation.x); + writer.writeFloat(grabPointParameters.lastRotation.y); + writer.writeFloat(grabPointParameters.lastRotation.z); + writer.writeFloat(grabPointParameters.lastRotation.w); + } + } + } + + return writer.flush(); + } +} diff --git a/src/components/PickupDockComponent.test.ts b/src/components/PickupDockComponent.test.ts new file mode 100644 index 0000000..db2f4ee --- /dev/null +++ b/src/components/PickupDockComponent.test.ts @@ -0,0 +1,137 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { PickupDockComponent } from './PickupDockComponent.js'; + +const componentHash = ComponentHash.PickupDock; +const componentName = 'PickupDock'; +const componentVersion = 2; +const componentProps = { + dockedTypeHash: 1337, + quantity: -420, + childIndex: -69 +}; + +describe('new PickupDockComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the PickupDockComponent class', () => { + const component = new PickupDockComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(PickupDockComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the PickupDockComponent class', () => { + const component = new PickupDockComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(PickupDockComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.dockedTypeHash).toStrictEqual(componentProps.dockedTypeHash); + expect(component.quantity).toStrictEqual(componentProps.quantity); + expect(component.childIndex).toStrictEqual(componentProps.childIndex); + }); + }); +}); + +describe('PickupDockComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('Grass_Clump', { + components: { + PickupDock: new PickupDockComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // PickupDockComponent hash. + reader.readUnsignedInteger(); // PickupDockComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the PickupDockComponent class', () => { + const component = PickupDockComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(PickupDockComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.dockedTypeHash).toStrictEqual(componentProps.dockedTypeHash); + expect(component.quantity).toStrictEqual(componentProps.quantity); + expect(component.childIndex).toStrictEqual(componentProps.childIndex); + }); +}); + +describe('PickupDockComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new PickupDockComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = + '000000000000000000000101001110010111111111111111111111100101110001111111111111111111111110111011'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('PickupDockComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new PickupDockComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '1001101010000010011111001110001100000000000000000000000001100000000000000000000000000101001110010111111111111111111111100101110001111111111111111111111110111011'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // PickupDockComponent data length. + const dockedTypeHash = reader.readUnsignedInteger(); + const quantity = reader.readSignedInteger(); + const childIndex = reader.readSignedInteger(); + + expect(hash).toStrictEqual(componentHash); + expect(dockedTypeHash).toStrictEqual(componentProps.dockedTypeHash); + expect(quantity).toStrictEqual(componentProps.quantity); + expect(childIndex).toStrictEqual(componentProps.childIndex); + }); +}); diff --git a/src/components/PickupDockComponent.ts b/src/components/PickupDockComponent.ts new file mode 100644 index 0000000..6095381 --- /dev/null +++ b/src/components/PickupDockComponent.ts @@ -0,0 +1,152 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type PickupDockComponentPropsV2 = { + dockedTypeHash?: number | undefined; + quantity?: number | undefined; + childIndex?: number | undefined; +}; + +export type PickupDockComponentProps = PickupDockComponentPropsV2; + +/** + * @see [Class: `BasicDecayComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/BasicDecayComponent.md) + * @since v3.0.0 + * @version 2 + * + * @example + * import { PickupDockComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new PickupDockComponent({ version: componentVersion }); + */ +export class PickupDockComponent extends Component { + /** + * @since v2 + * + * @example + * import { PickupDockComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new PickupDockComponent({ version: componentVersion }); + * + * const dockedTypeHash = component.dockedTypeHash; + * // `dockedTypeHash` is `0` + */ + dockedTypeHash: number; + + /** + * @since v2 + * + * @example + * import { PickupDockComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new PickupDockComponent({ version: componentVersion }); + * + * const quantity = component.quantity; + * // `quantity` is `1` + */ + quantity: number; + + /** + * @since v2 + * + * @example + * import { PickupDockComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new PickupDockComponent({ version: componentVersion }); + * + * const childIndex = component.childIndex; + * // `childIndex` is `0` + */ + childIndex: number; + + /** + * @see [Class: `BasicDecayComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/BasicDecayComponent.md) + * @since v3.0.0 + * @version 2 + * + * @example + * import { PickupDockComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new PickupDockComponent({ version: componentVersion }); + */ + constructor({ version, dockedTypeHash, quantity, childIndex }: ComponentProps & PickupDockComponentProps) { + const hash = ComponentHash.PickupDock; + const name = 'PickupDock'; + + super({ hash, name, version }); + + this.dockedTypeHash = dockedTypeHash ?? 0; + this.quantity = quantity ?? 1; + this.childIndex = childIndex ?? 0; + } + + static override fromBinary(reader: BinaryReader, version: number): PickupDockComponent { + const props: ComponentProps & PickupDockComponentProps = { version }; + + /** + * @property {number} dockedTypeHash + * @since v2 + */ + if (props.version >= 2) { + props.dockedTypeHash = reader.readUnsignedInteger(); + } + + /** + * @property {number} quantity + * @since v2 + */ + if (props.version >= 2) { + props.quantity = reader.readSignedInteger(); + } + + /** + * @property {number} childIndex + * @since v2 + */ + if (props.version >= 2) { + props.childIndex = reader.readSignedInteger(); + } + + return new PickupDockComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {number} dockedTypeHash + * @since v2 + */ + if (version >= 2) { + writer.writeUnsignedInteger(this.dockedTypeHash); + } + + /** + * @property {number} quantity + * @since v2 + */ + if (version >= 2) { + writer.writeSignedInteger(this.quantity); + } + + /** + * @property {number} childIndex + * @since v2 + */ + if (version >= 2) { + writer.writeSignedInteger(this.childIndex); + } + + return writer.flush(); + } +} diff --git a/src/components/PopulationSpawnAreaComponent.test.ts b/src/components/PopulationSpawnAreaComponent.test.ts new file mode 100644 index 0000000..382e52a --- /dev/null +++ b/src/components/PopulationSpawnAreaComponent.test.ts @@ -0,0 +1,244 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { + PopulationSpawnAreaComponent, + type PopulationSpawnAreaComponentProps +} from './PopulationSpawnAreaComponent.js'; + +const componentHash = ComponentHash.PopulationSpawnArea; +const componentName = 'PopulationSpawnArea'; +const componentVersion = 2; + +const child = { + index: -420, + pointIndex: -69 +}; + +const componentProps = { + definition: 1337, + isPopulationStarted: true, + children: [child], + maxPopulation: 420, + currentPopulation: 69, + checkPopulationTime: 133742069, + numberOfSpawnPoints: 42, + startingPopulation: 8, + isOneOff: false +}; + +describe('new PopulationSpawnAreaComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the PopulationSpawnAreaComponent class', () => { + const component = new PopulationSpawnAreaComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(PopulationSpawnAreaComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the PopulationSpawnAreaComponent class', () => { + const component = new PopulationSpawnAreaComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(PopulationSpawnAreaComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.definition).toStrictEqual(componentProps.definition); + expect(component.isPopulationStarted).toStrictEqual(componentProps.isPopulationStarted); + expect(component.children).toStrictEqual(componentProps.children); + expect(component.maxPopulation).toStrictEqual(componentProps.maxPopulation); + expect(component.currentPopulation).toStrictEqual(componentProps.currentPopulation); + expect(component.checkPopulationTime).toStrictEqual(componentProps.checkPopulationTime); + expect(component.numberOfSpawnPoints).toStrictEqual(componentProps.numberOfSpawnPoints); + expect(component.startingPopulation).toStrictEqual(componentProps.startingPopulation); + expect(component.isOneOff).toStrictEqual(componentProps.isOneOff); + }); + }); +}); + +describe('PopulationSpawnAreaComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + describe('when all component props are given', () => { + const prefab = new Prefab('Grass_Clump', { + components: { + PopulationSpawnArea: new PopulationSpawnAreaComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // PopulationSpawnAreaComponent hash. + reader.readUnsignedInteger(); // PopulationSpawnAreaComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the PopulationSpawnAreaComponent class', () => { + const component = PopulationSpawnAreaComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(PopulationSpawnAreaComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.definition).toStrictEqual(componentProps.definition); + expect(component.isPopulationStarted).toStrictEqual(componentProps.isPopulationStarted); + expect(component.children).toStrictEqual(componentProps.children); + expect(component.maxPopulation).toStrictEqual(componentProps.maxPopulation); + expect(component.currentPopulation).toStrictEqual(componentProps.currentPopulation); + expect(component.checkPopulationTime).toStrictEqual(componentProps.checkPopulationTime); + expect(component.numberOfSpawnPoints).toStrictEqual(componentProps.numberOfSpawnPoints); + expect(component.startingPopulation).toStrictEqual(componentProps.startingPopulation); + expect(component.isOneOff).toStrictEqual(componentProps.isOneOff); + }); + }); + + describe('when child is null', () => { + beforeEach(() => { + (componentProps as PopulationSpawnAreaComponentProps).children = [null]; + + const prefab = new Prefab('Grass_Clump', { + components: { + PopulationSpawnArea: new PopulationSpawnAreaComponent({ version: componentVersion, ...componentProps }) + } + }); + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // PopulationSpawnAreaComponent hash. + reader.readUnsignedInteger(); // PopulationSpawnAreaComponent data length. + + fastForwardedReader = reader; + }); + + afterEach(() => { + componentProps.children = [child]; + }); + + it('returns an instance of the PopulationSpawnAreaComponent class', () => { + const component = PopulationSpawnAreaComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(PopulationSpawnAreaComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.definition).toStrictEqual(componentProps.definition); + expect(component.isPopulationStarted).toStrictEqual(componentProps.isPopulationStarted); + expect(component.children).toStrictEqual(componentProps.children); + expect(component.maxPopulation).toStrictEqual(componentProps.maxPopulation); + expect(component.currentPopulation).toStrictEqual(componentProps.currentPopulation); + expect(component.checkPopulationTime).toStrictEqual(componentProps.checkPopulationTime); + expect(component.numberOfSpawnPoints).toStrictEqual(componentProps.numberOfSpawnPoints); + expect(component.startingPopulation).toStrictEqual(componentProps.startingPopulation); + expect(component.isOneOff).toStrictEqual(componentProps.isOneOff); + }); + }); +}); + +describe('PopulationSpawnAreaComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new PopulationSpawnAreaComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = + '00000000000000000000010100111001100000000000000000000000000000001001111111111111111111111001011100011111111111111111111111101110111000000000000000000000011010010010000000000000000000000001000101000001111111100010111101111101010000000000000000000000000000000010000000000000000000000000101010100000000000000000000000000010000'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('PopulationSpawnAreaComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new PopulationSpawnAreaComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '101101110000010000000011100111110000000000000000000000010100001100000000000000000000010100111001100000000000000000000000000000001001111111111111111111111001011100011111111111111111111111101110111000000000000000000000011010010010000000000000000000000001000101000001111111100010111101111101010000000000000000000000000000000010000000000000000000000000101010100000000000000000000000000010000'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // PopulationSpawnAreaComponent data length. + const definition = reader.readUnsignedInteger(); + const isPopulationStarted = reader.readBoolean(); + reader.readUnsignedInteger(); // Children array length. + const isNullBit = reader.readBoolean(); + const index = reader.readSignedInteger(); + const pointIndex = reader.readSignedInteger(); + const maxPopulation = reader.readSignedInteger(); + const currentPopulation = reader.readSignedInteger(); + const checkPopulationTime = reader.readUnsignedLong(); + const numberOfSpawnPoints = reader.readSignedInteger(); + const startingPopulation = reader.readSignedInteger(); + const isOneOff = reader.readBoolean(); + + expect(hash).toStrictEqual(componentHash); + expect(definition).toStrictEqual(componentProps.definition); + expect(isPopulationStarted).toStrictEqual(componentProps.isPopulationStarted); + expect(isNullBit).toStrictEqual(false); + expect(index).toStrictEqual(componentProps.children[0]?.index); + expect(pointIndex).toStrictEqual(componentProps.children[0]?.pointIndex); + expect(maxPopulation).toStrictEqual(componentProps.maxPopulation); + expect(currentPopulation).toStrictEqual(componentProps.currentPopulation); + expect(checkPopulationTime).toStrictEqual(componentProps.checkPopulationTime); + expect(numberOfSpawnPoints).toStrictEqual(componentProps.numberOfSpawnPoints); + expect(startingPopulation).toStrictEqual(componentProps.startingPopulation); + expect(isOneOff).toStrictEqual(componentProps.isOneOff); + }); +}); diff --git a/src/components/PopulationSpawnAreaComponent.ts b/src/components/PopulationSpawnAreaComponent.ts new file mode 100644 index 0000000..539d31f --- /dev/null +++ b/src/components/PopulationSpawnAreaComponent.ts @@ -0,0 +1,425 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; +import { PopulationDefinitionHash } from '../types/PopulationDefinitionHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type PopulationSaveDataChild = null | { + index: number; + pointIndex: number; +}; + +type PopulationSpawnAreaComponentPropsV2 = { + definition?: number | undefined; + isPopulationStarted?: boolean | undefined; + children?: PopulationSaveDataChild[] | undefined; + maxPopulation?: number | undefined; + currentPopulation?: number | undefined; + checkPopulationTime?: number | undefined; + numberOfSpawnPoints?: number | undefined; + startingPopulation?: number | undefined; + isOneOff?: boolean | undefined; +}; + +export type PopulationSpawnAreaComponentProps = PopulationSpawnAreaComponentPropsV2; + +/** + * @see [Class: `PopulationSpawnAreaComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/PopulationSpawnAreaComponent.md) + * @since v3.0.0 + * @version 2 + * + * @example + * import { PopulationSpawnAreaComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new PopulationSpawnAreaComponent({ version: componentVersion }); + */ +export class PopulationSpawnAreaComponent extends Component { + /** + * The hash of the population to spawn in the `SpawnArea` component that is attached to the same prefab this component is attached to. + * + * @since v2 + * + * @example + * import { PopulationSpawnAreaComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new PopulationSpawnAreaComponent({ version: componentVersion }); + * + * const definition = component.definition; + * // `definition` is `30040` + */ + definition: number; + + /** + * @since v2 + * + * @example + * import { PopulationSpawnAreaComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new PopulationSpawnAreaComponent({ version: componentVersion }); + * + * const isPopulationStarted = component.isPopulationStarted; + * // `isPopulationStarted` is `true` + */ + isPopulationStarted: boolean; + + /** + * @since v2 + * + * @example + * import { PopulationSpawnAreaComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new PopulationSpawnAreaComponent({ version: componentVersion }); + * + * const children = component.children; + * // `children` is `[]` + */ + children: PopulationSaveDataChild[]; + + /** + * The maximum amount of spawned prefabs in this population. + * + * @since v2 + * + * @example + * import { PopulationSpawnAreaComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new PopulationSpawnAreaComponent({ version: componentVersion }); + * + * const maxPopulation = component.maxPopulation; + * // `maxPopulation` is `20` + */ + maxPopulation: number; + + /** + * The current amount of spawned prefabs in this population. + * + * @since v2 + * + * @example + * import { PopulationSpawnAreaComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new PopulationSpawnAreaComponent({ version: componentVersion }); + * + * const currentPopulation = component.currentPopulation; + * // `currentPopulation` is `5` + */ + currentPopulation: number; + + /** + * @since v2 + * + * @example + * import { PopulationSpawnAreaComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new PopulationSpawnAreaComponent({ version: componentVersion }); + * + * const checkPopulationTime = component.checkPopulationTime; + * // `checkPopulationTime` is `852974979330` + */ + checkPopulationTime: number; + + /** + * The amount of spawn locations inside the `SpawnArea` component that is attached to the same prefab this component is attached to. + * + * @since v2 + * + * @example + * import { PopulationSpawnAreaComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new PopulationSpawnAreaComponent({ version: componentVersion }); + * + * const numberOfSpawnPoints = component.numberOfSpawnPoints; + * // `numberOfSpawnPoints` is `40` + */ + numberOfSpawnPoints: number; + + /** + * The amount of spawned prefabs that this population begins with. + * + * @since v2 + * + * @example + * import { PopulationSpawnAreaComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new PopulationSpawnAreaComponent({ version: componentVersion }); + * + * const startingPopulation = component.startingPopulation; + * // `startingPopulation` is `5` + */ + startingPopulation: number; + + /** + * Whether any removed prefabs from this population shouldn't be replaced after the server's respawn timer has elapsed. + * + * @since v2 + * + * @example + * import { PopulationSpawnAreaComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new PopulationSpawnAreaComponent({ version: componentVersion }); + * + * const isOneOff = component.isOneOff; + * // `isOneOff` is `false` + */ + isOneOff: boolean; + + /** + * @see [Class: `PopulationSpawnAreaComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/PopulationSpawnAreaComponent.md) + * @since v3.0.0 + * @version 2 + * + * @example + * import { PopulationSpawnAreaComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new PopulationSpawnAreaComponent({ version: componentVersion }); + */ + constructor({ + version, + definition, + isPopulationStarted, + children, + maxPopulation, + currentPopulation, + checkPopulationTime, + numberOfSpawnPoints, + startingPopulation, + isOneOff + }: ComponentProps & PopulationSpawnAreaComponentProps) { + const hash = ComponentHash.PopulationSpawnArea; + const name = 'PopulationSpawnArea'; + + super({ hash, name, version }); + + this.definition = definition ?? PopulationDefinitionHash.StickPopulation; + this.isPopulationStarted = isPopulationStarted ?? true; + this.children = children ?? []; + this.maxPopulation = maxPopulation ?? 20; + this.currentPopulation = currentPopulation ?? 5; + this.checkPopulationTime = checkPopulationTime ?? 852974979330; + this.numberOfSpawnPoints = numberOfSpawnPoints ?? 40; + this.startingPopulation = startingPopulation ?? 5; + this.isOneOff = isOneOff ?? false; + } + + static override fromBinary(reader: BinaryReader, version: number): PopulationSpawnAreaComponent { + const props: ComponentProps & PopulationSpawnAreaComponentProps = { version }; + + /** + * @property {number} definition + * @since v2 + */ + if (props.version >= 2) { + props.definition = reader.readUnsignedInteger(); + } + + /** + * @property {boolean} isPopulationStarted + * @since v2 + */ + if (props.version >= 2) { + props.isPopulationStarted = reader.readBoolean(); + } + + /** + * @property {PopulationSaveDataChild[]} children + * @since v2 + */ + if (props.version >= 2) { + const childrenLength = reader.readUnsignedInteger(); + props.children = []; + + for (let index = 0; index < childrenLength; ++index) { + /** + * @property {boolean} isNull + * @since v2 + */ + const isNull = reader.readBoolean(); + + if (isNull) { + props.children.push(null); + continue; + } + + props.children.push({ + /** + * @property {number} index + * @since v2 + */ + index: reader.readSignedInteger(), + + /** + * @property {number} pointIndex + * @since v2 + */ + pointIndex: reader.readSignedInteger() + }); + } + } + + /** + * @property {number} maxPopulation + * @since v2 + */ + if (props.version >= 2) { + props.maxPopulation = reader.readSignedInteger(); + } + + /** + * @property {number} currentPopulation + * @since v2 + */ + if (props.version >= 2) { + props.currentPopulation = reader.readSignedInteger(); + } + + /** + * @property {number} checkPopulationTime + * @since v2 + */ + if (props.version >= 2) { + props.checkPopulationTime = reader.readUnsignedLong(); + } + + /** + * @property {number} numberOfSpawnPoints + * @since v2 + */ + if (props.version >= 2) { + props.numberOfSpawnPoints = reader.readSignedInteger(); + } + + /** + * @property {number} startingPopulation + * @since v2 + */ + if (props.version >= 2) { + props.startingPopulation = reader.readSignedInteger(); + } + + /** + * @property {boolean} isOneOff + * @since v2 + */ + if (props.version >= 2) { + props.isOneOff = reader.readBoolean(); + } + + return new PopulationSpawnAreaComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {number} definition + * @since v2 + */ + if (version >= 2) { + writer.writeUnsignedInteger(this.definition); + } + + /** + * @property {boolean} isPopulationStarted + * @since v2 + */ + if (version >= 2) { + writer.writeBoolean(this.isPopulationStarted); + } + + /** + * @property {PopulationSaveDataChild[]} children + * @since v2 + */ + if (version >= 2) { + writer.writeUnsignedInteger(this.children.length); + + for (const populationSaveDataChild of this.children) { + const isNull = populationSaveDataChild === null; + + /** + * @property {boolean} isNull + * @since v2 + */ + writer.writeBoolean(isNull); + + if (!isNull) { + /** + * @property {number} index + * @since v2 + */ + writer.writeSignedInteger(populationSaveDataChild.index); + + /** + * @property {number} pointIndex + * @since v2 + */ + writer.writeSignedInteger(populationSaveDataChild.pointIndex); + } + } + } + + /** + * @property {number} maxPopulation + * @since v2 + */ + if (version >= 2) { + writer.writeSignedInteger(this.maxPopulation); + } + + /** + * @property {number} currentPopulation + * @since v2 + */ + if (version >= 2) { + writer.writeSignedInteger(this.currentPopulation); + } + + /** + * @property {number} checkPopulationTime + * @since v2 + */ + if (version >= 2) { + writer.writeUnsignedLong(this.checkPopulationTime); + } + + /** + * @property {number} numberOfSpawnPoints + * @since v2 + */ + if (version >= 2) { + writer.writeSignedInteger(this.numberOfSpawnPoints); + } + + /** + * @property {number} startingPopulation + * @since v2 + */ + if (version >= 2) { + writer.writeSignedInteger(this.startingPopulation); + } + + /** + * @property {boolean} isOneOff + * @since v2 + */ + if (version >= 2) { + writer.writeBoolean(this.isOneOff); + } + + return writer.flush(); + } +} diff --git a/src/components/SentGiftComponent.test.ts b/src/components/SentGiftComponent.test.ts new file mode 100644 index 0000000..a7568e6 --- /dev/null +++ b/src/components/SentGiftComponent.test.ts @@ -0,0 +1,286 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { SentGiftComponent, type SentGiftComponentProps } from './SentGiftComponent.js'; + +const componentHash = ComponentHash.SentGift; +const componentName = 'SentGift'; +const componentVersion = 1; + +const gift = { + data: [1337], + messageSizeInBytes: 420, + hash: 69, + chunkVersioning: [42] +}; + +const senderTag = { + from: 1337, + to: 420 +}; + +const componentProps = { + receiverName: 'Joel', + senderName: 'Ethyn Wyrmbane', + gifts: [gift], + senderTag: senderTag +}; + +describe('new SentGiftComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the SentGiftComponent class', () => { + const component = new SentGiftComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(SentGiftComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the SentGiftComponent class', () => { + const component = new SentGiftComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(SentGiftComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.receiverName).toStrictEqual(componentProps.receiverName); + expect(component.senderName).toStrictEqual(componentProps.senderName); + expect(component.gifts).toStrictEqual(componentProps.gifts); + expect(component.senderTag).toStrictEqual(componentProps.senderTag); + }); + }); +}); + +describe('SentGiftComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + describe('when all component props are given', () => { + const prefab = new Prefab('Grass_Clump', { + components: { + SentGift: new SentGiftComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // SentGiftComponent hash. + reader.readUnsignedInteger(); // SentGiftComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the SentGiftComponent class', () => { + const component = SentGiftComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(SentGiftComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.receiverName).toStrictEqual(componentProps.receiverName); + expect(component.senderName).toStrictEqual(componentProps.senderName); + expect(component.gifts).toStrictEqual(componentProps.gifts); + expect(component.senderTag).toStrictEqual(componentProps.senderTag); + }); + }); + + describe('when gift is null', () => { + beforeEach(() => { + (componentProps as SentGiftComponentProps).gifts = [null]; + + const prefab = new Prefab('Grass_Clump', { + components: { + SentGift: new SentGiftComponent({ version: componentVersion, ...componentProps }) + } + }); + + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // SentGiftComponent hash. + reader.readUnsignedInteger(); // SentGiftComponent data length. + + fastForwardedReader = reader; + }); + + afterEach(() => { + componentProps.gifts = [gift]; + }); + + it('returns an instance of the SentGiftComponent class', () => { + const component = SentGiftComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(SentGiftComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.receiverName).toStrictEqual(componentProps.receiverName); + expect(component.senderName).toStrictEqual(componentProps.senderName); + expect(component.gifts).toStrictEqual(componentProps.gifts); + expect(component.senderTag).toStrictEqual(componentProps.senderTag); + }); + }); + + describe('when senderTag is null', () => { + beforeEach(() => { + (componentProps as SentGiftComponentProps).senderTag = null; + + const prefab = new Prefab('Grass_Clump', { + components: { + SentGift: new SentGiftComponent({ version: componentVersion, ...componentProps }) + } + }); + + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // SentGiftComponent hash. + reader.readUnsignedInteger(); // SentGiftComponent data length. + + fastForwardedReader = reader; + }); + + afterEach(() => { + componentProps.senderTag = senderTag; + }); + + it('returns an instance of the SentGiftComponent class', () => { + const component = SentGiftComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(SentGiftComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.receiverName).toStrictEqual(componentProps.receiverName); + expect(component.senderName).toStrictEqual(componentProps.senderName); + expect(component.gifts).toStrictEqual(componentProps.gifts); + expect(component.senderTag).toStrictEqual(componentProps.senderTag); + }); + }); +}); + +describe('SentGiftComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new SentGiftComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = + '0000000000000100010010100110111101100101011011000000000000001110010001010111010001101000011110010111100101010111001000000110111001100001011000100110110101110010011011100110010100000000000000000000000000000001000000000000000000000000000000001000000000000000000000101001110010000000000000000000000011010010000000000000000000000000001000101000000000000000000000000000000010000000000000000000000000010101001000000000000000000001010011100110000000000000000000000110100100'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('SentGiftComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new SentGiftComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '00100111011011011010011100100110000000000000000000000001110100100000000000000100010010100110111101100101011011000000000000001110010001010111010001101000011110010111100101010111001000000110111001100001011000100110110101110010011011100110010100000000000000000000000000000001000000000000000000000000000000001000000000000000000000101001110010000000000000000000000011010010000000000000000000000000001000101000000000000000000000000000000010000000000000000000000000010101001000000000000000000001010011100110000000000000000000000110100100'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // SentGiftComponent data length. + const receiverName = reader.readString(); + const senderName = reader.readString(); + reader.readUnsignedInteger(); // Gifts array length. + const isDataNullBit = reader.readBoolean(); + reader.readUnsignedInteger(); // Gift data array length. + const dataUInt = reader.readUnsignedInteger(); + const dataBytes = reader.readUnsignedInteger(); + const dataHash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // Gift data chunk versioning array length. + const chunkVersioning = reader.readUnsignedInteger(); + const isSenderTagNullBit = reader.readBoolean(); + const tagFrom = reader.readSignedInteger(); + const tagTo = reader.readSignedInteger(); + + expect(hash).toStrictEqual(componentHash); + expect(receiverName).toStrictEqual(componentProps.receiverName); + expect(senderName).toStrictEqual(componentProps.senderName); + expect(isDataNullBit).toStrictEqual(false); + expect(dataUInt).toStrictEqual(componentProps.gifts[0]?.data[0]); + expect(dataBytes).toStrictEqual(componentProps.gifts[0]?.messageSizeInBytes); + expect(dataHash).toStrictEqual(componentProps.gifts[0]?.hash); + expect(chunkVersioning).toStrictEqual(componentProps.gifts[0]?.chunkVersioning[0]); + expect(isSenderTagNullBit).toStrictEqual(false); + expect(tagFrom).toStrictEqual(componentProps.senderTag.from); + expect(tagTo).toStrictEqual(componentProps.senderTag.to); + }); +}); diff --git a/src/components/SentGiftComponent.ts b/src/components/SentGiftComponent.ts new file mode 100644 index 0000000..89c8873 --- /dev/null +++ b/src/components/SentGiftComponent.ts @@ -0,0 +1,358 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type Gift = null | { + data: number[]; + messageSizeInBytes: number; + hash: number; + chunkVersioning: number[]; +}; + +type SentGiftTag = null | { + from: number; + to: number; +}; + +type SentGiftComponentPropsV1 = { + receiverName?: string | undefined; + senderName?: string | undefined; + gifts?: Gift[] | undefined; + senderTag?: SentGiftTag | undefined; +}; + +export type SentGiftComponentProps = SentGiftComponentPropsV1; + +/** + * @see [Class: `SentGiftComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/SentGiftComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { SentGiftComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new SentGiftComponent({ version: componentVersion }); + */ +export class SentGiftComponent extends Component { + /** + * Name of the player intended as the receiver of the prefab this component is attached to. + * + * @since v1 + * + * @example + * import { SentGiftComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new SentGiftComponent({ version: componentVersion }); + * + * const receiverName = component.receiverName; + * // `receiverName` is `''` + */ + receiverName: string; + + /** + * Name of the player intended as the sender of the prefab this component is attached to. This name will be displayed as a label on a gift box prefab. + * + * @since v1 + * + * @example + * import { SentGiftComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new SentGiftComponent({ version: componentVersion }); + * + * const senderName = component.senderName; + * // `senderName` is `''` + */ + senderName: string; + + /** + * Array of gifts, which are prefab save strings. + * + * @since v1 + * + * @example + * import { SentGiftComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new SentGiftComponent({ version: componentVersion }); + * + * const gifts = component.gifts; + * // `gifts` is `[]` + */ + gifts: Gift[]; + + /** + * @since v1 + * + * @example + * import { SentGiftComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new SentGiftComponent({ version: componentVersion }); + * + * const senderTag = component.senderTag; + * // `senderTag` is `null` + */ + senderTag: SentGiftTag; + + /** + * @see [Class: `SentGiftComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/SentGiftComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { SentGiftComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new SentGiftComponent({ version: componentVersion }); + */ + constructor({ version, receiverName, senderName, gifts, senderTag }: ComponentProps & SentGiftComponentProps) { + const hash = ComponentHash.SentGift; + const name = 'SentGift'; + + super({ hash, name, version }); + + this.receiverName = receiverName ?? ''; + this.senderName = senderName ?? ''; + this.gifts = gifts ?? []; + this.senderTag = senderTag ?? null; + } + + static override fromBinary(reader: BinaryReader, version: number): SentGiftComponent { + const props: ComponentProps & SentGiftComponentProps = { version }; + + /** + * @property {string} receiverName + * @since v1 + */ + if (props.version >= 1) { + props.receiverName = reader.readString(); + } + + /** + * @property {string} senderName + * @since v1 + */ + if (props.version >= 1) { + props.senderName = reader.readString(); + } + + /** + * @property {Gift[]} gifts + * @since v1 + */ + if (props.version >= 1) { + const giftsLength = reader.readUnsignedInteger(); + props.gifts = []; + + for (let index = 0; index < giftsLength; ++index) { + /** + * @property {boolean} isNull + * @since v1 + */ + const isNull = reader.readBoolean(); + + if (isNull) { + props.gifts.push(null); + continue; + } + + /** + * @property {number[]} data + * @since v1 + */ + const dataLength = reader.readUnsignedInteger(); + const data: number[] = []; + + for (let dataIndex = 0; dataIndex < dataLength; ++dataIndex) { + /** + * @property {number} data + * @since v1 + */ + data.push(reader.readUnsignedInteger()); + } + + /** + * @property {number} messageSizeInBytes + * @since v1 + */ + + const messageSizeInBytes = reader.readUnsignedInteger(); + + /** + * @property {number} hash + * @since v1 + */ + const hash = reader.readUnsignedInteger(); + + /** + * @property {number[]} chunkVersioning + * @since v1 + */ + const chunkVersioningLength = reader.readUnsignedInteger(); + const chunkVersioning: number[] = []; + + for (let chunkVersioningIndex = 0; chunkVersioningIndex < chunkVersioningLength; ++chunkVersioningIndex) { + /** + * @property {number} chunkVersioning + * @since v1 + */ + chunkVersioning.push(reader.readUnsignedInteger()); + } + + props.gifts.push({ + data, + messageSizeInBytes, + hash, + chunkVersioning + }); + } + } + + /** + * @property {SentGiftTag} senderTag + * @since v1 + */ + if (props.version >= 1) { + /** + * @property {boolean} isNull + * @since v1 + */ + const isNull = reader.readBoolean(); + + props.senderTag = isNull + ? null + : { + /** + * @property {number} from + * @since v1 + */ + from: reader.readSignedInteger(), + + /** + * @property {number} to + * @since v1 + */ + to: reader.readSignedInteger() + }; + } + + return new SentGiftComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {string} receiverName + * @since v1 + */ + if (version >= 1) { + writer.writeString(this.receiverName); + } + + /** + * @property {string} senderName + * @since v1 + */ + if (version >= 1) { + writer.writeString(this.senderName); + } + + /** + * @property {Gift[]} gifts + * @since v1 + */ + if (version >= 1) { + writer.writeUnsignedInteger(this.gifts.length); + + for (const gift of this.gifts) { + const isNull = gift === null; + + /** + * @property {boolean} isNull + * @since v1 + */ + writer.writeBoolean(isNull); + + if (!isNull) { + /** + * @property {number[]} data + * @since v1 + */ + writer.writeUnsignedInteger(gift.data.length); + + for (const data of gift.data) { + /** + * @property {number} data + * @since v1 + */ + writer.writeUnsignedInteger(data); + } + + /** + * @property {number} messageSizeInBytes + * @since v1 + */ + writer.writeUnsignedInteger(gift.messageSizeInBytes); + + /** + * @property {number} hash + * @since v1 + */ + writer.writeUnsignedInteger(gift.hash); + + /** + * @property {number[]} chunkVersioning + * @since v1 + */ + writer.writeUnsignedInteger(gift.chunkVersioning.length); + + for (const chunk of gift.chunkVersioning) { + /** + * @property {number} chunkVersioning + * @since v1 + */ + writer.writeUnsignedInteger(chunk); + } + } + } + } + + /** + * @property {SentGiftTag} senderTag + * @since v1 + */ + if (version >= 1) { + const isNull = this.senderTag === null; + + /** + * @property {boolean} isNull + * @since v1 + */ + writer.writeBoolean(isNull); + + if (this.senderTag !== null) { + /** + * @property {number} from + * @since v1 + */ + writer.writeSignedInteger(this.senderTag.from); + + /** + * @property {number} to + * @since v1 + */ + writer.writeSignedInteger(this.senderTag.to); + } + } + + return writer.flush(); + } +} diff --git a/src/components/SlidingDoorComponent.test.ts b/src/components/SlidingDoorComponent.test.ts new file mode 100644 index 0000000..971b166 --- /dev/null +++ b/src/components/SlidingDoorComponent.test.ts @@ -0,0 +1,125 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { SlidingDoorComponent } from './SlidingDoorComponent.js'; + +const componentHash = ComponentHash.SlidingDoor; +const componentName = 'SlidingDoor'; +const componentVersion = 1; +const componentProps = { + isOpen: true +}; + +describe('new SlidingDoorComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the SlidingDoorComponent class', () => { + const component = new SlidingDoorComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(SlidingDoorComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the SlidingDoorComponent class', () => { + const component = new SlidingDoorComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(SlidingDoorComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.isOpen).toStrictEqual(componentProps.isOpen); + }); + }); +}); + +describe('SlidingDoorComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('Grass_Clump', { + components: { + SlidingDoor: new SlidingDoorComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // SlidingDoorComponent hash. + reader.readUnsignedInteger(); // SlidingDoorComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the SlidingDoorComponent class', () => { + const component = SlidingDoorComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(SlidingDoorComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.isOpen).toStrictEqual(componentProps.isOpen); + }); +}); + +describe('SlidingDoorComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new SlidingDoorComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = '1'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('SlidingDoorComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new SlidingDoorComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = '11010101100101110100110110010100000000000000000000000000000000011'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // SlidingDoorComponent data length. + const isOpen = reader.readBoolean(); + + expect(hash).toStrictEqual(componentHash); + expect(isOpen).toStrictEqual(componentProps.isOpen); + }); +}); diff --git a/src/components/SlidingDoorComponent.ts b/src/components/SlidingDoorComponent.ts new file mode 100644 index 0000000..c1dba09 --- /dev/null +++ b/src/components/SlidingDoorComponent.ts @@ -0,0 +1,90 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type SlidingDoorComponentPropsV1 = { + isOpen?: boolean | undefined; +}; + +export type SlidingDoorComponentProps = SlidingDoorComponentPropsV1; + +/** + * @see [Class: `SlidingDoorComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/SlidingDoorComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { SlidingDoorComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new SlidingDoorComponent({ version: componentVersion }); + */ +export class SlidingDoorComponent extends Component { + /** + * Reveals the open state of this component's prefab. + * + * @since v1 + * + * @example + * import { SlidingDoorComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new SlidingDoorComponent({ version: componentVersion }); + * + * const isOpen = component.isOpen; + * // `isOpen` is `false` + */ + isOpen: boolean; + + /** + * @see [Class: `SlidingDoorComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/SlidingDoorComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { SlidingDoorComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new SlidingDoorComponent({ version: componentVersion }); + */ + constructor({ version, isOpen }: ComponentProps & SlidingDoorComponentProps) { + const hash = ComponentHash.SlidingDoor; + const name = 'SlidingDoor'; + + super({ hash, name, version }); + + this.isOpen = isOpen ?? false; + } + + static override fromBinary(reader: BinaryReader, version: number): SlidingDoorComponent { + const props: ComponentProps & SlidingDoorComponentProps = { version }; + + /** + * @property {boolean} isOpen + * @since v1 + */ + if (props.version >= 1) { + props.isOpen = reader.readBoolean(); + } + + return new SlidingDoorComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {boolean} isOpen + * @since v1 + */ + if (version >= 1) { + writer.writeBoolean(this.isOpen); + } + + return writer.flush(); + } +} diff --git a/src/components/SpawnAreaComponent.test.ts b/src/components/SpawnAreaComponent.test.ts new file mode 100644 index 0000000..f3a5354 --- /dev/null +++ b/src/components/SpawnAreaComponent.test.ts @@ -0,0 +1,147 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { SpawnAreaComponent } from './SpawnAreaComponent.js'; + +const componentHash = ComponentHash.SpawnArea; +const componentName = 'SpawnArea'; +const componentVersion = 1; +const componentProps = { + size: 13.37, + groundLayers: 420, + avoidLayers: 69, + isAligningNormal: true, + maxAcceptableAngleDot: 0.69 +}; + +describe('new SpawnAreaComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the SpawnAreaComponent class', () => { + const component = new SpawnAreaComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(SpawnAreaComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the SpawnAreaComponent class', () => { + const component = new SpawnAreaComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(SpawnAreaComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.size).toBeCloseTo(componentProps.size, 2); + expect(component.groundLayers).toStrictEqual(componentProps.groundLayers); + expect(component.avoidLayers).toStrictEqual(componentProps.avoidLayers); + expect(component.isAligningNormal).toStrictEqual(componentProps.isAligningNormal); + expect(component.maxAcceptableAngleDot).toBeCloseTo(componentProps.maxAcceptableAngleDot, 2); + }); + }); +}); + +describe('SpawnAreaComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('Grass_Clump', { + components: { + SpawnArea: new SpawnAreaComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // SpawnAreaComponent hash. + reader.readUnsignedInteger(); // SpawnAreaComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the SpawnAreaComponent class', () => { + const component = SpawnAreaComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(SpawnAreaComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.size).toBeCloseTo(componentProps.size, 2); + expect(component.groundLayers).toStrictEqual(componentProps.groundLayers); + expect(component.avoidLayers).toStrictEqual(componentProps.avoidLayers); + expect(component.isAligningNormal).toStrictEqual(componentProps.isAligningNormal); + expect(component.maxAcceptableAngleDot).toBeCloseTo(componentProps.maxAcceptableAngleDot, 2); + }); +}); + +describe('SpawnAreaComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new SpawnAreaComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = + '010000010101010111101011100001011000000000000000000000011010010010000000000000000000000001000101100111111001100001010001111010111'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('SpawnAreaComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new SpawnAreaComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '1001110000000011110011111110100000000000000000000000000010000001010000010101010111101011100001011000000000000000000000011010010010000000000000000000000001000101100111111001100001010001111010111'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // SpawnAreaComponent data length. + const size = reader.readFloat(); + const groundLayers = reader.readSignedInteger(); + const avoidLayers = reader.readSignedInteger(); + const isAligningNormal = reader.readBoolean(); + const maxAcceptableAngleDot = reader.readFloat(); + + expect(hash).toStrictEqual(componentHash); + expect(size).toBeCloseTo(componentProps.size, 2); + expect(groundLayers).toStrictEqual(componentProps.groundLayers); + expect(avoidLayers).toStrictEqual(componentProps.avoidLayers); + expect(isAligningNormal).toStrictEqual(componentProps.isAligningNormal); + expect(maxAcceptableAngleDot).toBeCloseTo(componentProps.maxAcceptableAngleDot, 2); + }); +}); diff --git a/src/components/SpawnAreaComponent.ts b/src/components/SpawnAreaComponent.ts new file mode 100644 index 0000000..13541e5 --- /dev/null +++ b/src/components/SpawnAreaComponent.ts @@ -0,0 +1,225 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type SpawnAreaComponentPropsV1 = { + size?: number | undefined; + groundLayers?: number | undefined; + avoidLayers?: number | undefined; + isAligningNormal?: boolean | undefined; + maxAcceptableAngleDot?: number | undefined; +}; + +export type SpawnAreaComponentProps = SpawnAreaComponentPropsV1; + +/** + * @see [Class: `SpawnAreaComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/SpawnAreaComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { SpawnAreaComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new SpawnAreaComponent({ version: componentVersion }); + */ +export class SpawnAreaComponent extends Component { + /** + * The size (in metres) of the spawn area of the prefab this component is attached to. + * + * @since v1 + * + * @example + * import { SpawnAreaComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new SpawnAreaComponent({ version: componentVersion }); + * + * const size = component.size; + * // `size` is `5` + */ + size: number; + + /** + * @since v1 + * + * @example + * import { SpawnAreaComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new SpawnAreaComponent({ version: componentVersion }); + * + * const groundLayers = component.groundLayers; + * // `groundLayers` is `1280` + */ + groundLayers: number; + + /** + * @since v1 + * + * @example + * import { SpawnAreaComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new SpawnAreaComponent({ version: componentVersion }); + * + * const avoidLayers = component.avoidLayers; + * // `avoidLayers` is `8721` + */ + avoidLayers: number; + + /** + * @since v1 + * + * @example + * import { SpawnAreaComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new SpawnAreaComponent({ version: componentVersion }); + * + * const isAligningNormal = component.isAligningNormal; + * // `isAligningNormal` is `false` + */ + isAligningNormal: boolean; + + /** + * @since v1 + * + * @example + * import { SpawnAreaComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new SpawnAreaComponent({ version: componentVersion }); + * + * const maxAcceptableAngleDot = component.maxAcceptableAngleDot; + * // `maxAcceptableAngleDot` is `-1` + */ + maxAcceptableAngleDot: number; + + /** + * @see [Class: `SpawnAreaComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/SpawnAreaComponent.md) + * @since v3.0.0 + * @version 1 + * + * @example + * import { SpawnAreaComponent } from 'att-string-transcoder'; + * + * const componentVersion = 1; + * const component = new SpawnAreaComponent({ version: componentVersion }); + */ + constructor({ + version, + size, + groundLayers, + avoidLayers, + isAligningNormal, + maxAcceptableAngleDot + }: ComponentProps & SpawnAreaComponentProps) { + const hash = ComponentHash.SpawnArea; + const name = 'SpawnArea'; + + super({ hash, name, version }); + + this.size = size ?? 5; + this.groundLayers = groundLayers ?? 1280; + this.avoidLayers = avoidLayers ?? 8721; + this.isAligningNormal = isAligningNormal ?? false; + this.maxAcceptableAngleDot = maxAcceptableAngleDot ?? -1; + } + + static override fromBinary(reader: BinaryReader, version: number): SpawnAreaComponent { + const props: ComponentProps & SpawnAreaComponentProps = { version }; + + /** + * @property {float} size + * @since v1 + */ + if (props.version >= 1) { + props.size = reader.readFloat(); + } + + /** + * @property {number} groundLayers + * @since v1 + */ + if (props.version >= 1) { + props.groundLayers = reader.readSignedInteger(); + } + + /** + * @property {number} avoidLayers + * @since v1 + */ + if (props.version >= 1) { + props.avoidLayers = reader.readSignedInteger(); + } + + /** + * @property {boolean} isAligningNormal + * @since v1 + */ + if (props.version >= 1) { + props.isAligningNormal = reader.readBoolean(); + } + + /** + * @property {float} maxAcceptableAngleDot + * @since v1 + */ + if (props.version >= 1) { + props.maxAcceptableAngleDot = reader.readFloat(); + } + + return new SpawnAreaComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {float} size + * @since v1 + */ + if (version >= 1) { + writer.writeFloat(this.size); + } + + /** + * @property {number} groundLayers + * @since v1 + */ + if (version >= 1) { + writer.writeSignedInteger(this.groundLayers); + } + + /** + * @property {number} avoidLayers + * @since v1 + */ + if (version >= 1) { + writer.writeSignedInteger(this.avoidLayers); + } + + /** + * @property {boolean} isAligningNormal + * @since v1 + */ + if (version >= 1) { + writer.writeBoolean(this.isAligningNormal); + } + + /** + * @property {float} maxAcceptableAngleDot + * @since v1 + */ + if (version >= 1) { + writer.writeFloat(this.maxAcceptableAngleDot); + } + + return writer.flush(); + } +} diff --git a/src/components/StatManagerComponent.test.ts b/src/components/StatManagerComponent.test.ts new file mode 100644 index 0000000..6ed37b8 --- /dev/null +++ b/src/components/StatManagerComponent.test.ts @@ -0,0 +1,443 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { StatManagerComponent, type StatManagerComponentProps } from './StatManagerComponent.js'; + +const componentHash = ComponentHash.StatManager; +const componentName = 'StatManager'; +const componentVersion = 2; + +const stat = { + hash: 1337, + baseFlat: 0.69 +}; + +const timedModifier = { + hash: 1337, + value: 0.69, + isMultiplier: true, + time: 133742069 +}; + +const indirectModifierSaveData = { + valueOverDurationHash: 1337, + baseValue: 0.69, + duration: 133742069, + tick: 420 +}; + +const indirectStatModifier = { + hash: 1337, + time: 133742069, + modifiers: [indirectModifierSaveData] +}; + +const componentProps = { + stats: [stat], + modifiers: [timedModifier], + indirectStatModifiers: [indirectStatModifier] +}; + +describe('new StatManagerComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the StatManagerComponent class', () => { + const component = new StatManagerComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(StatManagerComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the StatManagerComponent class', () => { + const component = new StatManagerComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(StatManagerComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.stats[0]?.hash).toStrictEqual(componentProps.stats[0]?.hash); + expect(component.stats[0]?.baseFlat).toBeCloseTo(componentProps.stats[0]?.baseFlat ?? 0, 2); + expect(component.modifiers[0]?.hash).toStrictEqual(componentProps.modifiers[0]?.hash); + expect(component.modifiers[0]?.value).toBeCloseTo(componentProps.modifiers[0]?.value ?? 0, 2); + expect(component.modifiers[0]?.isMultiplier).toStrictEqual(componentProps.modifiers[0]?.isMultiplier); + expect(component.modifiers[0]?.time).toStrictEqual(componentProps.modifiers[0]?.time); + expect(component.indirectStatModifiers[0]?.hash).toStrictEqual(componentProps.indirectStatModifiers[0]?.hash); + expect(component.indirectStatModifiers[0]?.time).toStrictEqual(componentProps.indirectStatModifiers[0]?.time); + expect(component.indirectStatModifiers[0]?.modifiers[0]?.valueOverDurationHash).toStrictEqual( + componentProps.indirectStatModifiers[0]?.modifiers[0]?.valueOverDurationHash + ); + expect(component.indirectStatModifiers[0]?.modifiers[0]?.baseValue).toBeCloseTo( + componentProps.indirectStatModifiers[0]?.modifiers[0]?.baseValue ?? 0, + 2 + ); + expect(component.indirectStatModifiers[0]?.modifiers[0]?.duration).toStrictEqual( + componentProps.indirectStatModifiers[0]?.modifiers[0]?.duration + ); + expect(component.indirectStatModifiers[0]?.modifiers[0]?.tick).toStrictEqual( + componentProps.indirectStatModifiers[0]?.modifiers[0]?.tick + ); + }); + }); +}); + +describe('StatManagerComponent.fromBinary()', () => { + describe('when all component props are given', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('Grass_Clump', { + components: { + StatManager: new StatManagerComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // StatManagerComponent hash. + reader.readUnsignedInteger(); // StatManagerComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the StatManagerComponent class', () => { + const component = StatManagerComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(StatManagerComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.stats[0]?.hash).toStrictEqual(componentProps.stats[0]?.hash); + expect(component.stats[0]?.baseFlat).toBeCloseTo(componentProps.stats[0]?.baseFlat ?? 0, 2); + expect(component.modifiers[0]?.hash).toStrictEqual(componentProps.modifiers[0]?.hash); + expect(component.modifiers[0]?.value).toBeCloseTo(componentProps.modifiers[0]?.value ?? 0, 2); + expect(component.modifiers[0]?.isMultiplier).toStrictEqual(componentProps.modifiers[0]?.isMultiplier); + expect(component.modifiers[0]?.time).toStrictEqual(componentProps.modifiers[0]?.time); + expect(component.indirectStatModifiers[0]?.hash).toStrictEqual(componentProps.indirectStatModifiers[0]?.hash); + expect(component.indirectStatModifiers[0]?.time).toStrictEqual(componentProps.indirectStatModifiers[0]?.time); + expect(component.indirectStatModifiers[0]?.modifiers[0]?.valueOverDurationHash).toStrictEqual( + componentProps.indirectStatModifiers[0]?.modifiers[0]?.valueOverDurationHash + ); + expect(component.indirectStatModifiers[0]?.modifiers[0]?.baseValue).toBeCloseTo( + componentProps.indirectStatModifiers[0]?.modifiers[0]?.baseValue ?? 0, + 2 + ); + expect(component.indirectStatModifiers[0]?.modifiers[0]?.duration).toStrictEqual( + componentProps.indirectStatModifiers[0]?.modifiers[0]?.duration + ); + expect(component.indirectStatModifiers[0]?.modifiers[0]?.tick).toStrictEqual( + componentProps.indirectStatModifiers[0]?.modifiers[0]?.tick + ); + }); + }); + + describe('when stat is null', () => { + let fastForwardedReader: BinaryReader; + + beforeEach(() => { + (componentProps as StatManagerComponentProps).stats = [null]; + + const prefab = new Prefab('Grass_Clump', { + components: { + StatManager: new StatManagerComponent({ version: componentVersion, ...componentProps }) + } + }); + + const saveString = prefab.toSaveString(); + + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // StatManagerComponent hash. + reader.readUnsignedInteger(); // StatManagerComponent data length. + + fastForwardedReader = reader; + }); + + afterEach(() => { + componentProps.stats = [stat]; + }); + + it('returns an instance of the StatManagerComponent class', () => { + const component = StatManagerComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(StatManagerComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.stats[0]).toStrictEqual(null); + expect(component.modifiers[0]?.hash).toStrictEqual(componentProps.modifiers[0]?.hash); + expect(component.modifiers[0]?.value).toBeCloseTo(componentProps.modifiers[0]?.value ?? 0, 2); + expect(component.modifiers[0]?.isMultiplier).toStrictEqual(componentProps.modifiers[0]?.isMultiplier); + expect(component.modifiers[0]?.time).toStrictEqual(componentProps.modifiers[0]?.time); + expect(component.indirectStatModifiers[0]?.hash).toStrictEqual(componentProps.indirectStatModifiers[0]?.hash); + expect(component.indirectStatModifiers[0]?.time).toStrictEqual(componentProps.indirectStatModifiers[0]?.time); + expect(component.indirectStatModifiers[0]?.modifiers[0]?.valueOverDurationHash).toStrictEqual( + componentProps.indirectStatModifiers[0]?.modifiers[0]?.valueOverDurationHash + ); + expect(component.indirectStatModifiers[0]?.modifiers[0]?.baseValue).toBeCloseTo( + componentProps.indirectStatModifiers[0]?.modifiers[0]?.baseValue ?? 0, + 2 + ); + expect(component.indirectStatModifiers[0]?.modifiers[0]?.duration).toStrictEqual( + componentProps.indirectStatModifiers[0]?.modifiers[0]?.duration + ); + expect(component.indirectStatModifiers[0]?.modifiers[0]?.tick).toStrictEqual( + componentProps.indirectStatModifiers[0]?.modifiers[0]?.tick + ); + }); + }); + + describe('when timedModifier is null', () => { + let fastForwardedReader: BinaryReader; + + beforeEach(() => { + (componentProps as StatManagerComponentProps).modifiers = [null]; + + const prefab = new Prefab('Grass_Clump', { + components: { + StatManager: new StatManagerComponent({ version: componentVersion, ...componentProps }) + } + }); + + const saveString = prefab.toSaveString(); + + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // StatManagerComponent hash. + reader.readUnsignedInteger(); // StatManagerComponent data length. + + fastForwardedReader = reader; + }); + + afterEach(() => { + componentProps.modifiers = [timedModifier]; + }); + + it('returns an instance of the StatManagerComponent class', () => { + const component = StatManagerComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(StatManagerComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.stats[0]?.hash).toStrictEqual(componentProps.stats[0]?.hash); + expect(component.stats[0]?.baseFlat).toBeCloseTo(componentProps.stats[0]?.baseFlat ?? 0, 2); + expect(component.modifiers[0]).toStrictEqual(null); + expect(component.indirectStatModifiers[0]?.hash).toStrictEqual(componentProps.indirectStatModifiers[0]?.hash); + expect(component.indirectStatModifiers[0]?.time).toStrictEqual(componentProps.indirectStatModifiers[0]?.time); + expect(component.indirectStatModifiers[0]?.modifiers[0]?.valueOverDurationHash).toStrictEqual( + componentProps.indirectStatModifiers[0]?.modifiers[0]?.valueOverDurationHash + ); + expect(component.indirectStatModifiers[0]?.modifiers[0]?.baseValue).toBeCloseTo( + componentProps.indirectStatModifiers[0]?.modifiers[0]?.baseValue ?? 0, + 2 + ); + expect(component.indirectStatModifiers[0]?.modifiers[0]?.duration).toStrictEqual( + componentProps.indirectStatModifiers[0]?.modifiers[0]?.duration + ); + expect(component.indirectStatModifiers[0]?.modifiers[0]?.tick).toStrictEqual( + componentProps.indirectStatModifiers[0]?.modifiers[0]?.tick + ); + }); + }); + + describe('when indirectStatModifier is null', () => { + let fastForwardedReader: BinaryReader; + + beforeEach(() => { + (componentProps as StatManagerComponentProps).indirectStatModifiers = [null]; + + const prefab = new Prefab('Grass_Clump', { + components: { + StatManager: new StatManagerComponent({ version: componentVersion, ...componentProps }) + } + }); + + const saveString = prefab.toSaveString(); + + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // StatManagerComponent hash. + reader.readUnsignedInteger(); // StatManagerComponent data length. + + fastForwardedReader = reader; + }); + + afterEach(() => { + componentProps.indirectStatModifiers = [indirectStatModifier]; + }); + + it('returns an instance of the StatManagerComponent class', () => { + const component = StatManagerComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(StatManagerComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.stats[0]?.hash).toStrictEqual(componentProps.stats[0]?.hash); + expect(component.stats[0]?.baseFlat).toBeCloseTo(componentProps.stats[0]?.baseFlat ?? 0, 2); + expect(component.modifiers[0]?.hash).toStrictEqual(componentProps.modifiers[0]?.hash); + expect(component.modifiers[0]?.value).toBeCloseTo(componentProps.modifiers[0]?.value ?? 0, 2); + expect(component.modifiers[0]?.isMultiplier).toStrictEqual(componentProps.modifiers[0]?.isMultiplier); + expect(component.modifiers[0]?.time).toStrictEqual(componentProps.modifiers[0]?.time); + expect(component.indirectStatModifiers[0]).toStrictEqual(null); + }); + }); +}); + +describe('StatManagerComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new StatManagerComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = + '00000000000000000000000000000001000000000000000000000010100111001001111110011000010100011110101110000000000000000000000000000000100000000000000000000001010011100100111111001100001010001111010111100000111111110001011110111110101000000000000000000000000000000000000000000000000000000000000000100000000000000000000001010011100100000111111110001011110111110101000000000000000000000000000000000000000000000000000000000000000100000000000000000000010100111001001111110011000010100011110101110000011111111000101111011111010100000000000000000000000110100100'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('StatManagerComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new StatManagerComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '100110001100110011101110000000010000000000000000000000100010010000000000000000000000000000000001000000000000000000000010100111001001111110011000010100011110101110000000000000000000000000000000100000000000000000000001010011100100111111001100001010001111010111100000111111110001011110111110101000000000000000000000000000000000000000000000000000000000000000100000000000000000000001010011100100000111111110001011110111110101000000000000000000000000000000000000000000000000000000000000000100000000000000000000010100111001001111110011000010100011110101110000011111111000101111011111010100000000000000000000000110100100'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // StatManagerComponent data length. + reader.readUnsignedInteger(); // Stat array length. + const isStatNullBit = reader.readBoolean(); + const statHash = reader.readUnsignedInteger(); + const statBaseFlat = reader.readFloat(); + reader.readUnsignedInteger(); // Modifier array length. + const isModifierNullBit = reader.readBoolean(); + const modifierHash = reader.readUnsignedInteger(); + const modifierValue = reader.readFloat(); + const modifierIsMultiplier = reader.readBoolean(); + const modifierTime = reader.readUnsignedLong(); + reader.readUnsignedInteger(); // IndirectStatModifiers array length. + const isIndirectStatModifiersNullBit = reader.readBoolean(); + const indirectHash = reader.readUnsignedInteger(); + const indirectTime = reader.readUnsignedLong(); + reader.readUnsignedInteger(); // IndirectModifierSaveData array length. + const saveHash = reader.readUnsignedInteger(); + const saveBaseValue = reader.readFloat(); + const saveDuration = reader.readUnsignedInteger(); + const saveTick = reader.readUnsignedInteger(); + + expect(hash).toStrictEqual(componentHash); + expect(isStatNullBit).toStrictEqual(false); + expect(statHash).toStrictEqual(componentProps.stats[0]?.hash); + expect(statBaseFlat).toBeCloseTo(componentProps.stats[0]?.baseFlat ?? 0, 2); + expect(isModifierNullBit).toStrictEqual(false); + expect(modifierHash).toStrictEqual(componentProps.modifiers[0]?.hash); + expect(modifierValue).toBeCloseTo(componentProps.modifiers[0]?.value ?? 0, 2); + expect(modifierIsMultiplier).toStrictEqual(componentProps.modifiers[0]?.isMultiplier); + expect(modifierTime).toStrictEqual(componentProps.modifiers[0]?.time); + expect(isIndirectStatModifiersNullBit).toStrictEqual(false); + expect(indirectHash).toStrictEqual(componentProps.indirectStatModifiers[0]?.hash); + expect(indirectTime).toStrictEqual(componentProps.indirectStatModifiers[0]?.time); + expect(saveHash).toStrictEqual(componentProps.indirectStatModifiers[0]?.modifiers[0]?.valueOverDurationHash); + expect(saveBaseValue).toBeCloseTo(componentProps.indirectStatModifiers[0]?.modifiers[0]?.baseValue ?? 0, 2); + expect(saveDuration).toStrictEqual(componentProps.indirectStatModifiers[0]?.modifiers[0]?.duration); + expect(saveTick).toStrictEqual(componentProps.indirectStatModifiers[0]?.modifiers[0]?.tick); + }); +}); diff --git a/src/components/StatManagerComponent.ts b/src/components/StatManagerComponent.ts new file mode 100644 index 0000000..abfc898 --- /dev/null +++ b/src/components/StatManagerComponent.ts @@ -0,0 +1,432 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type Stat = null | { + hash: number; + baseFlat: number; +}; + +type TimedModifier = null | { + hash: number; + value: number; + isMultiplier: boolean; + time: number; +}; + +type IndirectModifierSaveData = { + valueOverDurationHash: number; + baseValue: number; + duration: number; + tick: number; +}; + +type IndirectStatModifier = null | { + hash: number; + time: number; + modifiers: IndirectModifierSaveData[]; +}; + +type StatManagerComponentPropsV2 = { + stats?: Stat[] | undefined; + modifiers?: TimedModifier[] | undefined; + indirectStatModifiers?: IndirectStatModifier[] | undefined; +}; + +export type StatManagerComponentProps = StatManagerComponentPropsV2; + +/** + * @see [Class: `StatManagerComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/StatManagerComponent.md) + * @since v3.0.0 + * @version 2 + * + * @example + * import { StatManagerComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new StatManagerComponent({ version: componentVersion }); + */ +export class StatManagerComponent extends Component { + /** + * @since v2 + * + * @example + * import { StatManagerComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new StatManagerComponent({ version: componentVersion }); + * + * const stats = component.stats; + * // `stats` is `[]` + */ + stats: Stat[]; + + /** + * @since v2 + * + * @example + * import { StatManagerComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new StatManagerComponent({ version: componentVersion }); + * + * const modifiers = component.modifiers; + * // `modifiers` is `[]` + */ + modifiers: TimedModifier[]; + + /** + * @since v2 + * + * @example + * import { StatManagerComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new StatManagerComponent({ version: componentVersion }); + * + * const indirectStatModifiers = component.indirectStatModifiers; + * // `indirectStatModifiers` is `[]` + */ + indirectStatModifiers: IndirectStatModifier[]; + + /** + * @see [Class: `StatManagerComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/StatManagerComponent.md) + * @since v3.0.0 + * @version 2 + * + * @example + * import { StatManagerComponent } from 'att-string-transcoder'; + * + * const componentVersion = 2; + * const component = new StatManagerComponent({ version: componentVersion }); + */ + constructor({ version, stats, modifiers, indirectStatModifiers }: ComponentProps & StatManagerComponentProps) { + const hash = ComponentHash.StatManager; + const name = 'StatManager'; + + super({ hash, name, version }); + + this.stats = stats ?? []; + this.modifiers = modifiers ?? []; + this.indirectStatModifiers = indirectStatModifiers ?? []; + } + + static override fromBinary(reader: BinaryReader, version: number): StatManagerComponent { + const props: ComponentProps & StatManagerComponentProps = { version }; + + /** + * @property {Stat[]} stats + * @since v2 + */ + if (props.version >= 2) { + const statsLength = reader.readUnsignedInteger(); + props.stats = []; + + for (let index = 0; index < statsLength; ++index) { + /** + * @property {boolean} isNull + * @since v2 + */ + const isNull = reader.readBoolean(); + + if (isNull) { + props.stats.push(null); + continue; + } + + props.stats.push({ + /** + * @property {number} hash + * @since v2 + */ + hash: reader.readUnsignedInteger(), + + /** + * @property {float} baseFlat + * @since v2 + */ + baseFlat: reader.readFloat() + }); + } + } + + /** + * @property {TimedModifier[]} modifiers + * @since v2 + */ + if (props.version >= 2) { + const modifiersLength = reader.readUnsignedInteger(); + props.modifiers = []; + + for (let index = 0; index < modifiersLength; ++index) { + /** + * @property {boolean} isNull + * @since v2 + */ + const isNull = reader.readBoolean(); + + if (isNull) { + props.modifiers.push(null); + continue; + } + + props.modifiers.push({ + /** + * @property {number} hash + * @since v2 + */ + hash: reader.readUnsignedInteger(), + + /** + * @property {float} value + * @since v2 + */ + value: reader.readFloat(), + + /** + * @property {boolean} isMultiplier + * @since v2 + */ + isMultiplier: reader.readBoolean(), + + /** + * @property {number} time + * @since v2 + */ + time: reader.readUnsignedLong() + }); + } + } + + /** + * @property {IndirectStatModifier[]} indirectStatModifiers + * @since v2 + */ + if (props.version >= 2) { + const indirectStatModifiersLength = reader.readUnsignedInteger(); + props.indirectStatModifiers = []; + + for (let index = 0; index < indirectStatModifiersLength; ++index) { + /** + * @property {boolean} isNull + * @since v2 + */ + const isNull = reader.readBoolean(); + + if (isNull) { + props.indirectStatModifiers.push(null); + continue; + } + + /** + * @property {number} hash + * @since v2 + */ + const hash = reader.readUnsignedInteger(); + + /** + * @property {number} time + * @since v2 + */ + const time = reader.readUnsignedLong(); + + /** + * @property {IndirectModifierSaveData[]} indirectModifiersSaveData + * @since v2 + */ + const indirectModifiersSaveDataLength = reader.readUnsignedInteger(); + const indirectModifiersSaveData: IndirectModifierSaveData[] = []; + + for ( + let indirectModifiersSaveDataIndex = 0; + indirectModifiersSaveDataIndex < indirectModifiersSaveDataLength; + ++indirectModifiersSaveDataIndex + ) { + indirectModifiersSaveData.push({ + /** + * @property {number} valueOverDurationHash + * @since v2 + */ + valueOverDurationHash: reader.readUnsignedInteger(), + + /** + * @property {float} baseValue + * @since v2 + */ + baseValue: reader.readFloat(), + + /** + * @property {number} duration + * @since v2 + */ + duration: reader.readUnsignedInteger(), + + /** + * @property {number} tick + * @since v2 + */ + tick: reader.readUnsignedInteger() + }); + } + + props.indirectStatModifiers.push({ + hash, + time, + modifiers: indirectModifiersSaveData + }); + } + } + + return new StatManagerComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {Stat[]} stats + * @since v2 + */ + if (version >= 2) { + writer.writeUnsignedInteger(this.stats.length); + + for (const stat of this.stats) { + const isNull = stat === null; + + /** + * @property {boolean} isNull + * @since v2 + */ + writer.writeBoolean(isNull); + + if (!isNull) { + /** + * @property {number} hash + * @since v2 + */ + writer.writeUnsignedInteger(stat.hash); + + /** + * @property {float} baseFlat + * @since v2 + */ + writer.writeFloat(stat.baseFlat); + } + } + } + + /** + * @property {TimedModifier[]} modifiers + * @since v2 + */ + if (version >= 2) { + writer.writeUnsignedInteger(this.modifiers.length); + + for (const modifier of this.modifiers) { + const isNull = modifier === null; + + /** + * @property {boolean} isNull + * @since v2 + */ + writer.writeBoolean(isNull); + + if (!isNull) { + /** + * @property {number} hash + * @since v2 + */ + writer.writeUnsignedInteger(modifier.hash); + + /** + * @property {float} value + * @since v2 + */ + writer.writeFloat(modifier.value); + + /** + * @property {boolean} isMultiplier + * @since v2 + */ + writer.writeBoolean(modifier.isMultiplier); + + /** + * @property {number} time + * @since v2 + */ + writer.writeUnsignedLong(modifier.time); + } + } + } + + /** + * @property {IndirectStatModifier[]} indirectStatModifiers + * @since v2 + */ + if (version >= 2) { + writer.writeUnsignedInteger(this.indirectStatModifiers.length); + + for (const indirectStatModifier of this.indirectStatModifiers) { + const isNull = indirectStatModifier === null; + + /** + * @property {boolean} isNull + * @since v2 + */ + writer.writeBoolean(isNull); + + if (!isNull) { + /** + * @property {number} hash + * @since v2 + */ + writer.writeUnsignedInteger(indirectStatModifier.hash); + + /** + * @property {number} time + * @since v2 + */ + writer.writeUnsignedLong(indirectStatModifier.time); + + /** + * @property {IndirectModifierSaveData[]} indirectModifiersSaveData + * @since v2 + */ + writer.writeUnsignedInteger(indirectStatModifier.modifiers.length); + + for (const modifier of indirectStatModifier.modifiers) { + /** + * @property {number} valueOverDurationHash + * @since v2 + */ + writer.writeUnsignedInteger(modifier.valueOverDurationHash); + + /** + * @property {float} baseValue + * @since v2 + */ + writer.writeFloat(modifier.baseValue); + + /** + * @property {number} duration + * @since v2 + */ + writer.writeUnsignedInteger(modifier.duration); + + /** + * @property {number} tick + * @since v2 + */ + writer.writeUnsignedInteger(modifier.tick); + } + } + } + } + + return writer.flush(); + } +} diff --git a/src/components/UnsupportedComponent.test.ts b/src/components/UnsupportedComponent.test.ts new file mode 100644 index 0000000..7c5420e --- /dev/null +++ b/src/components/UnsupportedComponent.test.ts @@ -0,0 +1,155 @@ +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { UnsupportedComponent } from './UnsupportedComponent.js'; + +describe('new UnsupportedComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the UnsupportedComponent class', () => { + const componentHash = 1337; + const componentName = 'topkek'; + const componentVersion = 1; + const componentData = '11110111001100010000' as BinaryString; + + const component = new UnsupportedComponent({ + hash: componentHash, + name: componentName, + version: componentVersion, + rawData: componentData + }); + + expect(component).toBeInstanceOf(UnsupportedComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.rawData).toStrictEqual(componentData); + }); + }); +}); + +describe('UnsupportedComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + let componentDataLength: number; + const componentHash = ComponentHash.RandomSpawnRectangle; + const componentName = 'RandomSpawnRectangle'; + const componentVersion = 1; + const componentData = '11110111001100010000' as BinaryString; + const prefab = new Prefab('Grass_Clump', { + components: { + RandomSpawnRectangle: new UnsupportedComponent({ + hash: componentHash, + name: componentName, + version: componentVersion, + rawData: componentData + }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // UnsupportedComponent hash. + const dataLength = reader.readUnsignedInteger(); // UnsupportedComponent data length. + + fastForwardedReader = reader; + componentDataLength = dataLength; + }); + + it('returns an instance of the UnsupportedComponent class', () => { + const component = UnsupportedComponent.fromBinary( + fastForwardedReader, + componentVersion, + componentHash, + componentName, + componentDataLength + ); + + expect(component).toBeInstanceOf(UnsupportedComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.rawData).toStrictEqual(componentData); + }); +}); + +describe('UnsupportedComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const componentHash = 1337; + const componentName = 'topkek'; + const componentVersion = 1; + const componentData = '11110111001100010000' as BinaryString; + + const component = new UnsupportedComponent({ + hash: componentHash, + name: componentName, + version: componentVersion, + rawData: componentData + }); + + const data = component.toBinary(); + + const expectedData = componentData; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('UnsupportedComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const componentHash = 1337; + const componentName = 'topkek'; + const componentVersion = 1; + const componentData = '11110111001100010000' as BinaryString; + + const component = new UnsupportedComponent({ + hash: componentHash, + name: componentName, + version: componentVersion, + rawData: componentData + }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = '000000000000000000000101001110010000000000000000000000000001010011110111001100010000'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + const dataLength = reader.readUnsignedInteger(); + const rawData = reader.readBits(dataLength); + + expect(hash).toStrictEqual(componentHash); + expect(rawData).toStrictEqual(componentData); + }); +}); diff --git a/src/components/UnsupportedComponent.ts b/src/components/UnsupportedComponent.ts new file mode 100644 index 0000000..cfca472 --- /dev/null +++ b/src/components/UnsupportedComponent.ts @@ -0,0 +1,90 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; + +import { Component, type ComponentProps } from './Component.js'; + +export type UnsupportedComponentProps = { + hash: number; + name: string; + rawData: BinaryString; +}; + +/** + * A component whose data shape has not been configured in _ATT String Transcoder_. Its internal + * data shape is a raw binary data string so it may be re-encoded later. + * + * @see [Class: `UnsupportedComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/UnsupportedComponent.md) + * + * @example + * import { UnsupportedComponent, type BinaryString } from 'att-string-transcoder'; + * + * const hash = 1337; + * const name = 'SomeUnrecognisedComponentName'; + * const rawData = '11110111001100010000' as BinaryString; + * const version = 1; + * + * const component = new UnsupportedComponent({ hash, name, rawData, version }); + */ +export class UnsupportedComponent extends Component { + /** + * The component's serialised data. + * + * @example + * import { UnsupportedComponent } from 'att-string-transcoder'; + * + * const hash = 1337; + * const name = 'SomeUnrecognisedComponentName'; + * const rawData = '11110111001100010000'; + * const version = 1; + * + * const component = new UnsupportedComponent({ hash, name, rawData, version }); + * + * const rawData = component.rawData; + * // `rawData` is `'11110111001100010000'` + */ + rawData: BinaryString; + + /** + * Creates a versioned component without deserialising its data. + * + * @see [Class: `UnsupportedComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/UnsupportedComponent.md) + * + * @example + * import { UnsupportedComponent, type BinaryString } from 'att-string-transcoder'; + * + * const hash = 1337; + * const name = 'SomeUnrecognisedComponentName'; + * const rawData = '11110111001100010000' as BinaryString; + * const version = 1; + * + * const component = new UnsupportedComponent({ hash, name, rawData, version }); + */ + constructor({ hash, name, rawData, version }: ComponentProps & UnsupportedComponentProps) { + super({ hash, name, version }); + + this.rawData = rawData; + } + + static override fromBinary( + reader: BinaryReader, + version: number, + hash: number, + name: string, + dataLength: number + ): UnsupportedComponent { + return new UnsupportedComponent({ + hash, + name, + version, + rawData: reader.readBits(dataLength) + }); + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + override toBinary(_ = this.version): BinaryString { + /** + * @property {BinaryString} rawData + */ + return this.rawData; + } +} diff --git a/src/components/WoodcutTreeComponent.test.ts b/src/components/WoodcutTreeComponent.test.ts new file mode 100644 index 0000000..6a5bbbc --- /dev/null +++ b/src/components/WoodcutTreeComponent.test.ts @@ -0,0 +1,132 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; +import { ComponentHash } from '../types/ComponentHash.js'; +import { SpeciesHash } from '../types/SpeciesHash.js'; + +import { WoodcutTreeComponent } from './WoodcutTreeComponent.js'; + +const componentHash = ComponentHash.WoodcutTree; +const componentName = 'WoodcutTree'; +const componentVersion = 3; +const componentProps = { + presetHash: 0, + speciesHash: SpeciesHash.Walnut +}; + +describe('new WoodcutTreeComponent()', () => { + describe('when given the required props', () => { + it('returns an instance of the WoodcutTreeComponent class', () => { + const component = new WoodcutTreeComponent({ version: componentVersion }); + + expect(component).toBeInstanceOf(WoodcutTreeComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + }); + }); + + describe('when given additional props', () => { + it('returns an instance of the WoodcutTreeComponent class', () => { + const component = new WoodcutTreeComponent({ version: componentVersion, ...componentProps }); + + expect(component).toBeInstanceOf(WoodcutTreeComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.presetHash).toStrictEqual(componentProps.presetHash); + expect(component.speciesHash).toStrictEqual(componentProps.speciesHash); + }); + }); +}); + +describe('WoodcutTreeComponent.fromBinary()', () => { + let fastForwardedReader: BinaryReader; + + const prefab = new Prefab('Grass_Clump', { + components: { + WoodcutTree: new WoodcutTreeComponent({ version: componentVersion, ...componentProps }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // WoodcutTreeComponent hash. + reader.readUnsignedInteger(); // WoodcutTreeComponent data length. + + fastForwardedReader = reader; + }); + + it('returns an instance of the WoodcutTreeComponent class', () => { + const component = WoodcutTreeComponent.fromBinary(fastForwardedReader, componentVersion); + + expect(component).toBeInstanceOf(WoodcutTreeComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect(component.version).toStrictEqual(componentVersion); + expect(component.presetHash).toStrictEqual(componentProps.presetHash); + expect(component.speciesHash).toStrictEqual(componentProps.speciesHash); + }); +}); + +describe('WoodcutTreeComponent.toBinary()', () => { + it('returns a BinaryString representation of the component', () => { + const component = new WoodcutTreeComponent({ version: componentVersion, ...componentProps }); + + const data = component.toBinary(); + + const expectedData = '0000000000000000000000000000000000000000000000000110110110001100'; + + expect(data).toStrictEqual(expectedData); + }); +}); + +describe('WoodcutTreeComponent.write()', () => { + it('writes a BinaryString representation of the component to the given BinaryWriter, including component hash and data length', () => { + const component = new WoodcutTreeComponent({ version: componentVersion, ...componentProps }); + + const writer = new BinaryWriter(); + component.write(writer); + + const data = writer.flush(); + + const expectedData = + '01000001011100101110101010001111000000000000000000000000010000000000000000000000000000000000000000000000000000000110110110001100'; + + expect(data).toStrictEqual(expectedData); + + const reader = new BinaryReader(data); + + const hash = reader.readUnsignedInteger(); + reader.readUnsignedInteger(); // WoodcutTreeComponent data length. + const presetHash = reader.readUnsignedInteger(); + const speciesHash = reader.readUnsignedInteger(); + + expect(hash).toStrictEqual(componentHash); + expect(presetHash).toStrictEqual(componentProps.presetHash); + expect(speciesHash).toStrictEqual(componentProps.speciesHash); + }); +}); diff --git a/src/components/WoodcutTreeComponent.ts b/src/components/WoodcutTreeComponent.ts new file mode 100644 index 0000000..ceaac05 --- /dev/null +++ b/src/components/WoodcutTreeComponent.ts @@ -0,0 +1,129 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { BinaryString } from '../types/BinaryString.js'; +import type { PresetHash } from '../types/PresetHash.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { ComponentHash } from '../types/ComponentHash.js'; +import { SpeciesHash } from '../types/SpeciesHash.js'; + +import { Component, type ComponentProps } from './Component.js'; + +type WoodcutTreeComponentPropsV3 = { + presetHash?: 0 | PresetHash | undefined; + speciesHash?: SpeciesHash | undefined; +}; + +export type WoodcutTreeComponentProps = WoodcutTreeComponentPropsV3; + +/** + * @see [Class: `WoodcutTreeComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/WoodcutTreeComponent.md) + * @since v3.0.0 + * @version 3 + * + * @example + * import { WoodcutTreeComponent } from 'att-string-transcoder'; + * + * const componentVersion = 3; + * const component = new WoodcutTreeComponent({ version: componentVersion }); + */ +export class WoodcutTreeComponent extends Component { + /** + * @since v3 + * + * @example + * import { WoodcutTreeComponent } from 'att-string-transcoder'; + * + * const componentVersion = 3; + * const component = new WoodcutTreeComponent({ version: componentVersion }); + * + * const presetHash = component.presetHash; + * // `presetHash` is `0` + */ + presetHash: 0 | PresetHash; + + /** + * The hash of the species of the tree prefab this component is attached to. + * + * @since v3 + * + * @example + * import { WoodcutTreeComponent } from 'att-string-transcoder'; + * + * const componentVersion = 3; + * const component = new WoodcutTreeComponent({ version: componentVersion }); + * + * const speciesHash = component.speciesHash; + * // `speciesHash` is `11232` + */ + speciesHash: SpeciesHash; + + /** + * @see [Class: `WoodcutTreeComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/WoodcutTreeComponent.md) + * @since v3.0.0 + * @version 3 + * + * @example + * import { WoodcutTreeComponent } from 'att-string-transcoder'; + * + * const componentVersion = 3; + * const component = new WoodcutTreeComponent({ version: componentVersion }); + */ + constructor({ version, presetHash, speciesHash }: ComponentProps & WoodcutTreeComponentProps) { + const hash = ComponentHash.WoodcutTree; + const name = 'WoodcutTree'; + + super({ hash, name, version }); + + this.presetHash = presetHash ?? 0; + this.speciesHash = speciesHash ?? SpeciesHash.Oak; + } + + static override fromBinary(reader: BinaryReader, version: number): WoodcutTreeComponent { + const props: ComponentProps & WoodcutTreeComponentProps = { version }; + + /** + * @property {number} presetHash + * @since v3 + */ + if (props.version >= 3) { + props.presetHash = reader.readUnsignedInteger(); + } + + /** + * @property {number} speciesHash + * @since v3 + */ + if (props.version >= 3) { + props.speciesHash = reader.readUnsignedInteger(); + } + + return new WoodcutTreeComponent(props); + } + + override toBinary(version = this.version): BinaryString { + const writer = new BinaryWriter(); + + /** + * @property {number} presetHash + * @since v3 + */ + + /** + * @property {number} presetHash + * @since v3 + */ + if (version >= 3) { + writer.writeUnsignedInteger(this.presetHash); + } + + /** + * @property {number} speciesHash + * @since v3 + */ + if (version >= 3) { + writer.writeUnsignedInteger(this.speciesHash); + } + + return writer.flush(); + } +} diff --git a/src/components/index.ts b/src/components/index.ts deleted file mode 100644 index 1e528cf..0000000 --- a/src/components/index.ts +++ /dev/null @@ -1,44 +0,0 @@ -import * as transcoders from './transcoders'; - -export type ComponentName = keyof typeof transcoders; - -export type BasicDecay = transcoders.BasicDecay.BasicDecay; -export type DurabilityModule = transcoders.DurabilityModule.DurabilityModule; -export type Fire = transcoders.Fire.Fire; -export type Fuse = transcoders.Fuse.Fuse; -export type HeatSourceBase = transcoders.HeatSourceBase.HeatSourceBase; -export type LiquidContainer = transcoders.LiquidContainer.LiquidContainer; -export type NetworkRigidbody = transcoders.NetworkRigidbody.NetworkRigidbody; -export type PhysicalMaterialPart = transcoders.PhysicalMaterialPart.PhysicalMaterialPart; -export type Pickup = transcoders.Pickup.Pickup; -export type PickupDock = transcoders.PickupDock.PickupDock; -export type PopulationSpawnArea = transcoders.PopulationSpawnArea.PopulationSpawnArea; -export type SentGift = transcoders.SentGift.SentGift; -export type SpawnArea = transcoders.SpawnArea.SpawnArea; -export type StatManager = transcoders.StatManager.StatManager; -export type WoodcutTree = transcoders.WoodcutTree.WoodcutTree; - -export type KnownComponent = - | BasicDecay - | DurabilityModule - | Fire - | Fuse - | HeatSourceBase - | LiquidContainer - | NetworkRigidbody - | PhysicalMaterialPart - | Pickup - | PickupDock - | PopulationSpawnArea - | SentGift - | SpawnArea - | StatManager - | WoodcutTree; - -export type UnknownComponent = { hash: number; data: string }; - -export type Component = KnownComponent | UnknownComponent[]; - -export { ComponentVersion } from './ComponentVersion'; - -export { transcoders }; diff --git a/src/components/transcoders/basicDecay.ts b/src/components/transcoders/basicDecay.ts deleted file mode 100644 index 1a287f1..0000000 --- a/src/components/transcoders/basicDecay.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { ComponentHash } from '../../ComponentHash'; -import { BinaryReader, createBinaryWriter } from '../../utils'; - -const HUNDRED_YEARS_TICKS = 31557600000000000; - -export type BasicDecay = { - isDisabled?: boolean; - timelineEntry?: number; -}; - -export const decode = (reader: BinaryReader, version: number): BasicDecay => { - const component: BasicDecay = {}; - - if (version >= 3) component.isDisabled = reader.boolean(); - - if (version >= 3) component.timelineEntry = reader.uLong(); - - return component; -}; - -export const encode = ({ isDisabled = true, timelineEntry = HUNDRED_YEARS_TICKS }: BasicDecay): string => { - const writer = createBinaryWriter(); - - /* Component hash. */ - writer.uInt(ComponentHash.BasicDecay); - const hashBits = writer.flush(); - - /* Component data. */ - writer.boolean(isDisabled); - writer.uLong(timelineEntry); - const dataBits = writer.flush(); - - /* Component data length. */ - writer.uInt(dataBits.length); - const sizeBits = writer.flush(); - - /* Return encoded component. */ - writer.binary(hashBits); - writer.binary(sizeBits); - writer.binary(dataBits); - - return writer.flush(); -}; diff --git a/src/components/transcoders/durabilityModule.ts b/src/components/transcoders/durabilityModule.ts deleted file mode 100644 index d4fa53f..0000000 --- a/src/components/transcoders/durabilityModule.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { ComponentHash } from '../../ComponentHash'; -import { BinaryReader, createBinaryWriter } from '../../utils'; - -export type DurabilityModule = { - integrity?: number; -}; - -export const decode = (reader: BinaryReader, version: number): DurabilityModule => { - const component: DurabilityModule = {}; - - if (version >= 1) component.integrity = reader.float(); - - return component; -}; - -export const encode = ({ integrity = 1 }: DurabilityModule): string => { - const writer = createBinaryWriter(); - - /* Component hash. */ - writer.uInt(ComponentHash.DurabilityModule); - const hashBits = writer.flush(); - - /* Component data. */ - writer.float(integrity); - const dataBits = writer.flush(); - - /* Component data length. */ - writer.uInt(dataBits.length); - const sizeBits = writer.flush(); - - /* Return encoded component. */ - writer.binary(hashBits); - writer.binary(sizeBits); - writer.binary(dataBits); - - return writer.flush(); -}; diff --git a/src/components/transcoders/fire.ts b/src/components/transcoders/fire.ts deleted file mode 100644 index ca75f9f..0000000 --- a/src/components/transcoders/fire.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { ComponentHash } from '../../ComponentHash'; -import { BinaryReader, createBinaryWriter } from '../../utils'; - -export type Fire = { - fuelConsumptionProgress?: number; -}; - -export const decode = (reader: BinaryReader, version: number): Fire => { - const component: Fire = {}; - - if (version >= 2) component.fuelConsumptionProgress = reader.float(); - - return component; -}; - -export const encode = ({ fuelConsumptionProgress = 0 }: Fire): string => { - const writer = createBinaryWriter(); - - /* Component hash. */ - writer.uInt(ComponentHash.Fire); - const hashBits = writer.flush(); - - /* Component data. */ - writer.float(fuelConsumptionProgress); - const dataBits = writer.flush(); - - /* Component data length. */ - writer.uInt(dataBits.length); - const sizeBits = writer.flush(); - - /* Return encoded component. */ - writer.binary(hashBits); - writer.binary(sizeBits); - writer.binary(dataBits); - - return writer.flush(); -}; diff --git a/src/components/transcoders/fuse.ts b/src/components/transcoders/fuse.ts deleted file mode 100644 index 0ef5517..0000000 --- a/src/components/transcoders/fuse.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { ComponentHash } from '../../ComponentHash'; -import { BinaryReader, createBinaryWriter } from '../../utils'; - -export type Fuse = { - isFinished?: boolean; - isLit?: boolean; - currentFuseAmount?: number; -}; - -export const decode = (reader: BinaryReader, version: number): Fuse => { - const component: Fuse = {}; - - if (version >= 1) component.isFinished = reader.boolean(); - - if (version >= 1) component.isLit = reader.boolean(); - - if (version >= 1) component.currentFuseAmount = reader.float(); - - return component; -}; - -export const encode = ({ isFinished = false, isLit = false, currentFuseAmount = 1 }: Fuse): string => { - const writer = createBinaryWriter(); - - /* Component hash. */ - writer.uInt(ComponentHash.Fuse); - const hashBits = writer.flush(); - - /* Component data. */ - writer.boolean(isFinished); - writer.boolean(isLit); - writer.float(currentFuseAmount); - const dataBits = writer.flush(); - - /* Component data length. */ - writer.uInt(dataBits.length); - const sizeBits = writer.flush(); - - /* Return encoded component. */ - writer.binary(hashBits); - writer.binary(sizeBits); - writer.binary(dataBits); - - return writer.flush(); -}; diff --git a/src/components/transcoders/heatSourceBase.ts b/src/components/transcoders/heatSourceBase.ts deleted file mode 100644 index c5c9fbe..0000000 --- a/src/components/transcoders/heatSourceBase.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { ComponentHash } from '../../ComponentHash'; -import { BinaryReader, createBinaryWriter } from '../../utils'; - -const HUNDRED_YEARS_TICKS = 31557600000000000; - -export type HeatSourceBase = { - isLit?: boolean; - progress?: number; - time?: number; -}; - -export const decode = (reader: BinaryReader, version: number): HeatSourceBase => { - const component: HeatSourceBase = {}; - - if (version >= 1) component.isLit = reader.boolean(); - - if (version >= 1) component.progress = reader.float(); - - if (version >= 1) component.time = reader.uLong(); - - return component; -}; - -export const encode = ({ isLit = true, progress = 0, time = HUNDRED_YEARS_TICKS }: HeatSourceBase): string => { - const writer = createBinaryWriter(); - - /* Component hash. */ - writer.uInt(ComponentHash.HeatSourceBase); - const hashBits = writer.flush(); - - /* Component data. */ - writer.boolean(isLit); - writer.float(progress); - writer.uLong(time); - const dataBits = writer.flush(); - - /* Component data length. */ - writer.uInt(dataBits.length); - const sizeBits = writer.flush(); - - /* Return encoded component. */ - writer.binary(hashBits); - writer.binary(sizeBits); - writer.binary(dataBits); - - return writer.flush(); -}; diff --git a/src/components/transcoders/index.ts b/src/components/transcoders/index.ts deleted file mode 100644 index 932eb8c..0000000 --- a/src/components/transcoders/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -export * as BasicDecay from './basicDecay'; -export * as DurabilityModule from './durabilityModule'; -export * as Fire from './fire'; -export * as Fuse from './fuse'; -export * as HeatSourceBase from './heatSourceBase'; -export * as LiquidContainer from './liquidContainer'; -export * as NetworkRigidbody from './networkRigidbody'; -export * as PhysicalMaterialPart from './physicalMaterialPart'; -export * as Pickup from './pickup'; -export * as PickupDock from './pickupDock'; -export * as PopulationSpawnArea from './populationSpawnArea'; -export * as SentGift from './sentGift'; -export * as SpawnArea from './spawnArea'; -export * as StatManager from './statManager'; -export * as WoodcutTree from './woodcutTree'; diff --git a/src/components/transcoders/liquidContainer.ts b/src/components/transcoders/liquidContainer.ts deleted file mode 100644 index 25c16bd..0000000 --- a/src/components/transcoders/liquidContainer.ts +++ /dev/null @@ -1,168 +0,0 @@ -import { ComponentHash } from '../../ComponentHash'; -import { BinaryReader, createBinaryWriter } from '../../utils'; - -type Color = { - r: number; - g: number; - b: number; - a: number; -}; - -type Effect = null | { - hash: number; - strengthMultiplier: number; -}; - -type FoodChunk = number; - -type CustomData = { - color: Color; - isConsumableThroughSkin: boolean; - visualDataHash: number; - effects: Effect[]; - foodChunks: FoodChunk[]; -}; - -export type LiquidContainer = { - canAddTo?: boolean; - canRemoveFrom?: boolean; - contentLevel?: number; - hasContent?: boolean; - isCustom?: boolean; - presetHash?: number; - customData?: null | CustomData; -}; - -export const decode = (reader: BinaryReader, version: number): LiquidContainer => { - const component: LiquidContainer = {}; - - if (version >= 1) component.canAddTo = reader.boolean(); - - if (version >= 1) component.canRemoveFrom = reader.boolean(); - - if (version >= 1) component.contentLevel = reader.int(); - - if (version >= 1) component.hasContent = reader.boolean(); - - if (version >= 1) component.isCustom = reader.boolean(); - - if (version >= 1) component.presetHash = reader.uInt(); - - if (version >= 1) { - /* Get custom data */ - const isNull = reader.boolean(); - if (isNull) { - component.customData = null; - } else { - const customData = { - color: { - r: reader.float(), - g: reader.float(), - b: reader.float(), - a: reader.float() - }, - isConsumableThroughSkin: reader.boolean(), - visualDataHash: reader.uInt() - }; - - /* Get the effects array. */ - const effectsLength = reader.uInt(); - const effects: Effect[] = []; - for (let index = 0; index < effectsLength; ++index) { - /* Skip effect if is null. */ - const isNull = reader.boolean(); - if (isNull) { - effects.push(null); - continue; - } - - effects.push({ - hash: reader.uInt(), - strengthMultiplier: reader.float() - }); - } - - /* Get the food chunks array. */ - const foodChunksLength = reader.uInt(); - const foodChunks: FoodChunk[] = []; - for (let index = 0; index < foodChunksLength; ++index) { - foodChunks.push(reader.uInt()); - } - - /* Append custom data to result. */ - component.customData = { - ...customData, - effects, - foodChunks - }; - } - } - - return component; -}; - -export const encode = ({ - canAddTo = false, - canRemoveFrom = false, - contentLevel = 0, - hasContent = !!contentLevel, - isCustom = false, - presetHash = 0, - customData = null -}: LiquidContainer): string => { - const writer = createBinaryWriter(); - - /* Component hash. */ - writer.uInt(ComponentHash.LiquidContainer); - const hashBits = writer.flush(); - - /* Component data. */ - writer.boolean(canAddTo); - writer.boolean(canRemoveFrom); - writer.int(Math.round(contentLevel)); - writer.boolean(hasContent); - writer.boolean(isCustom); - writer.uInt(presetHash); - - if (customData === null) { - writer.boolean(true); // isNull bit - } else { - writer.boolean(false); // isNull bit - writer.float(customData.color.r); - writer.float(customData.color.g); - writer.float(customData.color.b); - writer.float(customData.color.a); - writer.boolean(customData.isConsumableThroughSkin); - writer.uInt(customData.visualDataHash); - writer.uInt(customData.effects.length); - - for (const effect of customData.effects) { - if (effect === null) { - writer.boolean(true); // isNull bit - } else { - writer.boolean(false); // isNull bit - writer.uInt(effect.hash); - writer.float(effect.strengthMultiplier); - } - } - - writer.uInt(customData.foodChunks.length); - - for (const foodChunk of customData.foodChunks) { - writer.uInt(foodChunk); - } - } - - const dataBits = writer.flush(); - - /* Component data length. */ - writer.uInt(dataBits.length); - const sizeBits = writer.flush(); - - /* Return encoded component. */ - writer.binary(hashBits); - writer.binary(sizeBits); - writer.binary(dataBits); - - return writer.flush(); -}; diff --git a/src/components/transcoders/networkRigidbody.ts b/src/components/transcoders/networkRigidbody.ts deleted file mode 100644 index 2048b14..0000000 --- a/src/components/transcoders/networkRigidbody.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { ComponentHash } from '../../ComponentHash'; -import { BinaryReader, createBinaryWriter } from '../../utils'; - -export type NetworkRigidbody = { - position?: { - x: number; - y: number; - z: number; - }; - rotation?: { - x: number; - y: number; - z: number; - w: number; - }; - isKinematic?: boolean; - isServerSleeping?: boolean; - velocity?: { - x: number; - y: number; - z: number; - }; - angularVelocity?: { - x: number; - y: number; - z: number; - }; -}; - -export const decode = (reader: BinaryReader, version: number): NetworkRigidbody => { - const component: NetworkRigidbody = {}; - - if (version >= 1) { - component.position = { - x: reader.float(), - y: reader.float(), - z: reader.float() - }; - } - - if (version >= 1) { - component.rotation = { - x: reader.float(), - y: reader.float(), - z: reader.float(), - w: reader.float() - }; - } - - if (version >= 1) component.isKinematic = reader.boolean(); - - if (version >= 1) component.isServerSleeping = reader.boolean(); - - if (version >= 1) { - component.velocity = { - x: reader.float(), - y: reader.float(), - z: reader.float() - }; - } - - if (version >= 1) { - component.angularVelocity = { - x: reader.float(), - y: reader.float(), - z: reader.float() - }; - } - - return component; -}; - -export const encode = ({ - position = { x: 0, y: 0, z: 0 }, - rotation = { x: 0, y: 0, z: 0, w: 1 }, - isKinematic = false, - isServerSleeping = false, - velocity = { x: 0, y: 0, z: 0 }, - angularVelocity = { x: 0, y: 0, z: 0 } -}: NetworkRigidbody): string => { - const writer = createBinaryWriter(); - - /* Component hash. */ - writer.uInt(ComponentHash.NetworkRigidbody); - const hashBits = writer.flush(); - - /* Component data. */ - writer.float(position.x); - writer.float(position.y); - writer.float(position.z); - writer.float(rotation.x); - writer.float(rotation.y); - writer.float(rotation.z); - writer.float(rotation.w); - writer.boolean(isKinematic); - writer.boolean(isServerSleeping); - writer.float(velocity.x); - writer.float(velocity.y); - writer.float(velocity.z); - writer.float(angularVelocity.x); - writer.float(angularVelocity.y); - writer.float(angularVelocity.z); - - const dataBits = writer.flush(); - - /* Component data length. */ - writer.uInt(dataBits.length); - const sizeBits = writer.flush(); - - /* Return encoded component. */ - writer.binary(hashBits); - writer.binary(sizeBits); - writer.binary(dataBits); - - return writer.flush(); -}; diff --git a/src/components/transcoders/physicalMaterialPart.ts b/src/components/transcoders/physicalMaterialPart.ts deleted file mode 100644 index e52f97a..0000000 --- a/src/components/transcoders/physicalMaterialPart.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { ComponentHash } from '../../ComponentHash'; -import { PhysicalMaterialPartHash } from '../../PhysicalMaterialPartHash'; -import { BinaryReader, createBinaryWriter } from '../../utils'; - -export type PhysicalMaterialPart = { - materialHash?: number; -}; - -export const decode = (reader: BinaryReader, version: number): PhysicalMaterialPart => { - const component: PhysicalMaterialPart = {}; - - if (version >= 1) component.materialHash = reader.uInt(); - - return component; -}; - -export const encode = ({ materialHash = PhysicalMaterialPartHash.Iron }: PhysicalMaterialPart): string => { - const writer = createBinaryWriter(); - - /* Component hash. */ - writer.uInt(ComponentHash.PhysicalMaterialPart); - const hashBits = writer.flush(); - - /* Component data. */ - writer.uInt(materialHash); - const dataBits = writer.flush(); - - /* Component data length. */ - writer.uInt(dataBits.length); - const sizeBits = writer.flush(); - - /* Return encoded component. */ - writer.binary(hashBits); - writer.binary(sizeBits); - writer.binary(dataBits); - - return writer.flush(); -}; diff --git a/src/components/transcoders/pickup.ts b/src/components/transcoders/pickup.ts deleted file mode 100644 index fc3b50c..0000000 --- a/src/components/transcoders/pickup.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { ComponentHash } from '../../ComponentHash'; -import { BinaryReader, createBinaryWriter } from '../../utils'; - -type GrabPointParameters = null | { - grabPointIndex: number; - lastLinearPosition: number; - lastPosition: { - x: number; - y: number; - z: number; - }; - lastRotation: { - x: number; - y: number; - z: number; - w: number; - }; -}; - -export type Pickup = { - lastInteractorPlayerId?: number; - dockedMemory?: GrabPointParameters[]; -}; - -export const decode = (reader: BinaryReader, version: number): Pickup => { - const component: Pickup = {}; - - if (version >= 1) component.lastInteractorPlayerId = reader.int(); - - if (version >= 2) { - /* Get the grabPointParameters array. */ - const grabPointParametersLength = reader.uInt(); - const grabPointParameters: GrabPointParameters[] = []; - for (let index = 0; index < grabPointParametersLength; ++index) { - /* Skip grabPointParameters if is null. */ - const isNull = reader.boolean(); - if (isNull) { - grabPointParameters.push(null); - continue; - } - - grabPointParameters.push({ - grabPointIndex: reader.int(), - lastLinearPosition: reader.float(), - lastPosition: { - x: reader.uInt(), - y: reader.uInt(), - z: reader.uInt() - }, - lastRotation: { - x: reader.uInt(), - y: reader.uInt(), - z: reader.uInt(), - w: reader.uInt() - } - }); - } - - component.dockedMemory = grabPointParameters; - } - - return component; -}; - -export const encode = ({ lastInteractorPlayerId = 0, dockedMemory = [] }: Pickup): string => { - const writer = createBinaryWriter(); - - /* Component hash. */ - writer.uInt(ComponentHash.Pickup); - const hashBits = writer.flush(); - - /* Component data. */ - writer.int(lastInteractorPlayerId); - writer.uInt(dockedMemory.length); - - for (const grabPointParameters of dockedMemory) { - if (grabPointParameters === null) { - writer.boolean(true); // isNull bit - } else { - writer.boolean(false); // isNull bit - writer.int(grabPointParameters.grabPointIndex); - writer.float(grabPointParameters.lastLinearPosition); - writer.uInt(grabPointParameters.lastPosition.x); - writer.uInt(grabPointParameters.lastPosition.y); - writer.uInt(grabPointParameters.lastPosition.z); - writer.uInt(grabPointParameters.lastRotation.x); - writer.uInt(grabPointParameters.lastRotation.y); - writer.uInt(grabPointParameters.lastRotation.z); - writer.uInt(grabPointParameters.lastRotation.w); - } - } - - const dataBits = writer.flush(); - - /* Component data length. */ - writer.uInt(dataBits.length); - const sizeBits = writer.flush(); - - /* Return encoded component. */ - writer.binary(hashBits); - writer.binary(sizeBits); - writer.binary(dataBits); - - return writer.flush(); -}; diff --git a/src/components/transcoders/pickupDock.ts b/src/components/transcoders/pickupDock.ts deleted file mode 100644 index e689067..0000000 --- a/src/components/transcoders/pickupDock.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { ComponentHash } from '../../ComponentHash'; -import { BinaryReader, createBinaryWriter } from '../../utils'; - -export type PickupDock = { - dockedTypeHash?: number; - quantity?: number; - childIndex?: number; -}; - -export const decode = (reader: BinaryReader, version: number): PickupDock => { - const component: PickupDock = {}; - - if (version >= 2) component.dockedTypeHash = reader.uInt(); - - if (version >= 2) component.quantity = reader.int(); - - if (version >= 2) component.childIndex = reader.int(); - - return component; -}; - -export const encode = ({ dockedTypeHash = 0, quantity = 1, childIndex = 0 }: PickupDock): string => { - const writer = createBinaryWriter(); - - /* Component hash. */ - writer.uInt(ComponentHash.PickupDock); - const hashBits = writer.flush(); - - /* Component data. */ - writer.uInt(dockedTypeHash); - writer.int(quantity); - writer.int(childIndex); - - const dataBits = writer.flush(); - - /* Component data length. */ - writer.uInt(dataBits.length); - const sizeBits = writer.flush(); - - /* Return encoded component. */ - writer.binary(hashBits); - writer.binary(sizeBits); - writer.binary(dataBits); - - return writer.flush(); -}; diff --git a/src/components/transcoders/populationSpawnArea.ts b/src/components/transcoders/populationSpawnArea.ts deleted file mode 100644 index daf87e3..0000000 --- a/src/components/transcoders/populationSpawnArea.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { ComponentHash } from '../../ComponentHash'; -import { PopulationDefinitionHash } from '../../PopulationDefinitionHash'; -import { BinaryReader, createBinaryWriter } from '../../utils'; - -type PopulationSaveDataChild = null | { - index: number; - pointIndex: number; -}; - -export type PopulationSpawnArea = { - definition?: number; - isPopulationStarted?: boolean; - children?: PopulationSaveDataChild[]; - maxPopulation?: number; - currentPopulation?: number; - checkPopulationTime?: number; - numberOfSpawnPoints?: number; - startingPopulation?: number; - isOneOff?: boolean; -}; - -export const decode = (reader: BinaryReader, version: number): PopulationSpawnArea => { - const component: PopulationSpawnArea = {}; - - if (version >= 2) component.definition = reader.uInt(); - - if (version >= 2) component.isPopulationStarted = reader.boolean(); - - if (version >= 2) { - /* Get the children array. */ - const childrenLength = reader.uInt(); - component.children = []; - for (let index = 0; index < childrenLength; ++index) { - /* Skip child if is null. */ - const isNull = reader.boolean(); - if (isNull) { - component.children.push(null); - continue; - } - - component.children.push({ - index: reader.int(), - pointIndex: reader.int() - }); - } - } - - if (version >= 2) component.maxPopulation = reader.int(); - - if (version >= 2) component.currentPopulation = reader.int(); - - if (version >= 2) component.checkPopulationTime = reader.uLong(); - - if (version >= 2) component.numberOfSpawnPoints = reader.int(); - - if (version >= 2) component.startingPopulation = reader.int(); - - if (version >= 2) component.isOneOff = reader.boolean(); - - return component; -}; - -export const encode = ({ - definition = PopulationDefinitionHash.StickPopulation, - isPopulationStarted = true, - children = [], - maxPopulation = 20, - currentPopulation = 5, - checkPopulationTime = 852974979330, - numberOfSpawnPoints = 40, - startingPopulation = 5, - isOneOff = false -}: PopulationSpawnArea): string => { - const writer = createBinaryWriter(); - - /* Component hash. */ - writer.uInt(ComponentHash.PopulationSpawnArea); - const hashBits = writer.flush(); - - /* Component data. */ - writer.uInt(definition); - writer.boolean(isPopulationStarted); - writer.uInt(children.length); - - for (const child of children) { - if (child === null) { - writer.boolean(true); // isNull bit - } else { - writer.boolean(false); // isNull bit - writer.int(child.index); - writer.int(child.pointIndex); - } - } - - writer.int(maxPopulation); - writer.int(currentPopulation); - writer.uLong(checkPopulationTime); - writer.int(numberOfSpawnPoints); - writer.int(startingPopulation); - writer.boolean(isOneOff); - const dataBits = writer.flush(); - - /* Component data length. */ - writer.uInt(dataBits.length); - const sizeBits = writer.flush(); - - /* Return encoded component. */ - writer.binary(hashBits); - writer.binary(sizeBits); - writer.binary(dataBits); - - return writer.flush(); -}; diff --git a/src/components/transcoders/sentGift.ts b/src/components/transcoders/sentGift.ts deleted file mode 100644 index 25b2245..0000000 --- a/src/components/transcoders/sentGift.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { ComponentHash } from '../../ComponentHash'; -import { BinaryReader, createBinaryWriter } from '../../utils'; - -type Gift = null | { - data: number[]; - messageSizeInBytes: number; - hash: number; - chunkVersioning: number[]; -}; - -type SentGiftTag = null | { - from: number; - to: number; -}; - -export type SentGift = { - receiverName?: string; - senderName?: string; - gifts?: Gift[]; - senderTag?: SentGiftTag; -}; - -export const decode = (reader: BinaryReader, version: number): SentGift => { - const component: SentGift = {}; - - if (version >= 1) component.receiverName = reader.string(); - - if (version >= 1) component.senderName = reader.string(); - - if (version >= 1) { - /* Get the gifts array. */ - const giftsLength = reader.uInt(); - component.gifts = []; - - for (let g = 0; g < giftsLength; ++g) { - /* Skip gift if is null. */ - const isNull = reader.boolean(); - if (isNull) { - component.gifts.push(null); - continue; - } - - /* Get the data array. */ - const dataLength = reader.uInt(); - const data: number[] = []; - - for (let d = 0; d < dataLength; ++d) { - data.push(reader.uInt()); - } - - const messageSizeInBytes = reader.uInt(); - const hash = reader.uInt(); - - /* Get the chunkVersioning array. */ - const chunkVersioningLength = reader.uInt(); - const chunkVersioning: number[] = []; - - for (let c = 0; c < chunkVersioningLength; ++c) { - chunkVersioning.push(reader.uInt()); - } - - component.gifts.push({ - data, - messageSizeInBytes, - hash, - chunkVersioning - }); - } - } - - if (version >= 1) { - const senderTagIsNull = reader.boolean(); - - component.senderTag = senderTagIsNull - ? null - : { - from: reader.int(), - to: reader.int() - }; - } - - return component; -}; - -export const encode = ({ receiverName = '', senderName = '', gifts = [], senderTag = null }: SentGift): string => { - const writer = createBinaryWriter(); - - /* Component hash. */ - writer.uInt(ComponentHash.SentGift); - const hashBits = writer.flush(); - - /* Component data. */ - writer.string(receiverName); - writer.string(senderName); - writer.uInt(gifts.length); - - for (const gift of gifts) { - if (gift === null) { - writer.boolean(true); // isNull bit - } else { - writer.boolean(false); // isNull bit - writer.uInt(gift.data.length); - - for (const d of gift.data) writer.uInt(d); - - writer.uInt(gift.messageSizeInBytes); - writer.uInt(gift.hash); - writer.uInt(gift.chunkVersioning.length); - - for (const c of gift.chunkVersioning) writer.uInt(c); - } - } - - if (senderTag === null) { - writer.boolean(true); // isNull bit - } else { - writer.boolean(false); // isNull bit - writer.int(senderTag.from); - writer.int(senderTag.to); - } - - const dataBits = writer.flush(); - - /* Component data length. */ - writer.uInt(dataBits.length); - const sizeBits = writer.flush(); - - /* Return encoded component. */ - writer.binary(hashBits); - writer.binary(sizeBits); - writer.binary(dataBits); - - return writer.flush(); -}; diff --git a/src/components/transcoders/spawnArea.ts b/src/components/transcoders/spawnArea.ts deleted file mode 100644 index 70bfc56..0000000 --- a/src/components/transcoders/spawnArea.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { ComponentHash } from '../../ComponentHash'; -import { BinaryReader, createBinaryWriter } from '../../utils'; - -export type SpawnArea = { - size?: number; - groundLayers?: number; - avoidLayers?: number; - isAligningNormal?: boolean; - maxAcceptableAngleDot?: number; -}; - -export const decode = (reader: BinaryReader, version: number): SpawnArea => { - const component: SpawnArea = {}; - - if (version >= 1) component.size = reader.float(); - - if (version >= 1) component.groundLayers = reader.int(); - - if (version >= 1) component.avoidLayers = reader.int(); - - if (version >= 1) component.isAligningNormal = reader.boolean(); - - if (version >= 1) component.maxAcceptableAngleDot = reader.float(); - - return component; -}; - -export const encode = ({ - size = 5, - groundLayers = 1280, - avoidLayers = 8721, - isAligningNormal = false, - maxAcceptableAngleDot = -1 -}: SpawnArea): string => { - const writer = createBinaryWriter(); - - /* Component hash. */ - writer.uInt(ComponentHash.SpawnArea); - const hashBits = writer.flush(); - - /* Component data. */ - writer.float(size); - writer.int(groundLayers); - writer.int(avoidLayers); - writer.boolean(isAligningNormal); - writer.float(maxAcceptableAngleDot); - const dataBits = writer.flush(); - - /* Component data length. */ - writer.uInt(dataBits.length); - const sizeBits = writer.flush(); - - /* Return encoded component. */ - writer.binary(hashBits); - writer.binary(sizeBits); - writer.binary(dataBits); - - return writer.flush(); -}; diff --git a/src/components/transcoders/statManager.ts b/src/components/transcoders/statManager.ts deleted file mode 100644 index d110c63..0000000 --- a/src/components/transcoders/statManager.ts +++ /dev/null @@ -1,182 +0,0 @@ -import { ComponentHash } from '../../ComponentHash'; -import { BinaryReader, createBinaryWriter } from '../../utils'; - -type Stat = null | { - hash: number; - baseFlat: number; -}; - -type TimedModifier = null | { - hash: number; - value: number; - isMultiplier: boolean; - time: number; -}; - -type IndirectModifierSaveData = { - valueOverDurationHash: number; - baseValue: number; - duration: number; - tick: number; -}; - -type IndirectStatModifier = null | { - hash: number; - time: number; - modifiers: IndirectModifierSaveData[]; -}; - -export type StatManager = { - stats?: Stat[]; - modifiers?: TimedModifier[]; - indirectStatModifiers?: IndirectStatModifier[]; -}; - -export const decode = (reader: BinaryReader, version: number): StatManager => { - const component: StatManager = {}; - - if (version >= 2) { - /* Get stats array. */ - const statsLength = reader.uInt(); - component.stats = []; - for (let index = 0; index < statsLength; ++index) { - /* Skip stat if is null. */ - const isNull = reader.boolean(); - if (isNull) { - component.stats.push(null); - continue; - } - - component.stats.push({ - hash: reader.uInt(), - baseFlat: reader.float() - }); - } - } - - if (version >= 2) { - /* Get modifiers array. */ - const modifiersLength = reader.uInt(); - component.modifiers = []; - for (let index = 0; index < modifiersLength; ++index) { - /* Skip modifier if is null. */ - const isNull = reader.boolean(); - if (isNull) { - component.modifiers.push(null); - continue; - } - - component.modifiers.push({ - hash: reader.uInt(), - value: reader.float(), - isMultiplier: reader.boolean(), - time: reader.uLong() - }); - } - } - - if (version >= 2) { - /* Get indirect stat modifiers array. */ - const indirectStatModifiersLength = reader.uInt(); - component.indirectStatModifiers = []; - for (let index = 0; index < indirectStatModifiersLength; ++index) { - /* Skip indirectStatModifier if is null. */ - const isNull = reader.boolean(); - if (isNull) { - component.indirectStatModifiers.push(null); - continue; - } - - const hash = reader.uInt(); - const time = reader.uLong(); - - /* Get indirect modifier save data array. */ - const indirectModifiersSaveDataLength = reader.uInt(); - const indirectModifiersSaveData: IndirectModifierSaveData[] = []; - for (let index = 0; index < indirectModifiersSaveDataLength; ++index) { - indirectModifiersSaveData.push({ - valueOverDurationHash: reader.uInt(), - baseValue: reader.float(), - duration: reader.uInt(), - tick: reader.uInt() - }); - } - - component.indirectStatModifiers.push({ - hash, - time, - modifiers: indirectModifiersSaveData - }); - } - } - - return component; -}; - -export const encode = ({ stats = [], modifiers = [], indirectStatModifiers = [] }: StatManager): string => { - const writer = createBinaryWriter(); - - /* Component hash. */ - writer.uInt(ComponentHash.StatManager); - const hashBits = writer.flush(); - - /* Component data. */ - writer.uInt(stats.length); - - for (const stat of stats) { - if (stat === null) { - writer.boolean(true); // isNull bit - } else { - writer.boolean(false); // isNull bit - writer.uInt(stat.hash); - writer.float(stat.baseFlat); - } - } - - writer.uInt(modifiers.length); - - for (const modifier of modifiers) { - if (modifier === null) { - writer.boolean(true); // isNull bit - } else { - writer.boolean(false); // isNull bit - writer.uInt(modifier.hash); - writer.float(modifier.value); - writer.boolean(modifier.isMultiplier); - writer.uLong(modifier.time); - } - } - - writer.uInt(indirectStatModifiers.length); - - for (const indirectStatModifier of indirectStatModifiers) { - if (indirectStatModifier === null) { - writer.boolean(true); // isNull bit - } else { - writer.boolean(false); // isNull bit - writer.uInt(indirectStatModifier.hash); - writer.uLong(indirectStatModifier.time); - writer.uInt(indirectStatModifier.modifiers.length); - - for (const modifier of indirectStatModifier.modifiers) { - writer.uInt(modifier.valueOverDurationHash); - writer.float(modifier.baseValue); - writer.uInt(modifier.duration); - writer.uInt(modifier.tick); - } - } - } - - const dataBits = writer.flush(); - - /* Component data length. */ - writer.uInt(dataBits.length); - const sizeBits = writer.flush(); - - /* Return encoded component. */ - writer.binary(hashBits); - writer.binary(sizeBits); - writer.binary(dataBits); - - return writer.flush(); -}; diff --git a/src/components/transcoders/woodcutTree.ts b/src/components/transcoders/woodcutTree.ts deleted file mode 100644 index c58ba31..0000000 --- a/src/components/transcoders/woodcutTree.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { ComponentHash } from '../../ComponentHash'; -import { PresetHash } from '../../PresetHash'; -import { SpeciesHash } from '../../SpeciesHash'; -import { BinaryReader, createBinaryWriter } from '../../utils'; - -export type WoodcutTree = { - presetHash?: 0 | PresetHash; - speciesHash?: SpeciesHash; -}; - -export const decode = (reader: BinaryReader, version: number): WoodcutTree => { - const component: WoodcutTree = {}; - - if (version >= 3) component.presetHash = reader.uInt(); - - if (version >= 3) component.speciesHash = reader.uInt(); - - return component; -}; - -export const encode = ({ presetHash = 0, speciesHash = SpeciesHash.Oak }: WoodcutTree): string => { - const writer = createBinaryWriter(); - - /* Component hash. */ - writer.uInt(ComponentHash.WoodcutTree); - const hashBits = writer.flush(); - - /* Component data. */ - writer.uInt(presetHash); - writer.uInt(speciesHash); - const dataBits = writer.flush(); - - /* Component data length. */ - writer.uInt(dataBits.length); - const sizeBits = writer.flush(); - - /* Return encoded component. */ - writer.binary(hashBits); - writer.binary(sizeBits); - writer.binary(dataBits); - - return writer.flush(); -}; diff --git a/src/constants.ts b/src/constants.ts new file mode 100644 index 0000000..0d49c70 --- /dev/null +++ b/src/constants.ts @@ -0,0 +1,214 @@ +import type { ATTPrefabHash } from './types/ATTPrefabHash.js'; +import type { ATTPrefabName } from './types/ATTPrefabName.js'; + +import { ATTPrefabs } from './types/ATTPrefabs.js'; + +export const attPrefabHashes = Object.values(ATTPrefabs).map(({ hash }) => hash as number); + +export const attPrefabNames = Object.fromEntries( + Object.entries(ATTPrefabs).map(([name, { hash }]) => [hash, name as ATTPrefabName]) +) as Record; + +export const latestDurabilityModuleComponentVersion = 1; +export const latestHeatSourceBaseComponentVersion = 1; +export const latestLiquidContainerComponentVersion = 1; +export const latestPhysicalMaterialPartComponentVersion = 1; +export const latestPopulationSpawnAreaComponentVersion = 2; +export const latestNetworkRigidbodyComponentVersion = 1; +export const latestSentGiftComponentVersion = 1; +export const latestSpawnAreaComponentVersion = 1; + +export const latestSupportedComponentVersions = new Map([ + [7704646, 1], // PopulationPath + [22446553, 2], // Embeddable + [34507654, 1], // CylindricalBoundsSurface + [43510150, 2], // TaxManager + [70871065, 1], // SafePositionSetter + [109805019, 0], // WoodcutTree (duplicate with 1098050191) + [159391088, 1], // ModifiableAdditionalStaticContent + [200292695, 3], // LogicFloatChangeOnBool + [205333986, 1], // Cookable + [237360636, 2], // RopeGrab + [259381630, 1], // Ecosystem + [272188517, 1], // PhysicalMaterialPart + [276353327, 1], // WoodcutPointCollection + [277505782, 2], // Trigger + [309083880, 1], // AreaOfInfluenceReceiver + [320224849, 1], // WheelGrab + [391977879, 2], // Mould + [392234266, 3], + [392344172, 1], // LogicFloatThresholdReceiver + [403040752, 2], // PlayerDetect + [414036426, 0], // KeyItem + [496827038, 1], + [566175523, 1], // LinearPartCloner + [586602603, 1], + [623957243, 1], + [634164392, 5], // LootModule + [654225716, 1], // SpawnBuried + [661497638, 1], // SentGift + [701033518, 1], + [715394364, 2], + [751359624, 1], // GrowthStageComponent + [766675725, 1], // GenericCraftingStation + [775321715, 2], + [788405183, 1], // LevelStatModifier + [830106687, 1], // RespawnOnDestroy + [875684520, 1], // ForestGenerator + [902024186, 1], // Smelter + [910018632, 2], // GameTimeManager + [963907309, 1], // Book + [967932020, 1], // GlobalLogicManager + [986260983, 0], // PopulationFolder`2 + [1001395212, 2], // PlaceItemPuzzleLogic + [1063725326, 1], // WayPointPath + [1081247904, 1], // LogicIntReceiver + [1085701614, 1], // TimeBasedStagedPrefab + [1098050191, 3], // WoodcutTree + [1176706580, 2], // PlaceItemNoDockPuzzleLogic + [1198377566, 1], + [1211178616, 1], // PlayerInteractionManager + [1217391130, 1], // HeatPointCollection + [1228539097, 1], // LogicVector3Receiver + [1233775263, 1], // PlayerProxy + [1257282635, 2], // LogicBoolSender + [1268269765, 1], + [1379877208, 0], // StewContainer + [1390862571, 1], // StageBasedPrefab + [1391720462, 2], // LogicGateReceiver + [1431397437, 2], // PopulationFolder + [1435171891, 0], // ImpactDetectionLogic + [1454441398, 2], // Pickup + [1454955908, 1], // SerializedFullEmptyStatTrigger + [1499506132, 1], // StewManager + [1509838052, 1], // FireLogic + [1556697998, 0], // MultiHandPickup + [1558189723, 1], + [1571096900, 0], // MouldRestrictor + [1587058252, 1], // LockableHinge + [1588536425, 1], // Crank + [1594932294, 0], // Lever + [1624211074, 1], // BasicDynamicPath + [1645673210, 2], // TradeVendor + [1651678475, 1], // RockCluster + [1714180166, 2], // SpawnInCircle + [1753993206, 2], // GlobalPagesManager + [1756836969, 1], + [1776498660, 3], // PositionRestrictor + [1787084913, 4], // CaveLayerManager + [1823429789, 1], // GhostSnapSlotCollection + [1871432223, 1], // DurabilityModule + [1874870249, 2], // MovePickup + [1908922854, 1], // AdditionalStaticContent + [1923918202, 3], // PageInstance + [1931537627, 1], // BasicPopulationFolder + [1934129787, 1], // LogicReset + [1946741389, 0], // PlayerLandmark + [1962842866, 1], // DirectionalBoundsSurface + [1964978567, 1], // LogicSumIntReceiver + [2026743731, 1], // LogicVector3Sender + [2042199192, 0], // TreeDecay + [2069630919, 1], // MRK_ActivationLever + [2081565440, 2], + [2120963769, 1], // LogicFloatSender + [2126500253, 1], // HealthBasedDigable + [2127962967, 1], // NetworkedFloatStream + [2169673426, 1], // MeshPlacement + [2190886200, 1], // SkillShrine + [2213531414, 0], // TwoStepLever + [2241532968, 0], // PaperPageInstance + [2253011220, 1], // LogicIntToBool + [2262399392, 2], // LeaderboardManager + [2272630171, 1], // ForgedPointCollection + [2290978823, 1], // NetworkRigidbody + [2293737711, 1], // OfflinePlayerProgressionHandler + [2314081177, 1], // LandmarkManager + [2363255897, 1], + [2400796504, 1], // SetPiece + [2443660852, 1], // MapBoard + [2450553269, 1], // Recycler + [2495475500, 2], // PlaceItemNoDockFirePuzzleLogic + [2498617949, 1], // RotatePickup + [2563434699, 1], // LogicIntThresholdReceiver + [2563567105, 2], // StatManager + [2576456808, 1], // CurveOutput + [2590537994, 2], // Landmark + [2592242915, 2], // PickupDock + [2610542999, 1], // LogicIntRangeReceiver + [2617495528, 1], // SpawnArea + [2624099526, 1], // Door + [2629079826, 1], // BookRestrictor + [2700376822, 1], // LogicFloatRangeReceiver + [2718386020, 0], // FireStatusRaycastCrafter + [2721336102, 0], // EnergyBasedHeatSource + [2743469720, 0], // PlayerStatManager + [2759613175, 1], + [2801168996, 2], // DrawBridgeRangeLogic + [2807522140, 0], // PickupDecay + [2814234626, 1], // LogicSumFloatReceiver + [2815374842, 1], // RaycastCrafter + [2833060406, 1], + [2880587164, 1], // LogicIntSender + [2882590463, 1], // CookingPot + [2912807649, 3], // PlayerUnlockStation + [2951515968, 1], // PlayerInteractionRestrictor + [2971871217, 1], + [2975913730, 1], // StaticGenerationParent + [2978042925, 1], // DrawBridgeLogic + [2978388169, 1], // PopulationDefinitionManager + [2978415408, 0], // GlobalLiquidContainer + [3008358716, 0], // DockableJoints + [3025846985, 0], // LevelSelectCaveTeleporter + [3070493599, 2], // PopulationSpawnArea + [3082855726, 0], // CapPickup + [3084373371, 1], // CommunalStorage + [3101665521, 1], // RandomSpawnRectangle + [3109677933, 2], // TimerLogic + [3146178080, 1], // TeleportationPoint + [3171294583, 1], + [3188272159, 1], // LogicFloatReceiver + [3202828999, 1], + [3230087383, 1], // OneTimeUpgradeuinteraction + [3236280681, 3], // ChisellingDeck + [3245685963, 1], // LogicFloatReset + [3257374625, 1], // Leaderboard + [3373651539, 1], // BuildupPickup + [3402094521, 1], // GrowerComponent + [3431876266, 1], // InfoBoard + [3445325106, 1], // DiggingImpactor + [3450348902, 1], // Visibility + [3457519710, 2], // Fire + [3538443740, 1], // PositionProvider + [3561515449, 1], // CaveLayerStreamer + [3583462804, 1], // SlidingDoor + [3588929783, 1], // CaveTeleporter + [3598052397, 0], // Chest + [3608460219, 1], // SerializedTimedEvent + [3638500874, 2], // TreeSpawner + [3640332570, 1], // CaveTeleporterManager + [3642863935, 2], // GeneratedLoot + [3665939353, 1], // Fuse + [3674519521, 1], // ModifiableStaticManager + [3684992773, 0], // ChildSyncableCollection`4 + [3704379512, 1], // CheckPoint + [3715151601, 0], // GenerationStarter + [3751351177, 1], // LogicBoolReceiver + [3764204299, 0], // BookPageInstance + [3801256786, 3], // BasicDecay + [3810525047, 0], // LogicValueSender`1 + [3820454400, 4], // RepairBox + [3884278372, 0], // MovingLandmark + [3901697682, 1], // ButtonCounter + [3920618075, 1], // ColoredExplosive + [3932346318, 1], // GlobalPopulationsManager + [4081488368, 1], // WipeManager + [4095875831, 1], // LandmarkDiscoverZone + [4109360768, 2], // HeatSourceBase + [4134534481, 1], // Enchantable + [4144776006, 3], // TimeManager + [4163873252, 0], // GlobalCommunalStorageValuesFile + [4179293747, 1], // LiquidContainer + [4282337604, 1] // SphericalSurface +]); + +export const terminatorHash = 0; diff --git a/src/createPrefab.ts b/src/createPrefab.ts deleted file mode 100644 index d7687d4..0000000 --- a/src/createPrefab.ts +++ /dev/null @@ -1,297 +0,0 @@ -import { Prefab } from './Prefab'; -import { createString } from './createString'; -import { PrefabData } from './decoders'; -import { PhysicalMaterialPartHash } from './PhysicalMaterialPartHash'; -import * as components from './components'; -import { reasonableGifts } from './utils'; - -const VALID_MATERIALS = Object.values(PhysicalMaterialPartHash) - .filter(key => typeof key === 'string') - .sort((a, b) => (a < b ? -1 : 1)); - -const availableSlots = (prefab: TPrefab) => { - const slots = Object.entries(prefab.embedded) - .filter(([key]) => key.startsWith('Slot_')) - .map(([key, entity]) => [key, entity.hash]) as [keyof TPrefab['embedded'], number][]; - - return Object.fromEntries(slots) as Record; -}; - -const getPrefabName = (hash: number) => - Object.entries(Prefab).find(([_, value]) => value.hash === hash)?.[0] ?? ''; - -type PrefabManager = { - name: string; - data: PrefabData; - slots: Record; - setPosition: (x: number, y: number, z: number) => PrefabManager; - setScale: (scale: number) => PrefabManager; - setRotation: (x: number, y: number, z: number, w: number) => PrefabManager; - setKinematic: (isKinematic?: boolean) => PrefabManager; - setServerSleeping: (isServerSleeping?: boolean) => PrefabManager; - setVelocity: (x: number, y: number, z: number) => PrefabManager; - setAngularVelocity: (x: number, y: number, z: number) => PrefabManager; - setMaterial: (material: keyof typeof PhysicalMaterialPartHash) => PrefabManager; - setIntegrity: (integrity: number) => PrefabManager; - setServings: (servings: number) => PrefabManager; - setOnFire: (isLit?: boolean) => PrefabManager; - setGiftBoxLabel: (label: string) => PrefabManager; - addGift: ( - gift: PrefabManager - ) => PrefabManager; - useSlot: ( - slotName: TEmbeddedEntity, - childPrefab: PrefabManager - ) => PrefabManager; - toString: () => string; - print: () => void; -}; - -export const createPrefab = ( - prefab: TPrefab -): PrefabManager => ({ - name: getPrefabName(prefab.hash), - - data: { - prefabObject: { hash: prefab.hash }, - components: {}, - embeddedEntities: {}, - childPrefabs: [] - }, - - slots: availableSlots(prefab), - - setPosition(x, y, z) { - if (typeof x === 'undefined' || typeof y === 'undefined' || typeof z === 'undefined') { - throw new Error(`setPosition(x, y, z) called with invalid arguments.`); - } - - const position = { x, y, z }; - - this.data.prefabObject.position = position; - this.data.components!.NetworkRigidbody = { - ...this.data.components!.NetworkRigidbody, - position - }; - - return this; - }, - - setRotation(x, y, z, w) { - if (typeof x === 'undefined' || typeof y === 'undefined' || typeof z === 'undefined' || typeof w === 'undefined') { - throw new Error(`setRotation(x, y, z, w) called with invalid arguments.`); - } - - const rotation = { x, y, z, w }; - - this.data.prefabObject.rotation = rotation; - this.data.components!.NetworkRigidbody = { - ...this.data.components!.NetworkRigidbody, - rotation - }; - - return this; - }, - - setScale(scale) { - if (typeof scale === 'undefined') { - throw new Error(`setScale(scale) called with invalid arguments.`); - } - - this.data.prefabObject.scale = scale; - - return this; - }, - - setKinematic(isKinematic = true) { - this.data.components!.NetworkRigidbody = { - ...this.data.components!.NetworkRigidbody, - isKinematic - }; - - return this; - }, - - setServerSleeping(isServerSleeping = true) { - this.data.components!.NetworkRigidbody = { - ...this.data.components!.NetworkRigidbody, - isServerSleeping - }; - - return this; - }, - - setVelocity(x, y, z) { - if (typeof x === 'undefined' || typeof y === 'undefined' || typeof z === 'undefined') { - throw new Error(`setVelocity(x, y, z) called with invalid arguments.`); - } - - const velocity = { x, y, z }; - - this.data.components!.NetworkRigidbody = { - ...this.data.components!.NetworkRigidbody, - velocity - }; - - return this; - }, - - setAngularVelocity(x, y, z) { - if (typeof x === 'undefined' || typeof y === 'undefined' || typeof z === 'undefined') { - throw new Error(`setAngularVelocity(x, y, z) called with invalid arguments.`); - } - - const angularVelocity = { x, y, z }; - - this.data.components!.NetworkRigidbody = { - ...this.data.components!.NetworkRigidbody, - angularVelocity - }; - - return this; - }, - - setMaterial(material) { - if (typeof material === 'undefined') { - throw new Error(`setMaterial(material) called with invalid arguments.`); - } - - if (!VALID_MATERIALS.includes(material)) { - throw new Error( - `'${material}' is not a valid material on '${this.name}'. ${`Valid materials: ${VALID_MATERIALS.join(', ')}`}` - ); - } - - this.data.components = { - ...this.data.components, - PhysicalMaterialPart: { - materialHash: PhysicalMaterialPartHash[material] - } - }; - - return this; - }, - - setIntegrity(integrity) { - if (typeof integrity === 'undefined') { - throw new Error(`setIntegrity(integrity) called with invalid arguments.`); - } - - this.data.components = { - ...this.data.components, - DurabilityModule: { integrity } - }; - - return this; - }, - - setServings(servings) { - if (typeof servings === 'undefined') { - throw new Error(`setServings(servings) called with invalid arguments.`); - } - - this.data.components!.LiquidContainer = { - ...this.data.components!.LiquidContainer, - contentLevel: Math.ceil(servings) - }; - - return this; - }, - - setOnFire(isLit = true) { - this.data.embeddedEntities!.Fire = { - ...this.data.embeddedEntities!.Fire, - isAlive: isLit, - components: { - ...this.data.embeddedEntities!.Fire?.components, - HeatSourceBase: { - ...this.data.embeddedEntities!.Fire?.components?.HeatSourceBase, - isLit - } - } - }; - - return this; - }, - - setGiftBoxLabel(label) { - this.data.components = { - ...this.data.components, - SentGift: { - ...this.data.components!.SentGift, - senderName: label - } - }; - - return this; - }, - - addGift(giftPrefab) { - if (!reasonableGifts.includes(giftPrefab.data.prefabObject.hash)) { - throw new Error('No gifts for naughty people.'); - } - - const string = createString(giftPrefab.data); - - const [dataString, versionsString] = string.split('|'); - const [hash, messageSizeInBytes, ...data] = dataString.split(',').map(Number); - const [_, ...chunkVersioning] = versionsString.split(',').map(Number); - - this.data.components = { - ...this.data.components, - SentGift: { - ...this.data.components!.SentGift, - gifts: [ - ...((this.data.components!.SentGift as components.SentGift | undefined)?.gifts ?? []), - { - data, - messageSizeInBytes, - hash, - chunkVersioning - } - ] - } - }; - - return this; - }, - - useSlot(slotName, childPrefab) { - if (typeof slotName === 'undefined' || typeof childPrefab === 'undefined') { - throw new Error(`useSlot(slot, prefab) called with invalid arguments.`); - } - - const slotHash = (this.slots?.[slotName] ?? 0) as number; - const validHashes = Object.values(this.slots); - - if (slotHash === 0 || !validHashes.includes(slotHash)) { - throw new Error( - `'${String(slotName)}' is not a valid slot on '${this.name}'. ${ - validHashes.length - ? `Valid slot(s): ${Object.keys(this.slots).join(', ')}` - : 'This prefab has no available slots.' - }` - ); - } - - this.data.childPrefabs = [ - ...this.data.childPrefabs!.filter(({ parentHash }) => parentHash !== slotHash), - { - parentHash: slotHash, - prefab: { ...childPrefab.data } - } - ]; - - return this; - }, - - toString() { - return createString(this.data); - }, - - print() { - const string = this.toString(); - - return console.log(string); - } -}); diff --git a/src/createString.ts b/src/createString.ts deleted file mode 100644 index d7e7eb1..0000000 --- a/src/createString.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { PrefabData } from './decoders'; -import { binaryToUIntArray } from './utils'; -import { encodePrefab } from './encoders'; -import { getComponentVersions } from './getComponentVersions'; - -export const createString = (prefab: PrefabData): string => { - const hash = prefab.prefabObject.hash; - - /* Encode the prefab. */ - const binary = encodePrefab(prefab); - - /* Pad bits with trailing zeroes to make it % 32. */ - const missingBits = binary.length + (32 - (binary.length % 32 === 0 ? 32 : binary.length % 32)); - const paddedBinary = binary.padEnd(missingBits, '0'); - - /* Calculate byte size of padded binary. */ - const bytes = paddedBinary.length / 8; - - /* Convert binary to array of UInts. */ - const uInts = binaryToUIntArray(paddedBinary); - - /* Construct the UInts string. */ - const uIntString = [hash, bytes, ...uInts].join(','); - - /* Construct the versions string. */ - const versionString = getComponentVersions(prefab); - - /* Return spawn string. */ - const strings = [uIntString, versionString].filter(Boolean); - return `${strings.join(',|')},`; -}; diff --git a/src/decodeString.ts b/src/decodeString.ts deleted file mode 100644 index a9aa52a..0000000 --- a/src/decodeString.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { parseVersionString, uIntToBinary, createBinaryReader } from './utils'; -import { decodePrefab, PrefabData } from './decoders'; - -export type DecodedString = { - hash: number; - size: number; - prefab: PrefabData; -}; - -/** - * Break down a raw spawn string into: - * - prefab object; - * - components; - * - child entities; and - * - child prefabs. - */ -export const decodeString = (rawString: string): DecodedString => { - /* Get the UInts and component versions from the raw spawn string. */ - const [uIntString, versionString] = rawString.split('|'); - const uInts = uIntString.split(',').filter(Boolean); - const versions = parseVersionString(versionString); - - /* Remove the first two UInts which do not count towards the string's size. */ - const hash = Number(uInts.shift() ?? 0); - const size = 8 * Number(uInts.shift() ?? 0); - - /* Convert remaining UInts to binary. */ - const binary = uInts.reduce((bits, uInt) => `${bits}${uIntToBinary(Number(uInt))}`, ''); - - /* Create binary reader. */ - const reader = createBinaryReader(binary); - - const prefab = decodePrefab(reader, versions); - - return { - hash, - size, - prefab - }; -}; diff --git a/src/decoders/decodeChildPrefabs.ts b/src/decoders/decodeChildPrefabs.ts deleted file mode 100644 index bc4948e..0000000 --- a/src/decoders/decodeChildPrefabs.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { BinaryReader, VersionMap } from '../utils'; -import { decodePrefab, PrefabData } from './decodePrefab'; - -export type ChildPrefab = { - parentHash: number; - prefab: PrefabData; -}; - -export type ChildPrefabs = ChildPrefab[]; - -export const decodeChildPrefabs = (reader: BinaryReader, versions: VersionMap): ChildPrefab[] => { - const childPrefabs: ChildPrefab[] = []; - - /* Continue looping until we find a false exists bit. */ - while (true) { - /* Get the exists bit. */ - const exists = reader.boolean(); - - /* Break if we reached the end of the child prefabs loop. */ - if (!exists) break; - - /* Get the parent entity hash. */ - const parentHash = reader.uInt(); - - /* Get the child prefab. */ - const prefab = decodePrefab(reader, versions); - - /* Save entity. */ - childPrefabs.push({ parentHash, prefab }); - } - - return childPrefabs; -}; diff --git a/src/decoders/decodeComponents.ts b/src/decoders/decodeComponents.ts deleted file mode 100644 index 9d32a22..0000000 --- a/src/decoders/decodeComponents.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { transcoders, Component, ComponentName, UnknownComponent, ComponentVersion } from '../components'; -import { ComponentHash } from '../ComponentHash'; -import { BinaryReader, VersionMap } from '../utils'; - -export type Components = { - [key in ComponentName | 'Unknown']?: Component; -}; - -export const decodeComponents = (reader: BinaryReader, versions: VersionMap): Components => { - const components: Components = { - Unknown: [] - }; - - /* Continue looping until we find a zero hash. */ - while (true) { - /* Get the component hash. */ - const hash = reader.uInt(); - - /* Break if we reached the end of the components loop. */ - if (hash === 0) break; - - /* Get the component's data length. */ - const size = reader.uInt(); - - /* Get the component's name. */ - const componentName = ComponentHash[hash] as ComponentName | undefined; - - /* Save the component's data. */ - if (componentName && transcoders[componentName]) { - let version = versions[hash]; - - if (!version) { - if (ComponentVersion.has(hash)) { - version = ComponentVersion.get(hash)!; - console.warn( - `String does not contain version info for the '${componentName}' component. Assuming latest supported version (v${version}).` - ); - } else { - throw new Error(`Cannot decode unsupported version of '${componentName}' component.`); - } - } - - components[componentName] = transcoders[componentName].decode(reader, version); - } else { - (components.Unknown as UnknownComponent[]).push({ hash, data: reader.binary(size) }); - } - } - - return components; -}; diff --git a/src/decoders/decodeEmbeddedEntities.ts b/src/decoders/decodeEmbeddedEntities.ts deleted file mode 100644 index 6d80ac9..0000000 --- a/src/decoders/decodeEmbeddedEntities.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { EmbeddedEntityHash } from '../EmbeddedEntityHash'; -import { BinaryReader, VersionMap } from '../utils'; -import { decodeComponents, Components } from './decodeComponents'; -import { Fire } from '../embeddedEntities'; - -export type UnknownEmbeddedEntity = { - hash: number; - isAlive?: boolean; - components?: Components; -}; - -export type KnownEmbeddedEntity = Fire; - -export type EmbeddedEntities = { - Unknown?: UnknownEmbeddedEntity[]; - Fire?: Fire; -}; - -export const decodeEmbeddedEntities = (reader: BinaryReader, versions: VersionMap): EmbeddedEntities => { - const embeddedEntities: EmbeddedEntities = { - Unknown: [] - }; - - /* Continue looping until we find a zero hash. */ - while (true) { - /* Get the entity hash. */ - const hash = reader.uInt(); - - /* Break if we reached the end of the entities loop. */ - if (hash === 0) break; - - /* Get entity name. */ - const embeddedEntityName = (EmbeddedEntityHash[hash] ?? 'Unknown') as keyof EmbeddedEntities; - - /* Read the entity's data length. */ - reader.uInt(); - - /* Check if entity is still alive. */ - const isAlive = reader.boolean(); - - /* Get the entity's components. */ - const components = decodeComponents(reader, versions); - - /* Save entity. */ - if (embeddedEntityName === 'Unknown') { - (embeddedEntities.Unknown as UnknownEmbeddedEntity[]).push({ hash, isAlive, components }); - } else { - (embeddedEntities[embeddedEntityName] as KnownEmbeddedEntity) = { isAlive, components }; - } - } - - return embeddedEntities; -}; diff --git a/src/decoders/decodePrefab.ts b/src/decoders/decodePrefab.ts deleted file mode 100644 index 01a51e2..0000000 --- a/src/decoders/decodePrefab.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { BinaryReader, VersionMap } from '../utils'; -import { decodePrefabObject, PrefabObject } from './decodePrefabObject'; -import { decodeComponents, Components } from './decodeComponents'; -import { decodeEmbeddedEntities, EmbeddedEntities } from './decodeEmbeddedEntities'; -import { decodeChildPrefabs, ChildPrefabs } from './decodeChildPrefabs'; - -export type PrefabData = { - prefabObject: PrefabObject; - components?: Components; - embeddedEntities?: EmbeddedEntities; - childPrefabs?: ChildPrefabs; -}; - -export const decodePrefab = (reader: BinaryReader, versions: VersionMap): PrefabData => { - const prefabObject = decodePrefabObject(reader); - const components = decodeComponents(reader, versions); - const embeddedEntities = decodeEmbeddedEntities(reader, versions); - const childPrefabs = decodeChildPrefabs(reader, versions); - - return { - prefabObject, - components, - embeddedEntities, - childPrefabs - }; -}; diff --git a/src/decoders/decodePrefabObject.ts b/src/decoders/decodePrefabObject.ts deleted file mode 100644 index 3f8274f..0000000 --- a/src/decoders/decodePrefabObject.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { BinaryReader } from '../utils'; - -export type PrefabObject = { - hash: number; - position?: { - x: number; - y: number; - z: number; - }; - rotation?: { - x: number; - y: number; - z: number; - w: number; - }; - scale?: number; -}; - -export const decodePrefabObject = (reader: BinaryReader): PrefabObject => ({ - hash: reader.uInt(), - position: { - x: reader.float(), - y: reader.float(), - z: reader.float() - }, - rotation: { - x: reader.float(), - y: reader.float(), - z: reader.float(), - w: reader.float() - }, - scale: reader.float() -}); diff --git a/src/decoders/index.ts b/src/decoders/index.ts deleted file mode 100644 index cc0e2f1..0000000 --- a/src/decoders/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { decodeComponents } from './decodeComponents'; -export { decodePrefab, PrefabData } from './decodePrefab'; -export { PrefabObject } from './decodePrefabObject'; -export { Components } from './decodeComponents'; -export { EmbeddedEntities, KnownEmbeddedEntity, UnknownEmbeddedEntity } from './decodeEmbeddedEntities'; -export { ChildPrefab, ChildPrefabs } from './decodeChildPrefabs'; diff --git a/src/embeddedEntities/fire.ts b/src/embeddedEntities/fire.ts deleted file mode 100644 index 97aadd6..0000000 --- a/src/embeddedEntities/fire.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Component } from '../components'; - -export type Fire = { - isAlive?: boolean; - components?: { - Fire?: Component; - HeatSourceBase?: Component; - HeatSourcePointCollection?: Component; - Unknown?: Component; - }; -}; diff --git a/src/embeddedEntities/index.ts b/src/embeddedEntities/index.ts deleted file mode 100644 index da2885c..0000000 --- a/src/embeddedEntities/index.ts +++ /dev/null @@ -1 +0,0 @@ -export type { Fire } from './fire'; diff --git a/src/encoders/encodeChildPrefabs.ts b/src/encoders/encodeChildPrefabs.ts deleted file mode 100644 index 94c0ad3..0000000 --- a/src/encoders/encodeChildPrefabs.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ChildPrefabs } from '../decoders'; -import { createBinaryWriter } from '../utils/createBinaryWriter'; -import { encodePrefab } from '.'; - -export const encodeChildPrefabs = (childPrefabs: ChildPrefabs = []): string => { - const writer = createBinaryWriter(); - - for (const childPrefab of childPrefabs) { - writer.boolean(true); // exists bit - writer.uInt(childPrefab.parentHash); - - const childPrefabBits = encodePrefab(childPrefab.prefab); - writer.binary(childPrefabBits); - } - - writer.boolean(false); // exists bit (terminator) - - return writer.flush(); -}; diff --git a/src/encoders/encodeComponents.ts b/src/encoders/encodeComponents.ts deleted file mode 100644 index 3e578b0..0000000 --- a/src/encoders/encodeComponents.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Components } from '../decoders'; -import { transcoders, KnownComponent, UnknownComponent, ComponentName } from '../components'; -import { createBinaryWriter } from '../utils/createBinaryWriter'; - -const terminator = '0'.repeat(32); - -export const encodeComponents = (components: Components = {}): string => { - const writer = createBinaryWriter(); - - for (const [key, value] of Object.entries(components)) { - const componentName = key as ComponentName | 'Unknown'; - - if (componentName === 'Unknown') { - const unknownComponents = value as UnknownComponent[]; - - for (const { hash, data } of unknownComponents) { - writer.uInt(hash); - writer.uInt(data.length); - writer.binary(data); - } - } else { - try { - const knownComponent = value as KnownComponent; - const componentBits = transcoders[componentName].encode(knownComponent); - writer.binary(componentBits); - } catch (error) { - throw Error(`Cannot encode unsupported component '${componentName}'`); - } - } - } - - const binary = writer.flush(); - - return `${binary}${terminator}`; -}; diff --git a/src/encoders/encodeEmbeddedEntities.ts b/src/encoders/encodeEmbeddedEntities.ts deleted file mode 100644 index f9ceb80..0000000 --- a/src/encoders/encodeEmbeddedEntities.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { EmbeddedEntities, KnownEmbeddedEntity, UnknownEmbeddedEntity } from '../decoders'; -import { EmbeddedEntityHash } from '../EmbeddedEntityHash'; -import { createBinaryWriter } from '../utils/createBinaryWriter'; -import { encodeComponents } from './encodeComponents'; - -const terminator = '0'.repeat(32); - -export const encodeEmbeddedEntities = (entities: EmbeddedEntities = {}): string => { - const writer = createBinaryWriter(); - - for (const [key, value] of Object.entries(entities)) { - const embeddedEntityName = key as keyof EmbeddedEntities; - - if (embeddedEntityName === 'Unknown') { - const unknownEmbeddedEntities = value as UnknownEmbeddedEntity[]; - - for (const { hash = 0, isAlive = true, components = {} } of unknownEmbeddedEntities) { - const componentsBits = encodeComponents(components); - - writer.uInt(hash); - writer.uInt(1 + componentsBits.length); - writer.boolean(isAlive); - writer.binary(componentsBits); - } - } else { - const { isAlive = true, components = {} } = value as KnownEmbeddedEntity; - const componentsBits = encodeComponents(components); - - writer.uInt(EmbeddedEntityHash[embeddedEntityName as keyof typeof EmbeddedEntityHash]); - writer.uInt(1 + componentsBits.length); - writer.boolean(isAlive); - writer.binary(componentsBits); - } - } - - const binary = writer.flush(); - - return `${binary}${terminator}`; -}; diff --git a/src/encoders/encodePrefab.ts b/src/encoders/encodePrefab.ts deleted file mode 100644 index 1212b1f..0000000 --- a/src/encoders/encodePrefab.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { PrefabData } from '../decoders'; -import { createBinaryWriter } from '../utils/createBinaryWriter'; -import { encodePrefabObject, encodeComponents, encodeEmbeddedEntities, encodeChildPrefabs } from '.'; - -export const encodePrefab = (prefab: PrefabData): string => { - const writer = createBinaryWriter(); - - /* Create prefab object. */ - const prefabObjectBits = encodePrefabObject(prefab.prefabObject); - writer.binary(prefabObjectBits); - - /* Create components. */ - const componentsBits = encodeComponents(prefab.components); - writer.binary(componentsBits); - - /* Create embedded entities. */ - const embeddedEntitiesBits = encodeEmbeddedEntities(prefab.embeddedEntities); - writer.binary(embeddedEntitiesBits); - - /* Create child prefabs. */ - const childPrefabsBits = encodeChildPrefabs(prefab.childPrefabs); - writer.binary(childPrefabsBits); - - return writer.flush(); -}; diff --git a/src/encoders/encodePrefabObject.ts b/src/encoders/encodePrefabObject.ts deleted file mode 100644 index cfa2092..0000000 --- a/src/encoders/encodePrefabObject.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { PrefabObject } from '../decoders'; -import { createBinaryWriter } from '../utils'; - -export const encodePrefabObject = ({ - hash, - position = { x: 0, y: 0, z: 0 }, - rotation = { x: 0, y: 0, z: 0, w: 1 }, - scale = 1 -}: PrefabObject): string => { - const writer = createBinaryWriter(); - - /* Prefab object hash. */ - writer.uInt(hash); - - /* Prefab object data. */ - writer.float(position.x); - writer.float(position.y); - writer.float(position.z); - writer.float(rotation.x); - writer.float(rotation.y); - writer.float(rotation.z); - writer.float(rotation.w); - writer.float(scale); - - return writer.flush(); -}; diff --git a/src/encoders/index.ts b/src/encoders/index.ts deleted file mode 100644 index 6e0e91f..0000000 --- a/src/encoders/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { encodePrefab } from './encodePrefab'; -export { encodePrefabObject } from './encodePrefabObject'; -export { encodeComponents } from './encodeComponents'; -export { encodeEmbeddedEntities } from './encodeEmbeddedEntities'; -export { encodeChildPrefabs } from './encodeChildPrefabs'; diff --git a/src/getComponentVersions.ts b/src/getComponentVersions.ts deleted file mode 100644 index 4180ec1..0000000 --- a/src/getComponentVersions.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { Components, KnownEmbeddedEntity, PrefabData, UnknownEmbeddedEntity } from './decoders'; -import { ComponentName, UnknownComponent, ComponentVersion } from './components'; -import { ComponentHash } from './ComponentHash'; - -type VersionPair = [number, number]; - -const getComponentVersionPairs = (components: Components = {}) => { - const versionPairs: VersionPair[] = []; - - for (const [key, value] of Object.entries(components)) { - const componentName = key as ComponentName | 'Unknown'; - - if (componentName === 'Unknown') { - const unknownComponents = value as UnknownComponent[]; - versionPairs.push( - ...unknownComponents.map( - component => [component.hash, ComponentVersion.get(component.hash)] as [number, number] - ) - ); - } else { - const componentHash = ComponentHash[componentName]; - const componentVersion = ComponentVersion.get(componentHash); - versionPairs.push([componentHash, componentVersion ?? 1]); - } - } - - return versionPairs; -}; - -const getPrefabVersionPairs = (prefab: PrefabData): VersionPair[] => { - const versionPairs: VersionPair[] = []; - - if (prefab.components) { - versionPairs.push(...getComponentVersionPairs(prefab.components)); - } - - if (prefab.embeddedEntities) { - for (const [key, value] of Object.entries(prefab.embeddedEntities)) { - const embeddedEntityName = key as keyof KnownEmbeddedEntity | 'Unknown'; - - if (embeddedEntityName === 'Unknown') { - const unknownEmbeddedEntities = value as UnknownEmbeddedEntity[]; - - for (const embeddedEntity of unknownEmbeddedEntities) { - versionPairs.push(...getComponentVersionPairs(embeddedEntity.components)); - } - } else { - const knownEmbeddedEntity = value as KnownEmbeddedEntity; - - versionPairs.push(...getComponentVersionPairs(knownEmbeddedEntity.components)); - } - } - } - - if (prefab.childPrefabs?.length) { - for (const childPrefab of prefab.childPrefabs) { - versionPairs.push(...getPrefabVersionPairs(childPrefab.prefab)); - } - } - - return versionPairs; -}; - -export const getComponentVersions = (prefab: PrefabData): string => { - const versionPairs = getPrefabVersionPairs(prefab); - const uniquePairs = versionPairs.filter( - ([hash], index) => versionPairs.findIndex(pair => pair[0] === hash) === index - ); - - const versions = uniquePairs.reduce((sum, [hash, version]) => `${sum},${hash},${version}`, ''); - - return `${uniquePairs.length}${versions}`; -}; diff --git a/src/index.ts b/src/index.ts index b846849..4e04ea9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,64 +1,110 @@ -/** - * PREFABS - */ -export { Prefab } from './Prefab'; +/* Types */ +export type { BinaryDataOptions, UnpackFloatOptions } from './BinaryData.js'; +export type { EntityProps } from './Entity.js'; +export type { PrefabProps } from './Prefab.js'; +export type { BasicDecayComponentProps } from './components/BasicDecayComponent.js'; +export type { ComponentProps } from './components/Component.js'; +export type { DurabilityModuleComponentProps } from './components/DurabilityModuleComponent.js'; +export type { FireComponentProps } from './components/FireComponent.js'; +export type { FuseComponentProps } from './components/FuseComponent.js'; +export type { HeatSourceBaseComponentProps } from './components/HeatSourceBaseComponent.js'; +export type { LiquidContainerComponentProps } from './components/LiquidContainerComponent.js'; +export type { LogicBoolReceiverComponentProps } from './components/LogicBoolReceiverComponent.js'; +export type { LogicBoolSenderComponentProps } from './components/LogicBoolSenderComponent.js'; +export type { LogicFloatReceiverComponentProps } from './components/LogicFloatReceiverComponent.js'; +export type { LogicFloatSenderComponentProps } from './components/LogicFloatSenderComponent.js'; +export type { LogicGateReceiverComponentProps } from './components/LogicGateReceiverComponent.js'; +export type { LogicIntReceiverComponentProps } from './components/LogicIntReceiverComponent.js'; +export type { LogicIntSenderComponentProps } from './components/LogicIntSenderComponent.js'; +export type { LogicVector3ReceiverComponentProps } from './components/LogicVector3ReceiverComponent.js'; +export type { LogicVector3SenderComponentProps } from './components/LogicVector3SenderComponent.js'; +export type { NetworkRigidbodyComponentProps } from './components/NetworkRigidbodyComponent.js'; +export type { PhysicalMaterialPartComponentProps } from './components/PhysicalMaterialPartComponent.js'; +export type { PickupComponentProps } from './components/PickupComponent.js'; +export type { PickupDockComponentProps } from './components/PickupDockComponent.js'; +export type { PopulationSpawnAreaComponentProps } from './components/PopulationSpawnAreaComponent.js'; +export type { SentGiftComponentProps } from './components/SentGiftComponent.js'; +export type { SpawnAreaComponentProps } from './components/SpawnAreaComponent.js'; +export type { StatManagerComponentProps } from './components/StatManagerComponent.js'; +export type { UnsupportedComponentProps } from './components/UnsupportedComponent.js'; +export type { WoodcutTreeComponentProps } from './components/WoodcutTreeComponent.js'; +export type { AngularVelocity } from './types/AngularVelocity.js'; +export type { ATTPrefabHash } from './types/ATTPrefabHash.js'; +export type { ATTPrefabName } from './types/ATTPrefabName.js'; +export type { BinaryString } from './types/BinaryString.js'; +export type { PopulationDefinitionName } from './types/PopulationDefinitionName.js'; +export type { Position } from './types/Position.js'; +export type { PrefabChild } from './types/PrefabChild.js'; +export type { PrefabComponents } from './types/PrefabComponents.js'; +export type { PrefabEntities } from './types/PrefabEntities.js'; +export type { Rotation } from './types/Rotation.js'; +export type { SaveString } from './types/SaveString.js'; +export type { SetSpawnAreaProps } from './types/SetSpawnAreaProps.js'; +export type { SupportedComponent } from './types/SupportedComponent.js'; +export type { SupportedPrefabComponents } from './types/SupportedPrefabComponents.js'; +export type { UnknownPrefabComponents } from './types/UnknownPrefabComponents.js'; +export type { UnsupportedPrefabComponents } from './types/UnsupportedPrefabComponents.js'; +export type { Velocity } from './types/Velocity.js'; -/** - * COMPONENTS - */ -export type { - BasicDecay, - DurabilityModule, - HeatSourceBase, - LiquidContainer, - NetworkRigidbody, - PhysicalMaterialPart, - Pickup, - PickupDock, - PopulationSpawnArea, - SpawnArea, - StatManager, - WoodcutTree -} from './components'; +/* Enums */ +export { ComponentHash } from './types/ComponentHash.js'; +export { LogicOperator } from './types/LogicOperator.js'; +export { PhysicalMaterialPartHash } from './types/PhysicalMaterialPartHash.js'; +export { PopulationDefinitionHash } from './types/PopulationDefinitionHash.js'; +export { PresetHash } from './types/PresetHash.js'; +export { SpeciesHash } from './types/SpeciesHash.js'; -/** - * EMBEDDED ENTITIES - */ -export * from './embeddedEntities'; +/* Binary classes */ +export { BinaryData } from './BinaryData.js'; +export { BinaryReader } from './BinaryReader.js'; +export { BinaryWriter } from './BinaryWriter.js'; -/** - * OBJECT SHAPES - */ -export type { DecodedString } from './decodeString'; -export type { - PrefabData, - PrefabObject, - Components, - EmbeddedEntities, - KnownEmbeddedEntity, - UnknownEmbeddedEntity, - ChildPrefab -} from './decoders'; -export type { Component, KnownComponent, UnknownComponent } from './components'; +/* Prefabs */ +export { Prefab } from './Prefab.js'; +export { ATTPrefabs } from './types/ATTPrefabs.js'; -/** - * HASHES - */ -export { ComponentHash } from './ComponentHash'; -export { EmbeddedEntityHash } from './EmbeddedEntityHash'; -export { PhysicalMaterialPartHash } from './PhysicalMaterialPartHash'; -export { PopulationDefinitionHash } from './PopulationDefinitionHash'; -export { PresetHash } from './PresetHash'; -export { SpeciesHash } from './SpeciesHash'; +/* Components */ +export { BasicDecayComponent } from './components/BasicDecayComponent.js'; +export { Component } from './components/Component.js'; +export { DoorComponent } from './components/DoorComponent.js'; +export { DurabilityModuleComponent } from './components/DurabilityModuleComponent.js'; +export { FireComponent } from './components/FireComponent.js'; +export { FuseComponent } from './components/FuseComponent.js'; +export { HeatSourceBaseComponent } from './components/HeatSourceBaseComponent.js'; +export { LiquidContainerComponent } from './components/LiquidContainerComponent.js'; +export { LogicBoolReceiverComponent } from './components/LogicBoolReceiverComponent.js'; +export { LogicBoolSenderComponent } from './components/LogicBoolSenderComponent.js'; +export { LogicFloatReceiverComponent } from './components/LogicFloatReceiverComponent.js'; +export { LogicFloatSenderComponent } from './components/LogicFloatSenderComponent.js'; +export { LogicGateReceiverComponent } from './components/LogicGateReceiverComponent.js'; +export { LogicIntReceiverComponent } from './components/LogicIntReceiverComponent.js'; +export { LogicIntSenderComponent } from './components/LogicIntSenderComponent.js'; +export { LogicVector3ReceiverComponent } from './components/LogicVector3ReceiverComponent.js'; +export { LogicVector3SenderComponent } from './components/LogicVector3SenderComponent.js'; +export { NetworkRigidbodyComponent } from './components/NetworkRigidbodyComponent.js'; +export { PhysicalMaterialPartComponent } from './components/PhysicalMaterialPartComponent.js'; +export { PickupComponent } from './components/PickupComponent.js'; +export { PickupDockComponent } from './components/PickupDockComponent.js'; +export { PopulationSpawnAreaComponent } from './components/PopulationSpawnAreaComponent.js'; +export { SentGiftComponent } from './components/SentGiftComponent.js'; +export { SlidingDoorComponent } from './components/SlidingDoorComponent.js'; +export { SpawnAreaComponent } from './components/SpawnAreaComponent.js'; +export { StatManagerComponent } from './components/StatManagerComponent.js'; +export { UnsupportedComponent } from './components/UnsupportedComponent.js'; +export { WoodcutTreeComponent } from './components/WoodcutTreeComponent.js'; -/** - * UTILITIES - */ -export * from './utils'; +/* Entities */ +export { Entity } from './Entity.js'; -/** - * ATT STRING TRANSCODER - */ -export { createPrefab } from './createPrefab'; -export { createString } from './createString'; -export { decodeString } from './decodeString'; +/* Utilities */ +export { isATTPrefabHash } from './utils/isATTPrefabHash.js'; +export { isATTPrefabName } from './utils/isATTPrefabName.js'; +export { isSavableComponent } from './utils/isSavableComponent.js'; +export { isUnknownComponent } from './utils/isUnknownComponent.js'; +export { readChildren } from './utils/readChildren.js'; +export { readComponent } from './utils/readComponent.js'; +export { readComponents } from './utils/readComponents.js'; +export { readEntities } from './utils/readEntities.js'; +export { writeChildren } from './utils/writeChildren.js'; +export { writeComponents } from './utils/writeComponents.js'; +export { writeEntities } from './utils/writeEntities.js'; diff --git a/src/supportedComponents.ts b/src/supportedComponents.ts new file mode 100644 index 0000000..67dcd48 --- /dev/null +++ b/src/supportedComponents.ts @@ -0,0 +1,57 @@ +import type { SupportedComponent } from './types/SupportedComponent.js'; + +import { BasicDecayComponent } from './components/BasicDecayComponent.js'; +import { DoorComponent } from './components/DoorComponent.js'; +import { DurabilityModuleComponent } from './components/DurabilityModuleComponent.js'; +import { FireComponent } from './components/FireComponent.js'; +import { FuseComponent } from './components/FuseComponent.js'; +import { HeatSourceBaseComponent } from './components/HeatSourceBaseComponent.js'; +import { LiquidContainerComponent } from './components/LiquidContainerComponent.js'; +import { LogicBoolReceiverComponent } from './components/LogicBoolReceiverComponent.js'; +import { LogicBoolSenderComponent } from './components/LogicBoolSenderComponent.js'; +import { LogicFloatReceiverComponent } from './components/LogicFloatReceiverComponent.js'; +import { LogicFloatSenderComponent } from './components/LogicFloatSenderComponent.js'; +import { LogicGateReceiverComponent } from './components/LogicGateReceiverComponent.js'; +import { LogicIntReceiverComponent } from './components/LogicIntReceiverComponent.js'; +import { LogicIntSenderComponent } from './components/LogicIntSenderComponent.js'; +import { LogicVector3ReceiverComponent } from './components/LogicVector3ReceiverComponent.js'; +import { LogicVector3SenderComponent } from './components/LogicVector3SenderComponent.js'; +import { NetworkRigidbodyComponent } from './components/NetworkRigidbodyComponent.js'; +import { PhysicalMaterialPartComponent } from './components/PhysicalMaterialPartComponent.js'; +import { PickupComponent } from './components/PickupComponent.js'; +import { PickupDockComponent } from './components/PickupDockComponent.js'; +import { PopulationSpawnAreaComponent } from './components/PopulationSpawnAreaComponent.js'; +import { SentGiftComponent } from './components/SentGiftComponent.js'; +import { SlidingDoorComponent } from './components/SlidingDoorComponent.js'; +import { SpawnAreaComponent } from './components/SpawnAreaComponent.js'; +import { StatManagerComponent } from './components/StatManagerComponent.js'; +import { WoodcutTreeComponent } from './components/WoodcutTreeComponent.js'; + +export const supportedComponents: Record = { + BasicDecay: BasicDecayComponent, + Door: DoorComponent, + DurabilityModule: DurabilityModuleComponent, + Fire: FireComponent, + Fuse: FuseComponent, + HeatSourceBase: HeatSourceBaseComponent, + LiquidContainer: LiquidContainerComponent, + LogicBoolReceiver: LogicBoolReceiverComponent, + LogicBoolSender: LogicBoolSenderComponent, + LogicFloatReceiver: LogicFloatReceiverComponent, + LogicFloatSender: LogicFloatSenderComponent, + LogicGateReceiver: LogicGateReceiverComponent, + LogicIntReceiver: LogicIntReceiverComponent, + LogicIntSender: LogicIntSenderComponent, + LogicVector3Receiver: LogicVector3ReceiverComponent, + LogicVector3Sender: LogicVector3SenderComponent, + NetworkRigidbody: NetworkRigidbodyComponent, + PhysicalMaterialPart: PhysicalMaterialPartComponent, + Pickup: PickupComponent, + PickupDock: PickupDockComponent, + PopulationSpawnArea: PopulationSpawnAreaComponent, + SentGift: SentGiftComponent, + SlidingDoor: SlidingDoorComponent, + SpawnArea: SpawnAreaComponent, + StatManager: StatManagerComponent, + WoodcutTree: WoodcutTreeComponent +}; diff --git a/src/types/ATTPrefabHash.ts b/src/types/ATTPrefabHash.ts new file mode 100644 index 0000000..edc7799 --- /dev/null +++ b/src/types/ATTPrefabHash.ts @@ -0,0 +1,5 @@ +import type { ATTPrefabName } from './ATTPrefabName.js'; + +import { ATTPrefabs } from './ATTPrefabs.js'; + +export type ATTPrefabHash = (typeof ATTPrefabs)[ATTPrefabName]['hash']; diff --git a/src/types/ATTPrefabName.ts b/src/types/ATTPrefabName.ts new file mode 100644 index 0000000..556c867 --- /dev/null +++ b/src/types/ATTPrefabName.ts @@ -0,0 +1,3 @@ +import { ATTPrefabs } from './ATTPrefabs.js'; + +export type ATTPrefabName = keyof typeof ATTPrefabs; diff --git a/src/types/ATTPrefabs.ts b/src/types/ATTPrefabs.ts new file mode 100644 index 0000000..83eb3b7 --- /dev/null +++ b/src/types/ATTPrefabs.ts @@ -0,0 +1,41507 @@ +/** + * Parsed spawn infodump. + * @since 2023-06-12 + * @version 3.0.0 + */ +export const ATTPrefabs = { + '(Child_Node)_Climbing_Tower_Teleporter_Node': { + 'hash': 5078, + 'name': '(Child_Node)_Climbing_Tower_Teleporter_Node', + 'embedded': { + '(Child_Node)_Climbing_Tower_Teleporter_Node_56704': { + 'hash': 56704, + 'name': '(Child_Node)_Climbing_Tower_Teleporter_Node', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + }, + 'ClimbingTowerTeleporterNode': { + 'hash': 392234266, + 'name': 'ClimbingTowerTeleporterNode' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + } + } + }, + 'Visualizer_56774': { + 'hash': 56774, + 'name': 'Visualizer', + 'savables': { + 'ClimbingTowerProgressionVisualizer': { + 'hash': 623957243, + 'name': 'ClimbingTowerProgressionVisualizer' + } + } + } + } + }, + '(OriginalRoot_Node)_Climbing_Tower_Teleporter_Node': { + 'hash': 55446, + 'name': '(OriginalRoot_Node)_Climbing_Tower_Teleporter_Node', + 'embedded': { + '(OriginalRoot_Node)_Climbing_Tower_Teleporter_Node_55438': { + 'hash': 55438, + 'name': '(OriginalRoot_Node)_Climbing_Tower_Teleporter_Node', + 'savables': { + 'ClimbingTowerTeleporterNode': { + 'hash': 392234266, + 'name': 'ClimbingTowerTeleporterNode' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + } + } + } + } + }, + '(Original_Child_Node)_Climbing_Tower_Teleporter_Node': { + 'hash': 26916, + 'name': '(Original_Child_Node)_Climbing_Tower_Teleporter_Node', + 'embedded': { + '(Original_Child_Node)_Climbing_Tower_Teleporter_Node_26908': { + 'hash': 26908, + 'name': '(Original_Child_Node)_Climbing_Tower_Teleporter_Node', + 'savables': { + 'ClimbingTowerTeleporterNode': { + 'hash': 392234266, + 'name': 'ClimbingTowerTeleporterNode' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + } + } + } + } + }, + '(Root_Node)_Climbing_Tower_Teleporter_Node': { + 'hash': 7668, + 'name': '(Root_Node)_Climbing_Tower_Teleporter_Node', + 'embedded': { + '(Root_Node)_Climbing_Tower_Teleporter_Node_56148': { + 'hash': 56148, + 'name': '(Root_Node)_Climbing_Tower_Teleporter_Node', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + }, + 'ClimbingTowerTeleporterNode': { + 'hash': 392234266, + 'name': 'ClimbingTowerTeleporterNode' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + } + } + }, + 'Visualizer_56330': { + 'hash': 56330, + 'name': 'Visualizer', + 'savables': { + 'ClimbingTowerProgressionVisualizer': { + 'hash': 623957243, + 'name': 'ClimbingTowerProgressionVisualizer' + } + } + } + } + }, + 'ATM_Coin_Bank': { + 'hash': 9780, + 'name': 'ATM_Coin_Bank', + 'embedded': { + 'ATM_Coin_Bank_7202': { + 'hash': 7202, + 'name': 'ATM_Coin_Bank', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + }, + 'Base_Dock_28320': { + 'hash': 28320, + 'name': 'Base_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'DepositDock_33532': { + 'hash': 33532, + 'name': 'DepositDock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Grab_22452': { + 'hash': 22452, + 'name': 'Grab', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Hand_Touch_46540': { + 'hash': 46540, + 'name': 'Hand_Touch', + 'savables': {} + }, + 'Withdraw_Dock_34750': { + 'hash': 34750, + 'name': 'Withdraw_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + } + } + }, + 'Absolute_Apple_Tree_Variant': { + 'hash': 15898, + 'name': 'Absolute_Apple_Tree_Variant', + 'embedded': { + 'Absolute_Apple_Tree_Variant_58592': { + 'hash': 58592, + 'name': 'Absolute_Apple_Tree_Variant', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Absolute_Blueberry_Tree_Variant': { + 'hash': 16322, + 'name': 'Absolute_Blueberry_Tree_Variant', + 'embedded': { + 'Absolute_Blueberry_Tree_Variant_24412': { + 'hash': 24412, + 'name': 'Absolute_Blueberry_Tree_Variant', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'And': { + 'hash': 42422, + 'name': 'And', + 'embedded': {} + }, + 'Anvil': { + 'hash': 23182, + 'name': 'Anvil', + 'embedded': { + 'Anvil_57386': { + 'hash': 57386, + 'name': 'Anvil', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + } + } + }, + 'Anvil_Training': { + 'hash': 24218, + 'name': 'Anvil_Training', + 'embedded': { + 'Anvil_Training_24216': { + 'hash': 24216, + 'name': 'Anvil_Training', + 'savables': {} + } + } + }, + 'Apple_Core_Burnt': { + 'hash': 50484, + 'name': 'Apple_Core_Burnt', + 'embedded': { + 'Apple_Core_Burnt_10462': { + 'hash': 10462, + 'name': 'Apple_Core_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_5784': { + 'hash': 5784, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Apple_Core_Cooked': { + 'hash': 15500, + 'name': 'Apple_Core_Cooked', + 'embedded': { + 'Apple_Core_Cooked_10462': { + 'hash': 10462, + 'name': 'Apple_Core_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_5784': { + 'hash': 5784, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Apple_Core_Ripe': { + 'hash': 902, + 'name': 'Apple_Core_Ripe', + 'embedded': { + 'Apple_Core_Ripe_10462': { + 'hash': 10462, + 'name': 'Apple_Core_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_5784': { + 'hash': 5784, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Apple_Core_Unripe': { + 'hash': 31614, + 'name': 'Apple_Core_Unripe', + 'embedded': { + 'Apple_Core_Unripe_10462': { + 'hash': 10462, + 'name': 'Apple_Core_Unripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'RaycastCrafter': { + 'hash': 2815374842, + 'name': 'RaycastCrafter' + } + } + }, + 'Cooking_5784': { + 'hash': 5784, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Apple_Flower_Bloom': { + 'hash': 12580, + 'name': 'Apple_Flower_Bloom', + 'embedded': { + 'Apple_Flower_Bloom_29560': { + 'hash': 29560, + 'name': 'Apple_Flower_Bloom', + 'savables': {} + } + } + }, + 'Apple_Flower_Bud': { + 'hash': 12578, + 'name': 'Apple_Flower_Bud', + 'embedded': { + 'Apple_Flower_Bud_35946': { + 'hash': 35946, + 'name': 'Apple_Flower_Bud', + 'savables': {} + } + } + }, + 'Apple_Full_Burnt': { + 'hash': 62102, + 'name': 'Apple_Full_Burnt', + 'embedded': { + 'Apple_Core_Spawner_52298': { + 'hash': 52298, + 'name': 'Apple_Core_Spawner', + 'savables': {} + }, + 'Apple_Full_Burnt_57036': { + 'hash': 57036, + 'name': 'Apple_Full_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_11820': { + 'hash': 11820, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Apple_Full_Cooked': { + 'hash': 14844, + 'name': 'Apple_Full_Cooked', + 'embedded': { + 'Apple_Core_Spawner_53358': { + 'hash': 53358, + 'name': 'Apple_Core_Spawner', + 'savables': {} + }, + 'Apple_Full_Cooked_56646': { + 'hash': 56646, + 'name': 'Apple_Full_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_5588': { + 'hash': 5588, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Apple_Full_Ripe': { + 'hash': 40010, + 'name': 'Apple_Full_Ripe', + 'embedded': { + 'Apple_Core_Spawner_56836': { + 'hash': 56836, + 'name': 'Apple_Core_Spawner', + 'savables': {} + }, + 'Apple_Full_Ripe_56174': { + 'hash': 56174, + 'name': 'Apple_Full_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_2434': { + 'hash': 2434, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Apple_Full_Unripe': { + 'hash': 6740, + 'name': 'Apple_Full_Unripe', + 'embedded': { + 'Apple_Core_Spawner_37092': { + 'hash': 37092, + 'name': 'Apple_Core_Spawner', + 'savables': {} + }, + 'Apple_Full_Unripe_55618': { + 'hash': 55618, + 'name': 'Apple_Full_Unripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_430': { + 'hash': 430, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Apple_Growth': { + 'hash': 19192, + 'name': 'Apple_Growth', + 'embedded': { + 'Apple_Growth_33458': { + 'hash': 33458, + 'name': 'Apple_Growth', + 'savables': { + 'GrowerComponent': { + 'hash': 3402094521, + 'name': 'GrowerComponent' + } + } + } + } + }, + 'Apple_Half_Burnt': { + 'hash': 65526, + 'name': 'Apple_Half_Burnt', + 'embedded': { + 'Apple_Half_Burnt_55062': { + 'hash': 55062, + 'name': 'Apple_Half_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_64844': { + 'hash': 64844, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Apple_Half_Cooked': { + 'hash': 2000, + 'name': 'Apple_Half_Cooked', + 'embedded': { + 'Apple_Half_Cooked_54784': { + 'hash': 54784, + 'name': 'Apple_Half_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_61738': { + 'hash': 61738, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Apple_Half_Ripe': { + 'hash': 7278, + 'name': 'Apple_Half_Ripe', + 'embedded': { + 'Apple_Half_Ripe_54506': { + 'hash': 54506, + 'name': 'Apple_Half_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_54586': { + 'hash': 54586, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Apple_Half_Unripe': { + 'hash': 62012, + 'name': 'Apple_Half_Unripe', + 'embedded': { + 'Apple_Half_Unripe_54228': { + 'hash': 54228, + 'name': 'Apple_Half_Unripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_60662': { + 'hash': 60662, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Apple_Tree': { + 'hash': 61222, + 'name': 'Apple_Tree', + 'embedded': { + 'Apple_Tree_58592': { + 'hash': 58592, + 'name': 'Apple_Tree', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Apple_Tree_Growth': { + 'hash': 14226, + 'name': 'Apple_Tree_Growth', + 'embedded': { + 'Apple_Tree_Growth_33458': { + 'hash': 33458, + 'name': 'Apple_Tree_Growth', + 'savables': { + 'GrowerComponent': { + 'hash': 3402094521, + 'name': 'GrowerComponent' + } + } + } + } + }, + 'Apple_Tree_Separated': { + 'hash': 8974, + 'name': 'Apple_Tree_Separated', + 'embedded': {} + }, + 'Apple_Tree_Stage_1': { + 'hash': 50926, + 'name': 'Apple_Tree_Stage_1', + 'embedded': { + 'Apple_Tree_Stage_1_63514': { + 'hash': 63514, + 'name': 'Apple_Tree_Stage_1', + 'savables': {} + } + } + }, + 'Apple_Tree_Stage_2': { + 'hash': 57538, + 'name': 'Apple_Tree_Stage_2', + 'embedded': { + 'Apple_Tree_Stage_2_11646': { + 'hash': 11646, + 'name': 'Apple_Tree_Stage_2', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Apple_Tree_Stage_3': { + 'hash': 62702, + 'name': 'Apple_Tree_Stage_3', + 'embedded': { + 'Apple_Tree_Stage_3_15774': { + 'hash': 15774, + 'name': 'Apple_Tree_Stage_3', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Area_of_Influence_Receiver_puzzle': { + 'hash': 13256, + 'name': 'Area_of_Influence_Receiver_puzzle', + 'embedded': { + 'Area_of_Influence_Receiver_puzzle_13236': { + 'hash': 13236, + 'name': 'Area_of_Influence_Receiver_puzzle', + 'savables': { + 'AreaOfInfluenceReceiver': { + 'hash': 309083880, + 'name': 'AreaOfInfluenceReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + } + } + } + } + }, + 'Area_of_Influence_Sender_puzzle': { + 'hash': 59482, + 'name': 'Area_of_Influence_Sender_puzzle', + 'embedded': { + 'Area_of_Influence_Sender_puzzle_59428': { + 'hash': 59428, + 'name': 'Area_of_Influence_Sender_puzzle', + 'savables': { + 'AreaOfInfluenceSender': { + 'hash': 176949352, + 'name': 'AreaOfInfluenceSender' + }, + 'LogicIntSender': { + 'hash': 2880587164, + 'name': 'LogicIntSender' + } + } + } + } + }, + 'Arrow': { + 'hash': 56460, + 'name': 'Arrow', + 'embedded': { + 'Arrow_43746': { + 'hash': 43746, + 'name': 'Arrow', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'Embeddable': { + 'hash': 22446553, + 'name': 'Embeddable' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Arrow_Tip_59378': { + 'hash': 59378, + 'name': 'Arrow_Tip', + 'savables': {} + } + } + }, + 'Arrow_Light_Beam_Effect': { + 'hash': 1798, + 'name': 'Arrow_Light_Beam_Effect', + 'embedded': { + 'Arrow_Light_Beam_Effect_64504': { + 'hash': 64504, + 'name': 'Arrow_Light_Beam_Effect', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Arrow_Shaft_Wooden': { + 'hash': 29772, + 'name': 'Arrow_Shaft_Wooden', + 'embedded': { + 'Arrow_Shaft_Wooden_31664': { + 'hash': 31664, + 'name': 'Arrow_Shaft_Wooden', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'Embeddable': { + 'hash': 22446553, + 'name': 'Embeddable' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_Deco_33560': { + 'hash': 33560, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Feather_38282': { + 'hash': 38282, + 'name': 'Slot_Feather', + 'savables': {} + }, + 'Slot_Grass_13582': { + 'hash': 13582, + 'name': 'Slot_Grass', + 'savables': {} + }, + 'Tip_59148': { + 'hash': 59148, + 'name': 'Tip', + 'savables': {} + } + } + }, + 'Arrow_Shaft_Wooden_Training': { + 'hash': 36772, + 'name': 'Arrow_Shaft_Wooden_Training', + 'embedded': { + 'Arrow_Shaft_Wooden_Training_36760': { + 'hash': 36760, + 'name': 'Arrow_Shaft_Wooden_Training', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Tip_59796': { + 'hash': 59796, + 'name': 'Tip', + 'savables': {} + } + } + }, + 'Arrow_Training': { + 'hash': 36190, + 'name': 'Arrow_Training', + 'embedded': { + 'Arrow_Training_43746': { + 'hash': 43746, + 'name': 'Arrow_Training', + 'savables': { + 'Embeddable': { + 'hash': 22446553, + 'name': 'Embeddable' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Tip_59502': { + 'hash': 59502, + 'name': 'Tip', + 'savables': {} + } + } + }, + 'Arrow_Training_Dud': { + 'hash': 8858, + 'name': 'Arrow_Training_Dud', + 'embedded': { + 'Arrow_Training_Dud_43746': { + 'hash': 43746, + 'name': 'Arrow_Training_Dud', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Ash_Gotera_Seed_Spray': { + 'hash': 61862, + 'name': 'Ash_Gotera_Seed_Spray', + 'embedded': { + 'Ash_Gotera_Seed_Spray_44772': { + 'hash': 44772, + 'name': 'Ash_Gotera_Seed_Spray', + 'savables': {} + } + } + }, + 'Ash_Gotera_Smoke': { + 'hash': 48860, + 'name': 'Ash_Gotera_Smoke', + 'embedded': { + 'Ash_Gotera_Smoke_50236': { + 'hash': 50236, + 'name': 'Ash_Gotera_Smoke', + 'savables': {} + } + } + }, + 'Ash_Pile': { + 'hash': 53398, + 'name': 'Ash_Pile', + 'embedded': { + 'Ash_Pile_41772': { + 'hash': 41772, + 'name': 'Ash_Pile', + 'savables': { + 'BasicDecay': { + 'hash': 3801256786, + 'name': 'BasicDecay' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Ash_Tree_Growth': { + 'hash': 48208, + 'name': 'Ash_Tree_Growth', + 'embedded': { + 'Ash_Tree_Growth_33458': { + 'hash': 33458, + 'name': 'Ash_Tree_Growth', + 'savables': { + 'GrowerComponent': { + 'hash': 3402094521, + 'name': 'GrowerComponent' + } + } + } + } + }, + 'Ash_Tree_Seed': { + 'hash': 35274, + 'name': 'Ash_Tree_Seed', + 'embedded': { + 'Ash_Tree_Seed_35258': { + 'hash': 35258, + 'name': 'Ash_Tree_Seed', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'RaycastCrafter': { + 'hash': 2815374842, + 'name': 'RaycastCrafter' + } + } + } + } + }, + 'Ash_Tree_Stage_1': { + 'hash': 17892, + 'name': 'Ash_Tree_Stage_1', + 'embedded': { + 'Ash_Tree_Stage_1_63514': { + 'hash': 63514, + 'name': 'Ash_Tree_Stage_1', + 'savables': {} + } + } + }, + 'Assembly_Deck': { + 'hash': 17520, + 'name': 'Assembly_Deck', + 'embedded': { + 'Assembly_Deck_17438': { + 'hash': 17438, + 'name': 'Assembly_Deck', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + }, + 'GenericAssemblyStation': { + 'hash': 2971871217, + 'name': 'GenericAssemblyStation' + } + } + }, + 'Dock_5748': { + 'hash': 5748, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Pickup_59306': { + 'hash': 59306, + 'name': 'Pickup', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Auto_Cam_Player': { + 'hash': 61644, + 'name': 'Auto_Cam_Player', + 'embedded': {} + }, + 'Axe_Head': { + 'hash': 34412, + 'name': 'Axe_Head', + 'embedded': { + 'Axe_Head_56484': { + 'hash': 56484, + 'name': 'Axe_Head', + 'savables': { + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_59758': { + 'hash': 59758, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_Pole_7796': { + 'hash': 7796, + 'name': 'Insert_Pole', + 'savables': {} + }, + 'metal_axeHead_curve_geo_17472': { + 'hash': 17472, + 'name': 'metal_axeHead_curve_geo', + 'savables': {} + } + } + }, + 'Axe_Head_Curve': { + 'hash': 50322, + 'name': 'Axe_Head_Curve', + 'embedded': { + 'Axe_Head_Curve_56484': { + 'hash': 56484, + 'name': 'Axe_Head_Curve', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_60150': { + 'hash': 60150, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_AxeType_7796': { + 'hash': 7796, + 'name': 'Insert_AxeType', + 'savables': {} + }, + 'metal_axeHead_Curve_geo_LOD0_46530': { + 'hash': 46530, + 'name': 'metal_axeHead_Curve_geo_LOD0', + 'savables': {} + } + } + }, + 'Axe_Head_Felling': { + 'hash': 9918, + 'name': 'Axe_Head_Felling', + 'embedded': { + 'Axe_Head_Felling_58934': { + 'hash': 58934, + 'name': 'Axe_Head_Felling', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_60560': { + 'hash': 60560, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_AxeType_7796': { + 'hash': 7796, + 'name': 'Insert_AxeType', + 'savables': {} + }, + 'metal_axeHead_felling_geo_LOD0_40512': { + 'hash': 40512, + 'name': 'metal_axeHead_felling_geo_LOD0', + 'savables': {} + } + } + }, + 'Axe_Head_GreatCurve': { + 'hash': 10056, + 'name': 'Axe_Head_GreatCurve', + 'embedded': { + 'Axe_Head_GreatCurve_39022': { + 'hash': 39022, + 'name': 'Axe_Head_GreatCurve', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_61024': { + 'hash': 61024, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_HammerType_End_Cap_7796': { + 'hash': 7796, + 'name': 'Insert_HammerType_End_Cap', + 'savables': {} + }, + 'metal_axeHead_greatCurve_geo_LOD0_47596': { + 'hash': 47596, + 'name': 'metal_axeHead_greatCurve_geo_LOD0', + 'savables': {} + } + } + }, + 'Axe_Head_LShape': { + 'hash': 17400, + 'name': 'Axe_Head_LShape', + 'embedded': { + 'Axe_Head_LShape_25390': { + 'hash': 25390, + 'name': 'Axe_Head_LShape', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_61514': { + 'hash': 61514, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_AxeType_7796': { + 'hash': 7796, + 'name': 'Insert_AxeType', + 'savables': {} + }, + 'metal_axeHead_Lshape_LOD0_22814': { + 'hash': 22814, + 'name': 'metal_axeHead_Lshape_LOD0', + 'savables': {} + } + } + }, + 'Axe_Training': { + 'hash': 57010, + 'name': 'Axe_Training', + 'embedded': {} + }, + 'Babu': { + 'hash': 9140, + 'name': 'Babu', + 'embedded': { + 'Babu_55348': { + 'hash': 55348, + 'name': 'Babu', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Babu_AI_55590': { + 'hash': 55590, + 'name': 'Babu_AI', + 'savables': {} + }, + 'Body_41706': { + 'hash': 41706, + 'name': 'Body', + 'savables': {} + }, + 'Dig_Spawn_65330': { + 'hash': 65330, + 'name': 'Dig_Spawn', + 'savables': {} + }, + 'Drop_Spawn_3448': { + 'hash': 3448, + 'name': 'Drop_Spawn', + 'savables': {} + }, + 'Head_Collision_43064': { + 'hash': 43064, + 'name': 'Head_Collision', + 'savables': {} + }, + 'Interactor_49402': { + 'hash': 49402, + 'name': 'Interactor', + 'savables': {} + }, + 'babu_tusk_L_(1)_16632': { + 'hash': 16632, + 'name': 'babu_tusk_L_(1)', + 'savables': {} + }, + 'babu_tusk_R_(1)_17014': { + 'hash': 17014, + 'name': 'babu_tusk_R_(1)', + 'savables': {} + } + } + }, + 'Babu_Leg_Bone': { + 'hash': 32526, + 'name': 'Babu_Leg_Bone', + 'embedded': { + 'Babu_Leg_Bone_26390': { + 'hash': 26390, + 'name': 'Babu_Leg_Bone', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Babu_Leg_Full_Burnt': { + 'hash': 64844, + 'name': 'Babu_Leg_Full_Burnt', + 'embedded': { + 'Babu_Leg_Full_Burnt_25250': { + 'hash': 25250, + 'name': 'Babu_Leg_Full_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Bone_Spawner_38786': { + 'hash': 38786, + 'name': 'Bone_Spawner', + 'savables': {} + }, + 'Cooking_24500': { + 'hash': 24500, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Babu_Leg_Full_Cooked': { + 'hash': 42916, + 'name': 'Babu_Leg_Full_Cooked', + 'embedded': { + 'Babu_Leg_Full_Cooked_25250': { + 'hash': 25250, + 'name': 'Babu_Leg_Full_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Bone_Spawner_38786': { + 'hash': 38786, + 'name': 'Bone_Spawner', + 'savables': {} + }, + 'Cooking_24500': { + 'hash': 24500, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Babu_Leg_Full_Ripe': { + 'hash': 2562, + 'name': 'Babu_Leg_Full_Ripe', + 'embedded': { + 'Babu_Leg_Full_Ripe_25250': { + 'hash': 25250, + 'name': 'Babu_Leg_Full_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Bone_Spawner_38786': { + 'hash': 38786, + 'name': 'Bone_Spawner', + 'savables': {} + }, + 'Cooking_24500': { + 'hash': 24500, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Babu_Leg_Half_Burnt': { + 'hash': 50328, + 'name': 'Babu_Leg_Half_Burnt', + 'embedded': { + 'Babu_Leg_Half_Burnt_16238': { + 'hash': 16238, + 'name': 'Babu_Leg_Half_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_16182': { + 'hash': 16182, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Babu_Leg_Half_Cooked': { + 'hash': 50326, + 'name': 'Babu_Leg_Half_Cooked', + 'embedded': { + 'Babu_Leg_Half_Cooked_16238': { + 'hash': 16238, + 'name': 'Babu_Leg_Half_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_16182': { + 'hash': 16182, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Babu_Leg_Half_Ripe': { + 'hash': 50252, + 'name': 'Babu_Leg_Half_Ripe', + 'embedded': { + 'Babu_Leg_Half_Ripe_16238': { + 'hash': 16238, + 'name': 'Babu_Leg_Half_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_16182': { + 'hash': 16182, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Bag': { + 'hash': 35324, + 'name': 'Bag', + 'embedded': { + 'Bag_43012': { + 'hash': 43012, + 'name': 'Bag', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Bag_Body_42972': { + 'hash': 42972, + 'name': 'Bag_Body', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Dock_BL_42978': { + 'hash': 42978, + 'name': 'Dock_BL', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_BM_42976': { + 'hash': 42976, + 'name': 'Dock_BM', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_BR_42974': { + 'hash': 42974, + 'name': 'Dock_BR', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_ML_42984': { + 'hash': 42984, + 'name': 'Dock_ML', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_MM_42982': { + 'hash': 42982, + 'name': 'Dock_MM', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_MR_42980': { + 'hash': 42980, + 'name': 'Dock_MR', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_TL_42990': { + 'hash': 42990, + 'name': 'Dock_TL', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_TM_42988': { + 'hash': 42988, + 'name': 'Dock_TM', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_TR_42986': { + 'hash': 42986, + 'name': 'Dock_TR', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Roll_Dock_47074': { + 'hash': 47074, + 'name': 'Roll_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Slot_Bag_Attach_30776': { + 'hash': 30776, + 'name': 'Slot_Bag_Attach', + 'savables': {} + }, + 'Slot_Bag_Attach_55164': { + 'hash': 55164, + 'name': 'Slot_Bag_Attach', + 'savables': {} + }, + 'Slot_Bag_Pin_Collectible_Attach_31454': { + 'hash': 31454, + 'name': 'Slot_Bag_Pin_Collectible_Attach', + 'savables': {} + }, + 'Slot_Bag_Tool_Attachment_36292': { + 'hash': 36292, + 'name': 'Slot_Bag_Tool_Attachment', + 'savables': {} + }, + 'Slot_Bag_Tool_Attachment_36386': { + 'hash': 36386, + 'name': 'Slot_Bag_Tool_Attachment', + 'savables': {} + }, + 'standard_bag_Body_14336': { + 'hash': 14336, + 'name': 'standard_bag_Body', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_backPin_L_14300': { + 'hash': 14300, + 'name': 'standard_bag_backPin_L', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_backPin_R_14296': { + 'hash': 14296, + 'name': 'standard_bag_backPin_R', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_crossStrap_01_14332': { + 'hash': 14332, + 'name': 'standard_bag_crossStrap_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_flap_14328': { + 'hash': 14328, + 'name': 'standard_bag_flap', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_flap_clasp_01_14324': { + 'hash': 14324, + 'name': 'standard_bag_flap_clasp_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_handle_body_14308': { + 'hash': 14308, + 'name': 'standard_bag_handle_body', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_handle_wraps_14304': { + 'hash': 14304, + 'name': 'standard_bag_handle_wraps', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_sideBuckle_L_01_14316': { + 'hash': 14316, + 'name': 'standard_bag_sideBuckle_L_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_sideBuckle_L_02_14312': { + 'hash': 14312, + 'name': 'standard_bag_sideBuckle_L_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_sideBuckle_R_01_14376': { + 'hash': 14376, + 'name': 'standard_bag_sideBuckle_R_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_sideBuckle_R_02_14372': { + 'hash': 14372, + 'name': 'standard_bag_sideBuckle_R_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_strap_bot_L_01_14360': { + 'hash': 14360, + 'name': 'standard_bag_strap_bot_L_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_strap_bot_R_01_14356': { + 'hash': 14356, + 'name': 'standard_bag_strap_bot_R_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_strap_bot_buckle_L_02_14368': { + 'hash': 14368, + 'name': 'standard_bag_strap_bot_buckle_L_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_strap_bot_buckle_R_02_14364': { + 'hash': 14364, + 'name': 'standard_bag_strap_bot_buckle_R_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_strap_top_L_01_14344': { + 'hash': 14344, + 'name': 'standard_bag_strap_top_L_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_strap_top_R_01_14340': { + 'hash': 14340, + 'name': 'standard_bag_strap_top_R_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_strap_top_buckle_L_01_14352': { + 'hash': 14352, + 'name': 'standard_bag_strap_top_buckle_L_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_strap_top_buckle_R_01_14348': { + 'hash': 14348, + 'name': 'standard_bag_strap_top_buckle_R_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Barrel_Bag': { + 'hash': 19354, + 'name': 'Barrel_Bag', + 'embedded': { + 'Bag_Body_42972': { + 'hash': 42972, + 'name': 'Bag_Body', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Barrel_Bag_43012': { + 'hash': 43012, + 'name': 'Barrel_Bag', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Dock_TL_42990': { + 'hash': 42990, + 'name': 'Dock_TL', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Heat_47560': { + 'hash': 47560, + 'name': 'Heat', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Liquid_Part_65316': { + 'hash': 65316, + 'name': 'Liquid_Part', + 'savables': { + 'LiquidContainer': { + 'hash': 4179293747, + 'name': 'LiquidContainer' + } + } + }, + 'Slot_Bag_Attach_30776': { + 'hash': 30776, + 'name': 'Slot_Bag_Attach', + 'savables': {} + }, + 'Slot_Bag_Attach_55164': { + 'hash': 55164, + 'name': 'Slot_Bag_Attach', + 'savables': {} + }, + 'barrel_bag_bottomCap_37710': { + 'hash': 37710, + 'name': 'barrel_bag_bottomCap', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'barrel_bag_handleRod_37706': { + 'hash': 37706, + 'name': 'barrel_bag_handleRod', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'barrel_bag_handleTop_37702': { + 'hash': 37702, + 'name': 'barrel_bag_handleTop', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'barrel_bag_ladleHook_37698': { + 'hash': 37698, + 'name': 'barrel_bag_ladleHook', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'barrel_bag_plank_01_37746': { + 'hash': 37746, + 'name': 'barrel_bag_plank_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'barrel_bag_plank_02_37742': { + 'hash': 37742, + 'name': 'barrel_bag_plank_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'barrel_bag_plank_03_37738': { + 'hash': 37738, + 'name': 'barrel_bag_plank_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'barrel_bag_plank_04_37734': { + 'hash': 37734, + 'name': 'barrel_bag_plank_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'barrel_bag_plank_05_37730': { + 'hash': 37730, + 'name': 'barrel_bag_plank_05', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'barrel_bag_plank_06_37726': { + 'hash': 37726, + 'name': 'barrel_bag_plank_06', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'barrel_bag_plank_07_37714': { + 'hash': 37714, + 'name': 'barrel_bag_plank_07', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'barrel_bag_plank_08_37722': { + 'hash': 37722, + 'name': 'barrel_bag_plank_08', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'barrel_bag_ringBottom_37718': { + 'hash': 37718, + 'name': 'barrel_bag_ringBottom', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'barrel_bag_ringtop_37750': { + 'hash': 37750, + 'name': 'barrel_bag_ringtop', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Basic_Population_Folder': { + 'hash': 31116, + 'name': 'Basic_Population_Folder', + 'embedded': {} + }, + 'Birch_Tree_Growth': { + 'hash': 48218, + 'name': 'Birch_Tree_Growth', + 'embedded': { + 'Birch_Tree_Growth_33458': { + 'hash': 33458, + 'name': 'Birch_Tree_Growth', + 'savables': { + 'GrowerComponent': { + 'hash': 3402094521, + 'name': 'GrowerComponent' + } + } + } + } + }, + 'Birch_Tree_Seed': { + 'hash': 55274, + 'name': 'Birch_Tree_Seed', + 'embedded': { + 'Birch_Tree_Seed_35258': { + 'hash': 35258, + 'name': 'Birch_Tree_Seed', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'RaycastCrafter': { + 'hash': 2815374842, + 'name': 'RaycastCrafter' + } + } + } + } + }, + 'Birch_Tree_Stage_1': { + 'hash': 17704, + 'name': 'Birch_Tree_Stage_1', + 'embedded': { + 'Birch_Tree_Stage_1_63514': { + 'hash': 63514, + 'name': 'Birch_Tree_Stage_1', + 'savables': {} + } + } + }, + 'Blue_Mix_Recipe_Burnt_Stew': { + 'hash': 57666, + 'name': 'Blue_Mix_Recipe_Burnt_Stew', + 'embedded': {} + }, + 'Blue_Mix_Recipe_Cooked_Stew': { + 'hash': 57642, + 'name': 'Blue_Mix_Recipe_Cooked_Stew', + 'embedded': {} + }, + 'Blue_Mix_Recipe_Raw_Stew': { + 'hash': 57614, + 'name': 'Blue_Mix_Recipe_Raw_Stew', + 'embedded': {} + }, + 'Blueberry_Flower_Bloom': { + 'hash': 40922, + 'name': 'Blueberry_Flower_Bloom', + 'embedded': { + 'Blueberry_Flower_Bloom_25566': { + 'hash': 25566, + 'name': 'Blueberry_Flower_Bloom', + 'savables': {} + } + } + }, + 'Blueberry_Flower_Bud': { + 'hash': 40920, + 'name': 'Blueberry_Flower_Bud', + 'embedded': { + 'Blueberry_Flower_Bud_25268': { + 'hash': 25268, + 'name': 'Blueberry_Flower_Bud', + 'savables': {} + } + } + }, + 'Blueberry_Full_Burnt': { + 'hash': 49890, + 'name': 'Blueberry_Full_Burnt', + 'embedded': { + 'Blueberry_Full_Burnt_56526': { + 'hash': 56526, + 'name': 'Blueberry_Full_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_46248': { + 'hash': 46248, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Blueberry_Full_Cooked': { + 'hash': 47468, + 'name': 'Blueberry_Full_Cooked', + 'embedded': { + 'Blueberry_Full_Cooked_55520': { + 'hash': 55520, + 'name': 'Blueberry_Full_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_45334': { + 'hash': 45334, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Blueberry_Full_Ripe': { + 'hash': 45012, + 'name': 'Blueberry_Full_Ripe', + 'embedded': { + 'Blueberry_Full_Ripe_54516': { + 'hash': 54516, + 'name': 'Blueberry_Full_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_44398': { + 'hash': 44398, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Blueberry_Full_Unripe': { + 'hash': 42556, + 'name': 'Blueberry_Full_Unripe', + 'embedded': { + 'Blueberry_Full_Unripe_53512': { + 'hash': 53512, + 'name': 'Blueberry_Full_Unripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'RaycastCrafter': { + 'hash': 2815374842, + 'name': 'RaycastCrafter' + } + } + }, + 'Cooking_43444': { + 'hash': 43444, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Blueberry_Growth': { + 'hash': 19292, + 'name': 'Blueberry_Growth', + 'embedded': { + 'Blueberry_Growth_33458': { + 'hash': 33458, + 'name': 'Blueberry_Growth', + 'savables': { + 'GrowerComponent': { + 'hash': 3402094521, + 'name': 'GrowerComponent' + } + } + } + } + }, + 'Blueberry_Recipe_Burnt_Stew': { + 'hash': 36830, + 'name': 'Blueberry_Recipe_Burnt_Stew', + 'embedded': {} + }, + 'Blueberry_Recipe_Cooked_Stew': { + 'hash': 36086, + 'name': 'Blueberry_Recipe_Cooked_Stew', + 'embedded': {} + }, + 'Blueberry_Recipe_Raw_Stew': { + 'hash': 35338, + 'name': 'Blueberry_Recipe_Raw_Stew', + 'embedded': {} + }, + 'Blueberry_Tree': { + 'hash': 878, + 'name': 'Blueberry_Tree', + 'embedded': { + 'Blueberry_Tree_24412': { + 'hash': 24412, + 'name': 'Blueberry_Tree', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Blueberry_Tree_Growth': { + 'hash': 14700, + 'name': 'Blueberry_Tree_Growth', + 'embedded': { + 'Blueberry_Tree_Growth_33458': { + 'hash': 33458, + 'name': 'Blueberry_Tree_Growth', + 'savables': { + 'GrowerComponent': { + 'hash': 3402094521, + 'name': 'GrowerComponent' + } + } + } + } + }, + 'Blueberry_Tree_Separated': { + 'hash': 13784, + 'name': 'Blueberry_Tree_Separated', + 'embedded': {} + }, + 'Blueberry_Tree_Stage_1': { + 'hash': 26588, + 'name': 'Blueberry_Tree_Stage_1', + 'embedded': { + 'Blueberry_Tree_Stage_1_63514': { + 'hash': 63514, + 'name': 'Blueberry_Tree_Stage_1', + 'savables': {} + } + } + }, + 'Blueberry_Tree_Stage_2': { + 'hash': 1038, + 'name': 'Blueberry_Tree_Stage_2', + 'embedded': { + 'Blueberry_Tree_Stage_2_1020': { + 'hash': 1020, + 'name': 'Blueberry_Tree_Stage_2', + 'savables': {} + } + } + }, + 'Blueberry_Tree_Stage_3': { + 'hash': 1040, + 'name': 'Blueberry_Tree_Stage_3', + 'embedded': { + 'Blueberry_Tree_Stage_3_1022': { + 'hash': 1022, + 'name': 'Blueberry_Tree_Stage_3', + 'savables': {} + } + } + }, + 'Book': { + 'hash': 44174, + 'name': 'Book', + 'embedded': {} + }, + 'Bookshelf': { + 'hash': 64316, + 'name': 'Bookshelf', + 'embedded': { + 'Bookshelf_64030': { + 'hash': 64030, + 'name': 'Bookshelf', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + }, + 'Dock_2780': { + 'hash': 2780, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_64568': { + 'hash': 64568, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_64570': { + 'hash': 64570, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_64572': { + 'hash': 64572, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_64574': { + 'hash': 64574, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_64576': { + 'hash': 64576, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_64578': { + 'hash': 64578, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_64580': { + 'hash': 64580, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_64582': { + 'hash': 64582, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_64584': { + 'hash': 64584, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_64586': { + 'hash': 64586, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_64588': { + 'hash': 64588, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_64590': { + 'hash': 64590, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_64592': { + 'hash': 64592, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_64594': { + 'hash': 64594, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_64596': { + 'hash': 64596, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_64598': { + 'hash': 64598, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_64600': { + 'hash': 64600, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_64602': { + 'hash': 64602, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_64604': { + 'hash': 64604, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + } + } + }, + 'Bookshelf_NoBackboard': { + 'hash': 59952, + 'name': 'Bookshelf_NoBackboard', + 'embedded': { + 'Bookshelf_NoBackboard_64030': { + 'hash': 64030, + 'name': 'Bookshelf_NoBackboard', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + }, + 'Dock_2780': { + 'hash': 2780, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62044': { + 'hash': 62044, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62046': { + 'hash': 62046, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62048': { + 'hash': 62048, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62050': { + 'hash': 62050, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62052': { + 'hash': 62052, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62054': { + 'hash': 62054, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62056': { + 'hash': 62056, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62058': { + 'hash': 62058, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62060': { + 'hash': 62060, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62062': { + 'hash': 62062, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62064': { + 'hash': 62064, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62066': { + 'hash': 62066, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62068': { + 'hash': 62068, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62070': { + 'hash': 62070, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62072': { + 'hash': 62072, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62074': { + 'hash': 62074, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62076': { + 'hash': 62076, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62078': { + 'hash': 62078, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62080': { + 'hash': 62080, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + } + } + }, + 'Bought_Skill_Orb_Replacer': { + 'hash': 42842, + 'name': 'Bought_Skill_Orb_Replacer', + 'embedded': {} + }, + 'Boulder_Button_Spawner': { + 'hash': 21830, + 'name': 'Boulder_Button_Spawner', + 'embedded': {} + }, + 'Bouncing_Movement': { + 'hash': 34396, + 'name': 'Bouncing_Movement', + 'embedded': { + 'Bouncing_Movement_60930': { + 'hash': 60930, + 'name': 'Bouncing_Movement', + 'savables': { + 'WayPointPath': { + 'hash': 1063725326, + 'name': 'WayPointPath' + } + } + } + } + }, + 'Bow': { + 'hash': 56546, + 'name': 'Bow', + 'embedded': { + 'Arrow_Dock_40686': { + 'hash': 40686, + 'name': 'Arrow_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bow_40716': { + 'hash': 40716, + 'name': 'Bow', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'String_40688': { + 'hash': 40688, + 'name': 'String', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Bow_Blade': { + 'hash': 27416, + 'name': 'Bow_Blade', + 'embedded': { + 'Bow_Blade_27418': { + 'hash': 27418, + 'name': 'Bow_Blade', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_12228': { + 'hash': 12228, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_Bow_Blade_7796': { + 'hash': 7796, + 'name': 'Insert_Bow_Blade', + 'savables': {} + }, + 'metal_blade_bow_full_geo_LOD0_52240': { + 'hash': 52240, + 'name': 'metal_blade_bow_full_geo_LOD0', + 'savables': {} + } + } + }, + 'Bow_Training': { + 'hash': 42340, + 'name': 'Bow_Training', + 'embedded': { + 'Arrow_Dock_40686': { + 'hash': 40686, + 'name': 'Arrow_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bow_Training_42328': { + 'hash': 42328, + 'name': 'Bow_Training', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'String_40688': { + 'hash': 40688, + 'name': 'String', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Bramble_Obstacle': { + 'hash': 59178, + 'name': 'Bramble_Obstacle', + 'embedded': { + 'Bramble_Obstacle_59546': { + 'hash': 59546, + 'name': 'Bramble_Obstacle', + 'savables': {} + } + } + }, + 'Bramble_Obstacle_No_Bush': { + 'hash': 24434, + 'name': 'Bramble_Obstacle_No_Bush', + 'embedded': { + 'Bramble_Obstacle_No_Bush_24428': { + 'hash': 24428, + 'name': 'Bramble_Obstacle_No_Bush', + 'savables': {} + } + } + }, + 'Breakable_Box': { + 'hash': 19624, + 'name': 'Breakable_Box', + 'embedded': { + 'Breakable_Box_17050': { + 'hash': 17050, + 'name': 'Breakable_Box', + 'savables': { + 'MultiHandPickup': { + 'hash': 1556697998, + 'name': 'MultiHandPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Spawn_Content_40226': { + 'hash': 40226, + 'name': 'Spawn_Content', + 'savables': {} + } + } + }, + 'Breakable_Pot': { + 'hash': 60800, + 'name': 'Breakable_Pot', + 'embedded': { + 'Breakable_Pot_17050': { + 'hash': 17050, + 'name': 'Breakable_Pot', + 'savables': { + 'MultiHandPickup': { + 'hash': 1556697998, + 'name': 'MultiHandPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Spawn_Content_40226': { + 'hash': 40226, + 'name': 'Spawn_Content', + 'savables': {} + } + } + }, + 'Breakable_Root_2.5m_Bendy': { + 'hash': 35896, + 'name': 'Breakable_Root_2.5m_Bendy', + 'embedded': { + 'Breakable_Root_2.5m_Bendy_35892': { + 'hash': 35892, + 'name': 'Breakable_Root_2.5m_Bendy', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_2.5m_Curved': { + 'hash': 35738, + 'name': 'Breakable_Root_2.5m_Curved', + 'embedded': { + 'Breakable_Root_2.5m_Curved_35734': { + 'hash': 35734, + 'name': 'Breakable_Root_2.5m_Curved', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_2.5m_Straight': { + 'hash': 34564, + 'name': 'Breakable_Root_2.5m_Straight', + 'embedded': { + 'Breakable_Root_2.5m_Straight_34560': { + 'hash': 34560, + 'name': 'Breakable_Root_2.5m_Straight', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_2.5m_Wavy': { + 'hash': 36054, + 'name': 'Breakable_Root_2.5m_Wavy', + 'embedded': { + 'Breakable_Root_2.5m_Wavy_36050': { + 'hash': 36050, + 'name': 'Breakable_Root_2.5m_Wavy', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_Bendy': { + 'hash': 41482, + 'name': 'Breakable_Root_Bendy', + 'embedded': { + 'Breakable_Root_Bendy_42186': { + 'hash': 42186, + 'name': 'Breakable_Root_Bendy', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_Curved': { + 'hash': 64388, + 'name': 'Breakable_Root_Curved', + 'embedded': { + 'Breakable_Root_Curved_2746': { + 'hash': 2746, + 'name': 'Breakable_Root_Curved', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_Fence': { + 'hash': 62846, + 'name': 'Breakable_Root_Fence', + 'embedded': { + 'Breakable_Root_Fence_63540': { + 'hash': 63540, + 'name': 'Breakable_Root_Fence', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_Ground_01': { + 'hash': 34014, + 'name': 'Breakable_Root_Ground_01', + 'embedded': { + 'Breakable_Root_Ground_01_34010': { + 'hash': 34010, + 'name': 'Breakable_Root_Ground_01', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_Ground_02': { + 'hash': 23246, + 'name': 'Breakable_Root_Ground_02', + 'embedded': { + 'Breakable_Root_Ground_02_23250': { + 'hash': 23250, + 'name': 'Breakable_Root_Ground_02', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_Ground_03': { + 'hash': 21206, + 'name': 'Breakable_Root_Ground_03', + 'embedded': { + 'Breakable_Root_Ground_03_21202': { + 'hash': 21202, + 'name': 'Breakable_Root_Ground_03', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_Ground_04': { + 'hash': 18702, + 'name': 'Breakable_Root_Ground_04', + 'embedded': { + 'Breakable_Root_Ground_04_18706': { + 'hash': 18706, + 'name': 'Breakable_Root_Ground_04', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_Ground_05': { + 'hash': 16298, + 'name': 'Breakable_Root_Ground_05', + 'embedded': { + 'Breakable_Root_Ground_05_16294': { + 'hash': 16294, + 'name': 'Breakable_Root_Ground_05', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_Ground_06': { + 'hash': 13634, + 'name': 'Breakable_Root_Ground_06', + 'embedded': { + 'Breakable_Root_Ground_06_13638': { + 'hash': 13638, + 'name': 'Breakable_Root_Ground_06', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_HangingShort_Bendy': { + 'hash': 13856, + 'name': 'Breakable_Root_HangingShort_Bendy', + 'embedded': { + 'Breakable_Root_HangingShort_Bendy_13860': { + 'hash': 13860, + 'name': 'Breakable_Root_HangingShort_Bendy', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_HangingShort_Curved': { + 'hash': 12224, + 'name': 'Breakable_Root_HangingShort_Curved', + 'embedded': { + 'Breakable_Root_HangingShort_Curved_12228': { + 'hash': 12228, + 'name': 'Breakable_Root_HangingShort_Curved', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_HangingShort_Straight': { + 'hash': 9226, + 'name': 'Breakable_Root_HangingShort_Straight', + 'embedded': { + 'Breakable_Root_HangingShort_Straight_9230': { + 'hash': 9230, + 'name': 'Breakable_Root_HangingShort_Straight', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_HangingShort_Wavy': { + 'hash': 8534, + 'name': 'Breakable_Root_HangingShort_Wavy', + 'embedded': { + 'Breakable_Root_HangingShort_Wavy_8538': { + 'hash': 8538, + 'name': 'Breakable_Root_HangingShort_Wavy', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_Hanging_Bendy': { + 'hash': 63792, + 'name': 'Breakable_Root_Hanging_Bendy', + 'embedded': { + 'Breakable_Root_Hanging_Bendy_63796': { + 'hash': 63796, + 'name': 'Breakable_Root_Hanging_Bendy', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_Hanging_Column_01': { + 'hash': 37666, + 'name': 'Breakable_Root_Hanging_Column_01', + 'embedded': { + 'Breakable_Root_Hanging_Column_01_37662': { + 'hash': 37662, + 'name': 'Breakable_Root_Hanging_Column_01', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_Hanging_Column_02': { + 'hash': 24548, + 'name': 'Breakable_Root_Hanging_Column_02', + 'embedded': { + 'Breakable_Root_Hanging_Column_02_24552': { + 'hash': 24552, + 'name': 'Breakable_Root_Hanging_Column_02', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_Hanging_Straight': { + 'hash': 12714, + 'name': 'Breakable_Root_Hanging_Straight', + 'embedded': { + 'Breakable_Root_Hanging_Straight_12710': { + 'hash': 12710, + 'name': 'Breakable_Root_Hanging_Straight', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_Hanging_Thin_Bendy': { + 'hash': 6394, + 'name': 'Breakable_Root_Hanging_Thin_Bendy', + 'embedded': { + 'Breakable_Root_Hanging_Thin_Bendy_6398': { + 'hash': 6398, + 'name': 'Breakable_Root_Hanging_Thin_Bendy', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_Hanging_Thin_Straight': { + 'hash': 57168, + 'name': 'Breakable_Root_Hanging_Thin_Straight', + 'embedded': { + 'Breakable_Root_Hanging_Thin_Straight_57164': { + 'hash': 57164, + 'name': 'Breakable_Root_Hanging_Thin_Straight', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_Mound_Large': { + 'hash': 15602, + 'name': 'Breakable_Root_Mound_Large', + 'embedded': { + 'Breakable_Root_Mound_Large_15598': { + 'hash': 15598, + 'name': 'Breakable_Root_Mound_Large', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_Mound_Small': { + 'hash': 43010, + 'name': 'Breakable_Root_Mound_Small', + 'embedded': { + 'Breakable_Root_Mound_Small_43014': { + 'hash': 43014, + 'name': 'Breakable_Root_Mound_Small', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_Spawner': { + 'hash': 40946, + 'name': 'Breakable_Root_Spawner', + 'embedded': { + 'Breakable_Root_Spawner_6790': { + 'hash': 6790, + 'name': 'Breakable_Root_Spawner', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + } + } + }, + 'Breakable_Root_Straight': { + 'hash': 47012, + 'name': 'Breakable_Root_Straight', + 'embedded': { + 'Breakable_Root_Straight_47710': { + 'hash': 47710, + 'name': 'Breakable_Root_Straight', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Breakable_Root_Wavy': { + 'hash': 28332, + 'name': 'Breakable_Root_Wavy', + 'embedded': { + 'Breakable_Root_Wavy_28960': { + 'hash': 28960, + 'name': 'Breakable_Root_Wavy', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Broken_Box_Piece': { + 'hash': 260, + 'name': 'Broken_Box_Piece', + 'embedded': { + 'Broken_Box_Piece_1356': { + 'hash': 1356, + 'name': 'Broken_Box_Piece', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Broken_Breakable_Root_Piece_Ground': { + 'hash': 43996, + 'name': 'Broken_Breakable_Root_Piece_Ground', + 'embedded': { + 'Broken_Breakable_Root_Piece_Ground_45852': { + 'hash': 45852, + 'name': 'Broken_Breakable_Root_Piece_Ground', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Broken_Breakable_Root_Piece_Short': { + 'hash': 43998, + 'name': 'Broken_Breakable_Root_Piece_Short', + 'embedded': { + 'Broken_Breakable_Root_Piece_Short_45854': { + 'hash': 45854, + 'name': 'Broken_Breakable_Root_Piece_Short', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Broken_Breakable_Root_Piece_Thick': { + 'hash': 43994, + 'name': 'Broken_Breakable_Root_Piece_Thick', + 'embedded': { + 'Broken_Breakable_Root_Piece_Thick_45850': { + 'hash': 45850, + 'name': 'Broken_Breakable_Root_Piece_Thick', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Broken_Breakable_Root_Piece_Thin': { + 'hash': 44000, + 'name': 'Broken_Breakable_Root_Piece_Thin', + 'embedded': { + 'Broken_Breakable_Root_Piece_Thin_45856': { + 'hash': 45856, + 'name': 'Broken_Breakable_Root_Piece_Thin', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Broken_Burnable_Root_Piece_Ground': { + 'hash': 60406, + 'name': 'Broken_Burnable_Root_Piece_Ground', + 'embedded': { + 'Broken_Burnable_Root_Piece_Ground_21172': { + 'hash': 21172, + 'name': 'Broken_Burnable_Root_Piece_Ground', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Broken_Burnable_Root_Piece_Short': { + 'hash': 58460, + 'name': 'Broken_Burnable_Root_Piece_Short', + 'embedded': { + 'Broken_Burnable_Root_Piece_Short_21416': { + 'hash': 21416, + 'name': 'Broken_Burnable_Root_Piece_Short', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Broken_Burnable_Root_Piece_Thick': { + 'hash': 64302, + 'name': 'Broken_Burnable_Root_Piece_Thick', + 'embedded': { + 'Broken_Burnable_Root_Piece_Thick_20728': { + 'hash': 20728, + 'name': 'Broken_Burnable_Root_Piece_Thick', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Broken_Burnable_Root_Piece_Thin': { + 'hash': 61492, + 'name': 'Broken_Burnable_Root_Piece_Thin', + 'embedded': { + 'Broken_Burnable_Root_Piece_Thin_21074': { + 'hash': 21074, + 'name': 'Broken_Burnable_Root_Piece_Thin', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Broken_Crystal_Piece_01': { + 'hash': 60484, + 'name': 'Broken_Crystal_Piece_01', + 'embedded': { + 'Broken_Crystal_Piece_01_63000': { + 'hash': 63000, + 'name': 'Broken_Crystal_Piece_01', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Broken_Crystal_Piece_02': { + 'hash': 49198, + 'name': 'Broken_Crystal_Piece_02', + 'embedded': { + 'Broken_Crystal_Piece_02_46364': { + 'hash': 46364, + 'name': 'Broken_Crystal_Piece_02', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Broken_Crystal_Piece_03': { + 'hash': 37046, + 'name': 'Broken_Crystal_Piece_03', + 'embedded': { + 'Broken_Crystal_Piece_03_34076': { + 'hash': 34076, + 'name': 'Broken_Crystal_Piece_03', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Broken_Crystal_Piece_04': { + 'hash': 23220, + 'name': 'Broken_Crystal_Piece_04', + 'embedded': { + 'Broken_Crystal_Piece_04_20126': { + 'hash': 20126, + 'name': 'Broken_Crystal_Piece_04', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Broken_ExplosionBoulder_Part_01': { + 'hash': 45514, + 'name': 'Broken_ExplosionBoulder_Part_01', + 'embedded': { + 'Broken_ExplosionBoulder_Part_01_53690': { + 'hash': 53690, + 'name': 'Broken_ExplosionBoulder_Part_01', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Broken_ExplosionBoulder_Part_02': { + 'hash': 45518, + 'name': 'Broken_ExplosionBoulder_Part_02', + 'embedded': { + 'Broken_ExplosionBoulder_Part_02_3998': { + 'hash': 3998, + 'name': 'Broken_ExplosionBoulder_Part_02', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Broken_ExplosionBoulder_Part_03': { + 'hash': 45516, + 'name': 'Broken_ExplosionBoulder_Part_03', + 'embedded': { + 'Broken_ExplosionBoulder_Part_03_39886': { + 'hash': 39886, + 'name': 'Broken_ExplosionBoulder_Part_03', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Broken_ExplosionBoulder_Part_04': { + 'hash': 45512, + 'name': 'Broken_ExplosionBoulder_Part_04', + 'embedded': { + 'Broken_ExplosionBoulder_Part_04_29214': { + 'hash': 29214, + 'name': 'Broken_ExplosionBoulder_Part_04', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Broken_ExplosionBoulder_Part_05': { + 'hash': 45520, + 'name': 'Broken_ExplosionBoulder_Part_05', + 'embedded': { + 'Broken_ExplosionBoulder_Part_05_18196': { + 'hash': 18196, + 'name': 'Broken_ExplosionBoulder_Part_05', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Broken_Vine_Bunch_Dead_Piece': { + 'hash': 7264, + 'name': 'Broken_Vine_Bunch_Dead_Piece', + 'embedded': { + 'Broken_Vine_Bunch_Dead_Piece_11182': { + 'hash': 11182, + 'name': 'Broken_Vine_Bunch_Dead_Piece', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Bronze_Alloy_Ingot': { + 'hash': 26316, + 'name': 'Bronze_Alloy_Ingot', + 'embedded': {} + }, + 'Brown_Mushroom_Shield': { + 'hash': 17258, + 'name': 'Brown_Mushroom_Shield', + 'embedded': { + 'Brown_Mushroom_Shield_15482': { + 'hash': 15482, + 'name': 'Brown_Mushroom_Shield', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Bung': { + 'hash': 8050, + 'name': 'Bung', + 'embedded': {} + }, + 'Buried_Grass': { + 'hash': 47090, + 'name': 'Buried_Grass', + 'embedded': { + 'Buried_Grass_64192': { + 'hash': 64192, + 'name': 'Buried_Grass', + 'savables': { + 'SpawnBuried': { + 'hash': 654225716, + 'name': 'SpawnBuried' + } + } + }, + 'PullPickup_51602': { + 'hash': 51602, + 'name': 'PullPickup', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Buried_Pullup': { + 'hash': 61742, + 'name': 'Buried_Pullup', + 'embedded': { + 'Buried_Pullup_64192': { + 'hash': 64192, + 'name': 'Buried_Pullup', + 'savables': { + 'SpawnBuried': { + 'hash': 654225716, + 'name': 'SpawnBuried' + } + } + }, + 'PullPickup_51602': { + 'hash': 51602, + 'name': 'PullPickup', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Buried_Pullup_Bramble': { + 'hash': 37764, + 'name': 'Buried_Pullup_Bramble', + 'embedded': { + 'Buried_Pullup_Bramble_64192': { + 'hash': 64192, + 'name': 'Buried_Pullup_Bramble', + 'savables': { + 'SpawnBuried': { + 'hash': 654225716, + 'name': 'SpawnBuried' + } + } + }, + 'PullPickup_51602': { + 'hash': 51602, + 'name': 'PullPickup', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Buried_Pullup_Carrot': { + 'hash': 59026, + 'name': 'Buried_Pullup_Carrot', + 'embedded': { + 'Buried_Pullup_Carrot_59022': { + 'hash': 59022, + 'name': 'Buried_Pullup_Carrot', + 'savables': { + 'SpawnBuried': { + 'hash': 654225716, + 'name': 'SpawnBuried' + } + } + }, + 'PullPickup_51602': { + 'hash': 51602, + 'name': 'PullPickup', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Buried_Pullup_Potato_Sapling': { + 'hash': 10960, + 'name': 'Buried_Pullup_Potato_Sapling', + 'embedded': { + 'Buried_Pullup_Potato_Sapling_64192': { + 'hash': 64192, + 'name': 'Buried_Pullup_Potato_Sapling', + 'savables': { + 'SpawnBuried': { + 'hash': 654225716, + 'name': 'SpawnBuried' + } + } + }, + 'PullPickup_51602': { + 'hash': 51602, + 'name': 'PullPickup', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Buried_Pullup_Primitive': { + 'hash': 29550, + 'name': 'Buried_Pullup_Primitive', + 'embedded': { + 'Buried_Pullup_Primitive_64192': { + 'hash': 64192, + 'name': 'Buried_Pullup_Primitive', + 'savables': { + 'SpawnBuried': { + 'hash': 654225716, + 'name': 'SpawnBuried' + } + } + }, + 'PullPickup_51602': { + 'hash': 51602, + 'name': 'PullPickup', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Burnable_Root_Fence': { + 'hash': 45144, + 'name': 'Burnable_Root_Fence', + 'embedded': { + 'Burnable_Root_Fence_63540': { + 'hash': 63540, + 'name': 'Burnable_Root_Fence', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Burnable_Root_Ground_01': { + 'hash': 5702, + 'name': 'Burnable_Root_Ground_01', + 'embedded': { + 'Burnable_Root_Ground_01_10714': { + 'hash': 10714, + 'name': 'Burnable_Root_Ground_01', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Burnable_Root_Ground_02': { + 'hash': 34852, + 'name': 'Burnable_Root_Ground_02', + 'embedded': { + 'Burnable_Root_Ground_02_36732': { + 'hash': 36732, + 'name': 'Burnable_Root_Ground_02', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Burnable_Root_Ground_03': { + 'hash': 65260, + 'name': 'Burnable_Root_Ground_03', + 'embedded': { + 'Burnable_Root_Ground_03_2088': { + 'hash': 2088, + 'name': 'Burnable_Root_Ground_03', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Burnable_Root_Ground_04': { + 'hash': 36342, + 'name': 'Burnable_Root_Ground_04', + 'embedded': { + 'Burnable_Root_Ground_04_38842': { + 'hash': 38842, + 'name': 'Burnable_Root_Ground_04', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Burnable_Root_Ground_05': { + 'hash': 35154, + 'name': 'Burnable_Root_Ground_05', + 'embedded': { + 'Burnable_Root_Ground_05_37204': { + 'hash': 37204, + 'name': 'Burnable_Root_Ground_05', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Burnable_Root_Ground_06': { + 'hash': 37414, + 'name': 'Burnable_Root_Ground_06', + 'embedded': { + 'Burnable_Root_Ground_06_59980': { + 'hash': 59980, + 'name': 'Burnable_Root_Ground_06', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Burnable_Root_HangingShort_Bendy': { + 'hash': 58042, + 'name': 'Burnable_Root_HangingShort_Bendy', + 'embedded': { + 'Burnable_Root_HangingShort_Bendy_60188': { + 'hash': 60188, + 'name': 'Burnable_Root_HangingShort_Bendy', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Burnable_Root_HangingShort_Curved': { + 'hash': 29008, + 'name': 'Burnable_Root_HangingShort_Curved', + 'embedded': { + 'Burnable_Root_HangingShort_Curved_31246': { + 'hash': 31246, + 'name': 'Burnable_Root_HangingShort_Curved', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Burnable_Root_HangingShort_Straight': { + 'hash': 43200, + 'name': 'Burnable_Root_HangingShort_Straight', + 'embedded': { + 'Burnable_Root_HangingShort_Straight_45316': { + 'hash': 45316, + 'name': 'Burnable_Root_HangingShort_Straight', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Burnable_Root_HangingShort_Wavy': { + 'hash': 680, + 'name': 'Burnable_Root_HangingShort_Wavy', + 'embedded': { + 'Burnable_Root_HangingShort_Wavy_3040': { + 'hash': 3040, + 'name': 'Burnable_Root_HangingShort_Wavy', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Burnable_Root_Hanging_Bendy': { + 'hash': 44884, + 'name': 'Burnable_Root_Hanging_Bendy', + 'embedded': { + 'Burnable_Root_Hanging_Bendy_46884': { + 'hash': 46884, + 'name': 'Burnable_Root_Hanging_Bendy', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Burnable_Root_Hanging_Column_01': { + 'hash': 39694, + 'name': 'Burnable_Root_Hanging_Column_01', + 'embedded': { + 'Burnable_Root_Hanging_Column_01_43274': { + 'hash': 43274, + 'name': 'Burnable_Root_Hanging_Column_01', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Burnable_Root_Hanging_Column_02': { + 'hash': 14166, + 'name': 'Burnable_Root_Hanging_Column_02', + 'embedded': { + 'Burnable_Root_Hanging_Column_02_16140': { + 'hash': 16140, + 'name': 'Burnable_Root_Hanging_Column_02', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Burnable_Root_Hanging_Straight': { + 'hash': 39592, + 'name': 'Burnable_Root_Hanging_Straight', + 'embedded': { + 'Burnable_Root_Hanging_Straight_41518': { + 'hash': 41518, + 'name': 'Burnable_Root_Hanging_Straight', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Burnable_Root_Hanging_Thin_Bendy': { + 'hash': 64866, + 'name': 'Burnable_Root_Hanging_Thin_Bendy', + 'embedded': { + 'Burnable_Root_Hanging_Thin_Bendy_1566': { + 'hash': 1566, + 'name': 'Burnable_Root_Hanging_Thin_Bendy', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Burnable_Root_Hanging_Thin_Straight': { + 'hash': 36356, + 'name': 'Burnable_Root_Hanging_Thin_Straight', + 'embedded': { + 'Burnable_Root_Hanging_Thin_Straight_38530': { + 'hash': 38530, + 'name': 'Burnable_Root_Hanging_Thin_Straight', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Burnable_Root_Mound_Large': { + 'hash': 48874, + 'name': 'Burnable_Root_Mound_Large', + 'embedded': { + 'Burnable_Root_Mound_Large_15598': { + 'hash': 15598, + 'name': 'Burnable_Root_Mound_Large', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Burnable_Root_Mound_Small': { + 'hash': 17066, + 'name': 'Burnable_Root_Mound_Small', + 'embedded': { + 'Burnable_Root_Mound_Small_17070': { + 'hash': 17070, + 'name': 'Burnable_Root_Mound_Small', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Burnable_VineBunch': { + 'hash': 35828, + 'name': 'Burnable_VineBunch', + 'embedded': { + 'Burnable_VineBunch_35834': { + 'hash': 35834, + 'name': 'Burnable_VineBunch', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Burnable_VineBunch_Tutorial': { + 'hash': 38202, + 'name': 'Burnable_VineBunch_Tutorial', + 'embedded': { + 'Burnable_VineBunch_Tutorial_35834': { + 'hash': 35834, + 'name': 'Burnable_VineBunch_Tutorial', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Button_Spawner': { + 'hash': 42752, + 'name': 'Button_Spawner', + 'embedded': {} + }, + 'Campfire': { + 'hash': 63848, + 'name': 'Campfire', + 'embedded': { + 'Campfire_8496': { + 'hash': 8496, + 'name': 'Campfire', + 'savables': {} + }, + 'Fire_8488': { + 'hash': 8488, + 'name': 'Fire', + 'savables': { + 'Fire': { + 'hash': 3457519710, + 'name': 'Fire' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Campfire_Infinite': { + 'hash': 63034, + 'name': 'Campfire_Infinite', + 'embedded': { + 'Campfire_Infinite_8496': { + 'hash': 8496, + 'name': 'Campfire_Infinite', + 'savables': {} + } + } + }, + 'Campfire_Spawner': { + 'hash': 6584, + 'name': 'Campfire_Spawner', + 'embedded': { + 'Campfire_Spawner_55752': { + 'hash': 55752, + 'name': 'Campfire_Spawner', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + }, + 'Tinder_Spawner_64618': { + 'hash': 64618, + 'name': 'Tinder_Spawner', + 'savables': {} + } + } + }, + 'Campfire_Weak': { + 'hash': 9276, + 'name': 'Campfire_Weak', + 'embedded': { + 'Campfire_Weak_8496': { + 'hash': 8496, + 'name': 'Campfire_Weak', + 'savables': {} + }, + 'Fire_8488': { + 'hash': 8488, + 'name': 'Fire', + 'savables': { + 'Fire': { + 'hash': 3457519710, + 'name': 'Fire' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Candy_Cane': { + 'hash': 27314, + 'name': 'Candy_Cane', + 'embedded': { + 'Candy_Cane_24532': { + 'hash': 24532, + 'name': 'Candy_Cane', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Candy_Cane_Knife_Spawner_3782': { + 'hash': 3782, + 'name': 'Candy_Cane_Knife_Spawner', + 'savables': {} + } + } + }, + 'Candy_Cane_Knife': { + 'hash': 7676, + 'name': 'Candy_Cane_Knife', + 'embedded': { + 'Candy_Cane_Knife_24532': { + 'hash': 24532, + 'name': 'Candy_Cane_Knife', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'Embeddable': { + 'hash': 22446553, + 'name': 'Embeddable' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Carrot_Full_Burnt': { + 'hash': 62634, + 'name': 'Carrot_Full_Burnt', + 'embedded': { + 'Carrot_Full_Burnt_61108': { + 'hash': 61108, + 'name': 'Carrot_Full_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_3266': { + 'hash': 3266, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Carrot_Full_Cooked': { + 'hash': 60742, + 'name': 'Carrot_Full_Cooked', + 'embedded': { + 'Carrot_Full_Cooked_59204': { + 'hash': 59204, + 'name': 'Carrot_Full_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_1986': { + 'hash': 1986, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Carrot_Full_Ripe': { + 'hash': 58838, + 'name': 'Carrot_Full_Ripe', + 'embedded': { + 'Carrot_Full_Ripe_57300': { + 'hash': 57300, + 'name': 'Carrot_Full_Ripe', + 'savables': { + 'BuildupPickup': { + 'hash': 3373651539, + 'name': 'BuildupPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_706': { + 'hash': 706, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Leaves_Parent_29566': { + 'hash': 29566, + 'name': 'Leaves_Parent', + 'savables': {} + } + } + }, + 'Carrot_Full_Unripe': { + 'hash': 56934, + 'name': 'Carrot_Full_Unripe', + 'embedded': { + 'Carrot_Full_Unripe_55396': { + 'hash': 55396, + 'name': 'Carrot_Full_Unripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_64962': { + 'hash': 64962, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Carrot_Half_Burnt': { + 'hash': 64146, + 'name': 'Carrot_Half_Burnt', + 'embedded': { + 'Carrot_Half_Burnt_63824': { + 'hash': 63824, + 'name': 'Carrot_Half_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_38970': { + 'hash': 38970, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Carrot_Half_Cooked': { + 'hash': 63758, + 'name': 'Carrot_Half_Cooked', + 'embedded': { + 'Carrot_Half_Cooked_63420': { + 'hash': 63420, + 'name': 'Carrot_Half_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_38624': { + 'hash': 38624, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Carrot_Half_Ripe': { + 'hash': 63354, + 'name': 'Carrot_Half_Ripe', + 'embedded': { + 'Carrot_Half_Ripe_63016': { + 'hash': 63016, + 'name': 'Carrot_Half_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_38278': { + 'hash': 38278, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Carrot_Half_Unripe': { + 'hash': 62950, + 'name': 'Carrot_Half_Unripe', + 'embedded': { + 'Carrot_Half_Unripe_62612': { + 'hash': 62612, + 'name': 'Carrot_Half_Unripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Cooking_37932': { + 'hash': 37932, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Carrot_Leaves': { + 'hash': 10440, + 'name': 'Carrot_Leaves', + 'embedded': { + 'Carrot_Leaves_14888': { + 'hash': 14888, + 'name': 'Carrot_Leaves', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'PullPickup_32134': { + 'hash': 32134, + 'name': 'PullPickup', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Carsi_Ingot': { + 'hash': 60868, + 'name': 'Carsi_Ingot', + 'embedded': { + 'Carsi_Ingot_32738': { + 'hash': 32738, + 'name': 'Carsi_Ingot', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_12680': { + 'hash': 12680, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Carved_Pumpkin_Smelter': { + 'hash': 27322, + 'name': 'Carved_Pumpkin_Smelter', + 'embedded': { + 'Carved_Pumpkin_Smelter_24226': { + 'hash': 24226, + 'name': 'Carved_Pumpkin_Smelter', + 'savables': { + 'MultiHandPickup': { + 'hash': 1556697998, + 'name': 'MultiHandPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Fire_30100': { + 'hash': 30100, + 'name': 'Fire', + 'savables': { + 'Fire': { + 'hash': 3457519710, + 'name': 'Fire' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Cast_Iron_Lamp': { + 'hash': 24782, + 'name': 'Cast_Iron_Lamp', + 'embedded': { + 'Cast_Iron_Lamp_48448': { + 'hash': 48448, + 'name': 'Cast_Iron_Lamp', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + }, + 'Fire_30100': { + 'hash': 30100, + 'name': 'Fire', + 'savables': { + 'Fire': { + 'hash': 3457519710, + 'name': 'Fire' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Cauldron_Medium': { + 'hash': 45082, + 'name': 'Cauldron_Medium', + 'embedded': { + 'Cauldron_Medium_42440': { + 'hash': 42440, + 'name': 'Cauldron_Medium', + 'savables': { + 'CookingPot': { + 'hash': 2882590463, + 'name': 'CookingPot' + }, + 'LiquidContainer': { + 'hash': 4179293747, + 'name': 'LiquidContainer' + }, + 'MultiHandPickup': { + 'hash': 1556697998, + 'name': 'MultiHandPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'StewManager': { + 'hash': 1499506132, + 'name': 'StewManager' + } + } + }, + 'Handle_Top_20': { + 'hash': 20, + 'name': 'Handle_Top', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'Heat_47560': { + 'hash': 47560, + 'name': 'Heat', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Liquid_19522': { + 'hash': 19522, + 'name': 'Liquid', + 'savables': {} + }, + 'Top_of_Liquid_not_rotating_59824': { + 'hash': 59824, + 'name': 'Top_of_Liquid_not_rotating', + 'savables': {} + }, + 'cookingPot_main_40': { + 'hash': 40, + 'name': 'cookingPot_main', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'cookingPot_medium_handle_L_grp_52': { + 'hash': 52, + 'name': 'cookingPot_medium_handle_L_grp', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'cookingPot_medium_handle_R_grp_44': { + 'hash': 44, + 'name': 'cookingPot_medium_handle_R_grp', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'cookingPot_plate_01_24': { + 'hash': 24, + 'name': 'cookingPot_plate_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'cookingPot_plate_02_28': { + 'hash': 28, + 'name': 'cookingPot_plate_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'cookingPot_plate_03_36': { + 'hash': 36, + 'name': 'cookingPot_plate_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'cookingPot_plate_04_32': { + 'hash': 32, + 'name': 'cookingPot_plate_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'cookingPot_plate_mid_01_48': { + 'hash': 48, + 'name': 'cookingPot_plate_mid_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'cookingPot_plate_mid_02_56': { + 'hash': 56, + 'name': 'cookingPot_plate_mid_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Cave_Explosion_Boulder': { + 'hash': 31136, + 'name': 'Cave_Explosion_Boulder', + 'embedded': { + 'Cave_Explosion_Boulder_31140': { + 'hash': 31140, + 'name': 'Cave_Explosion_Boulder', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Cave_Explosion_Boulder_Clusters': { + 'hash': 17608, + 'name': 'Cave_Explosion_Boulder_Clusters', + 'embedded': { + 'Cave_Explosion_Boulder_Clusters_17602': { + 'hash': 17602, + 'name': 'Cave_Explosion_Boulder_Clusters', + 'savables': {} + } + } + }, + 'Cave_Grass': { + 'hash': 63846, + 'name': 'Cave_Grass', + 'embedded': { + 'Cave_Grass_7194': { + 'hash': 7194, + 'name': 'Cave_Grass', + 'savables': {} + }, + 'Fire_7186': { + 'hash': 7186, + 'name': 'Fire', + 'savables': { + 'FireDissolve': { + 'hash': 3457519710, + 'name': 'FireDissolve' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Cave_Layer_Chunk': { + 'hash': 61672, + 'name': 'Cave_Layer_Chunk', + 'embedded': {} + }, + 'Cave_Layer_Generation': { + 'hash': 61664, + 'name': 'Cave_Layer_Generation', + 'embedded': {} + }, + 'Cave_Surface_Teleporter_Ruins': { + 'hash': 43368, + 'name': 'Cave_Surface_Teleporter_Ruins', + 'embedded': {} + }, + 'Cave_Teleporter': { + 'hash': 27074, + 'name': 'Cave_Teleporter', + 'embedded': {} + }, + 'Cave_Teleporter_Station': { + 'hash': 22840, + 'name': 'Cave_Teleporter_Station', + 'embedded': {} + }, + 'Cave_Teleporter_Station_Ruins': { + 'hash': 29310, + 'name': 'Cave_Teleporter_Station_Ruins', + 'embedded': {} + }, + 'Cave_Wall_Support': { + 'hash': 63840, + 'name': 'Cave_Wall_Support', + 'embedded': { + 'Cave_Wall_Support_5636': { + 'hash': 5636, + 'name': 'Cave_Wall_Support', + 'savables': {} + }, + 'Torch_Dock_5626': { + 'hash': 5626, + 'name': 'Torch_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + } + } + }, + 'Cave_Water_Mound': { + 'hash': 57530, + 'name': 'Cave_Water_Mound', + 'embedded': { + 'Cave_Water_Mound_57514': { + 'hash': 57514, + 'name': 'Cave_Water_Mound', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + }, + 'LiquidContainer': { + 'hash': 4179293747, + 'name': 'LiquidContainer' + } + } + }, + 'Heat_Point_52154': { + 'hash': 52154, + 'name': 'Heat_Point', + 'savables': {} + }, + 'Mushroom_Spawn_Area_22970': { + 'hash': 22970, + 'name': 'Mushroom_Spawn_Area', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + }, + 'Wyrm_Spawn_Area_45512': { + 'hash': 45512, + 'name': 'Wyrm_Spawn_Area', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + } + } + }, + 'Ceiling_Lantern': { + 'hash': 682, + 'name': 'Ceiling_Lantern', + 'embedded': { + 'Ceiling_Lantern_684': { + 'hash': 684, + 'name': 'Ceiling_Lantern', + 'savables': {} + }, + 'ceilingLight_Light_jnt_48980': { + 'hash': 48980, + 'name': 'ceilingLight_Light_jnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'ceilingLight_arm_jnt_48984': { + 'hash': 48984, + 'name': 'ceilingLight_arm_jnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'ceilingLight_root_jnt_48976': { + 'hash': 48976, + 'name': 'ceilingLight_root_jnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Ceiling_Lantern_Lit': { + 'hash': 32476, + 'name': 'Ceiling_Lantern_Lit', + 'embedded': { + 'Ceiling_Lantern_Lit_684': { + 'hash': 684, + 'name': 'Ceiling_Lantern_Lit', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Fire_55870': { + 'hash': 55870, + 'name': 'Fire', + 'savables': { + 'Fire': { + 'hash': 3457519710, + 'name': 'Fire' + } + } + }, + 'ceilingLight_Light_jnt_48980': { + 'hash': 48980, + 'name': 'ceilingLight_Light_jnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'ceilingLight_arm_jnt_48984': { + 'hash': 48984, + 'name': 'ceilingLight_arm_jnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'ceilingLight_root_jnt_48976': { + 'hash': 48976, + 'name': 'ceilingLight_root_jnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Ceiling_Light': { + 'hash': 8226, + 'name': 'Ceiling_Light', + 'embedded': { + 'Ceiling_Light_8232': { + 'hash': 8232, + 'name': 'Ceiling_Light', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Fire_54948': { + 'hash': 54948, + 'name': 'Fire', + 'savables': { + 'Fire': { + 'hash': 3457519710, + 'name': 'Fire' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'ceilingLight_Light_jnt_48980': { + 'hash': 48980, + 'name': 'ceilingLight_Light_jnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'ceilingLight_arm_jnt_48984': { + 'hash': 48984, + 'name': 'ceilingLight_arm_jnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'ceilingLight_root_jnt_48976': { + 'hash': 48976, + 'name': 'ceilingLight_root_jnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Character_Level_Stone': { + 'hash': 60762, + 'name': 'Character_Level_Stone', + 'embedded': { + 'Character_Level_Stone_57948': { + 'hash': 57948, + 'name': 'Character_Level_Stone', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + }, + 'Hand_Touch_46540': { + 'hash': 46540, + 'name': 'Hand_Touch', + 'savables': {} + }, + 'Landmark_Finder_24472': { + 'hash': 24472, + 'name': 'Landmark_Finder', + 'savables': { + 'Landmark': { + 'hash': 2590537994, + 'name': 'Landmark' + }, + 'LandmarkDiscoverZone': { + 'hash': 4095875831, + 'name': 'LandmarkDiscoverZone' + } + } + } + } + }, + 'Chess_Black_Bishop': { + 'hash': 16998, + 'name': 'Chess_Black_Bishop', + 'embedded': { + 'Chess_Black_Bishop_42198': { + 'hash': 42198, + 'name': 'Chess_Black_Bishop', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Chess_Black_Checker': { + 'hash': 16378, + 'name': 'Chess_Black_Checker', + 'embedded': { + 'Chess_Black_Checker_42196': { + 'hash': 42196, + 'name': 'Chess_Black_Checker', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Chess_Black_King': { + 'hash': 17200, + 'name': 'Chess_Black_King', + 'embedded': { + 'Chess_Black_King_42194': { + 'hash': 42194, + 'name': 'Chess_Black_King', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Chess_Black_Knight': { + 'hash': 17291, + 'name': 'Chess_Black_Knight', + 'embedded': { + 'Chess_Black_Knight_42200': { + 'hash': 42200, + 'name': 'Chess_Black_Knight', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Chess_Black_Pawn': { + 'hash': 17282, + 'name': 'Chess_Black_Pawn', + 'embedded': { + 'Chess_Black_Pawn_42202': { + 'hash': 42202, + 'name': 'Chess_Black_Pawn', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Chess_Black_Queen': { + 'hash': 16204, + 'name': 'Chess_Black_Queen', + 'embedded': { + 'Chess_Black_Queen_42192': { + 'hash': 42192, + 'name': 'Chess_Black_Queen', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Chess_Black_Rook': { + 'hash': 16142, + 'name': 'Chess_Black_Rook', + 'embedded': { + 'Chess_Black_Rook_42196': { + 'hash': 42196, + 'name': 'Chess_Black_Rook', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Chess_Board': { + 'hash': 16896, + 'name': 'Chess_Board', + 'embedded': { + 'Chess_Board_24184': { + 'hash': 24184, + 'name': 'Chess_Board', + 'savables': { + 'GhostSnapSlotCollection': { + 'hash': 1823429789, + 'name': 'GhostSnapSlotCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Chess_White_Bishop': { + 'hash': 17162, + 'name': 'Chess_White_Bishop', + 'embedded': { + 'Chess_White_Bishop_42198': { + 'hash': 42198, + 'name': 'Chess_White_Bishop', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Chess_White_Checker': { + 'hash': 16326, + 'name': 'Chess_White_Checker', + 'embedded': { + 'Chess_White_Checker_42196': { + 'hash': 42196, + 'name': 'Chess_White_Checker', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Chess_White_King': { + 'hash': 16276, + 'name': 'Chess_White_King', + 'embedded': { + 'Chess_White_King_42194': { + 'hash': 42194, + 'name': 'Chess_White_King', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Chess_White_Knight': { + 'hash': 17038, + 'name': 'Chess_White_Knight', + 'embedded': { + 'Chess_White_Knight_42200': { + 'hash': 42200, + 'name': 'Chess_White_Knight', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Chess_White_Pawn': { + 'hash': 17240, + 'name': 'Chess_White_Pawn', + 'embedded': { + 'Chess_White_Pawn_42202': { + 'hash': 42202, + 'name': 'Chess_White_Pawn', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Chess_White_Queen': { + 'hash': 16246, + 'name': 'Chess_White_Queen', + 'embedded': { + 'Chess_White_Queen_42192': { + 'hash': 42192, + 'name': 'Chess_White_Queen', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Chess_White_Rook': { + 'hash': 17084, + 'name': 'Chess_White_Rook', + 'embedded': { + 'Chess_White_Rook_42196': { + 'hash': 42196, + 'name': 'Chess_White_Rook', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Chisel': { + 'hash': 44380, + 'name': 'Chisel', + 'embedded': { + 'Chisel_48634': { + 'hash': 48634, + 'name': 'Chisel', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_64518': { + 'hash': 64518, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_SwordType_25524': { + 'hash': 25524, + 'name': 'Insert_SwordType', + 'savables': {} + }, + 'metal_chisel_blade_full_geo_LOD0_48424': { + 'hash': 48424, + 'name': 'metal_chisel_blade_full_geo_LOD0', + 'savables': {} + } + } + }, + 'ChiselDeck': { + 'hash': 37398, + 'name': 'ChiselDeck', + 'embedded': { + 'ChiselDeck_50854': { + 'hash': 50854, + 'name': 'ChiselDeck', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + }, + 'ChisellingDeck': { + 'hash': 3236280681, + 'name': 'ChisellingDeck' + }, + 'Landmark': { + 'hash': 2590537994, + 'name': 'Landmark' + }, + 'LandmarkDiscoverZone': { + 'hash': 4095875831, + 'name': 'LandmarkDiscoverZone' + } + } + }, + 'ChiselDeck_SetBlock_grp_63040': { + 'hash': 63040, + 'name': 'ChiselDeck_SetBlock_grp', + 'savables': {} + }, + 'Docker_11728': { + 'hash': 11728, + 'name': 'Docker', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'leftHandle_grip_41084': { + 'hash': 41084, + 'name': 'leftHandle_grip', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'panelSwivel_slotFrame_29114': { + 'hash': 29114, + 'name': 'panelSwivel_slotFrame', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'rightHandle_grip_41080': { + 'hash': 41080, + 'name': 'rightHandle_grip', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'rotateHandleGrip_22918': { + 'hash': 22918, + 'name': 'rotateHandleGrip', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Chocolate_Easter_Egg': { + 'hash': 30164, + 'name': 'Chocolate_Easter_Egg', + 'embedded': { + 'Chocolate_Easter_Egg_30160': { + 'hash': 30160, + 'name': 'Chocolate_Easter_Egg', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Christmas_Gift_Box': { + 'hash': 17920, + 'name': 'Christmas_Gift_Box', + 'embedded': { + 'Christmas_Gift_Box_17050': { + 'hash': 17050, + 'name': 'Christmas_Gift_Box', + 'savables': { + 'MultiHandPickup': { + 'hash': 1556697998, + 'name': 'MultiHandPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Spawn_Content_40226': { + 'hash': 40226, + 'name': 'Spawn_Content', + 'savables': {} + } + } + }, + 'Christmas_Gift_Box_Spawner': { + 'hash': 63174, + 'name': 'Christmas_Gift_Box_Spawner', + 'embedded': { + 'Christmas_Gift_Box_Spawner_42278': { + 'hash': 42278, + 'name': 'Christmas_Gift_Box_Spawner', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + } + } + }, + 'Christmas_Gift_Box_Special': { + 'hash': 18144, + 'name': 'Christmas_Gift_Box_Special', + 'embedded': { + 'Christmas_Gift_Box_Special_17050': { + 'hash': 17050, + 'name': 'Christmas_Gift_Box_Special', + 'savables': { + 'MultiHandPickup': { + 'hash': 1556697998, + 'name': 'MultiHandPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Spawn_Content_40226': { + 'hash': 40226, + 'name': 'Spawn_Content', + 'savables': {} + } + } + }, + 'Christmas_Gift_Mail_Box_01': { + 'hash': 24764, + 'name': 'Christmas_Gift_Mail_Box_01', + 'embedded': { + 'Christmas_Gift_Mail_Box_01_17050': { + 'hash': 17050, + 'name': 'Christmas_Gift_Mail_Box_01', + 'savables': { + 'MultiHandPickup': { + 'hash': 1556697998, + 'name': 'MultiHandPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'SentGift': { + 'hash': 661497638, + 'name': 'SentGift' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Christmas_Gift_Mail_Box_02': { + 'hash': 16494, + 'name': 'Christmas_Gift_Mail_Box_02', + 'embedded': { + 'Christmas_Gift_Mail_Box_02_17050': { + 'hash': 17050, + 'name': 'Christmas_Gift_Mail_Box_02', + 'savables': { + 'MultiHandPickup': { + 'hash': 1556697998, + 'name': 'MultiHandPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'SentGift': { + 'hash': 661497638, + 'name': 'SentGift' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Christmas_Gift_Mail_Box_03': { + 'hash': 1080, + 'name': 'Christmas_Gift_Mail_Box_03', + 'embedded': { + 'Christmas_Gift_Mail_Box_03_17050': { + 'hash': 17050, + 'name': 'Christmas_Gift_Mail_Box_03', + 'savables': { + 'MultiHandPickup': { + 'hash': 1556697998, + 'name': 'MultiHandPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'SentGift': { + 'hash': 661497638, + 'name': 'SentGift' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Christmas_Tree': { + 'hash': 56318, + 'name': 'Christmas_Tree', + 'embedded': { + 'Christmas_Tree_15640': { + 'hash': 15640, + 'name': 'Christmas_Tree', + 'savables': {} + } + } + }, + 'Chunk_Directional_Surface': { + 'hash': 47534, + 'name': 'Chunk_Directional_Surface', + 'embedded': {} + }, + 'Chunk_Spherical_Surface': { + 'hash': 47614, + 'name': 'Chunk_Spherical_Surface', + 'embedded': {} + }, + 'Chute_Gcore_Dynamic': { + 'hash': 60246, + 'name': 'Chute_Gcore_Dynamic', + 'embedded': { + 'Chute_Gcore_Dynamic_53304': { + 'hash': 53304, + 'name': 'Chute_Gcore_Dynamic', + 'savables': {} + }, + 'Complete_63570': { + 'hash': 63570, + 'name': 'Complete', + 'savables': {} + }, + 'Diggable_4216': { + 'hash': 4216, + 'name': 'Diggable', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + }, + 'Enemy_Spawn_12232': { + 'hash': 12232, + 'name': 'Enemy_Spawn', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + }, + 'Erupt_Area_19858': { + 'hash': 19858, + 'name': 'Erupt_Area', + 'savables': {} + }, + 'Erupt_Area_2920': { + 'hash': 2920, + 'name': 'Erupt_Area', + 'savables': {} + }, + 'Erupt_Area_3280': { + 'hash': 3280, + 'name': 'Erupt_Area', + 'savables': {} + }, + 'Erupt_Area_3286': { + 'hash': 3286, + 'name': 'Erupt_Area', + 'savables': {} + }, + 'Erupt_Area_3486': { + 'hash': 3486, + 'name': 'Erupt_Area', + 'savables': {} + }, + 'Geyser_AI_2664': { + 'hash': 2664, + 'name': 'Geyser_AI', + 'savables': {} + }, + 'Geyser_AI_2944': { + 'hash': 2944, + 'name': 'Geyser_AI', + 'savables': {} + }, + 'Geyser_AI_2946': { + 'hash': 2946, + 'name': 'Geyser_AI', + 'savables': {} + }, + 'Geyser_AI_29794': { + 'hash': 29794, + 'name': 'Geyser_AI', + 'savables': {} + }, + 'Geyser_AI_3258': { + 'hash': 3258, + 'name': 'Geyser_AI', + 'savables': {} + }, + 'Reset_63566': { + 'hash': 63566, + 'name': 'Reset', + 'savables': {} + }, + 'Targeted_Geyser_(1)_27232': { + 'hash': 27232, + 'name': 'Targeted_Geyser_(1)', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Targeted_Geyser_(2)_27100': { + 'hash': 27100, + 'name': 'Targeted_Geyser_(2)', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Targeted_Geyser_(3)_26416': { + 'hash': 26416, + 'name': 'Targeted_Geyser_(3)', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Targeted_Geyser_(4)_26284': { + 'hash': 26284, + 'name': 'Targeted_Geyser_(4)', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Targeted_Geyser_(5)_25600': { + 'hash': 25600, + 'name': 'Targeted_Geyser_(5)', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Top_Enemy_Spawn_12202': { + 'hash': 12202, + 'name': 'Top_Enemy_Spawn', + 'savables': { + 'DirectionalBoundsSurface': { + 'hash': 1962842866, + 'name': 'DirectionalBoundsSurface' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + } + } + }, + 'CircleSpawner': { + 'hash': 49642, + 'name': 'CircleSpawner', + 'embedded': { + 'CircleSpawner_52610': { + 'hash': 52610, + 'name': 'CircleSpawner', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'SpawnInCircle': { + 'hash': 1714180166, + 'name': 'SpawnInCircle' + } + } + } + } + }, + 'CircleSpawner(ExplosiveSpike)': { + 'hash': 31046, + 'name': 'CircleSpawner(ExplosiveSpike)', + 'embedded': { + 'CircleSpawner(ExplosiveSpike)_52620': { + 'hash': 52620, + 'name': 'CircleSpawner(ExplosiveSpike)', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'SpawnInCircle': { + 'hash': 1714180166, + 'name': 'SpawnInCircle' + } + } + } + } + }, + 'CircleSpawner_ExplosiveSpike': { + 'hash': 31046, + 'name': 'CircleSpawner_ExplosiveSpike', + 'embedded': {} + }, + 'Climbing_Tower_Progression_Visualizer': { + 'hash': 44244, + 'name': 'Climbing_Tower_Progression_Visualizer', + 'embedded': { + 'Climbing_Tower_Progression_Visualizer_43852': { + 'hash': 43852, + 'name': 'Climbing_Tower_Progression_Visualizer', + 'savables': { + 'ClimbingTowerProgressionVisualizer': { + 'hash': 623957243, + 'name': 'ClimbingTowerProgressionVisualizer' + } + } + }, + 'Ruins_Hand_Touch_Activator_20982': { + 'hash': 20982, + 'name': 'Ruins_Hand_Touch_Activator', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + } + } + } + } + }, + 'Climbing_Unlock_Orb_Pedestal': { + 'hash': 51594, + 'name': 'Climbing_Unlock_Orb_Pedestal', + 'embedded': { + 'Climbing_Unlock_Orb_Pedestal_51198': { + 'hash': 51198, + 'name': 'Climbing_Unlock_Orb_Pedestal', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + }, + 'Hand_Touch_46540': { + 'hash': 46540, + 'name': 'Hand_Touch', + 'savables': { + 'AddUnlockToPlayer': { + 'hash': 1756836969, + 'name': 'AddUnlockToPlayer' + }, + 'ClimbingTowerTeleporterNode': { + 'hash': 392234266, + 'name': 'ClimbingTowerTeleporterNode' + }, + 'OrbBasinVfxController': { + 'hash': 715394364, + 'name': 'OrbBasinVfxController' + }, + 'PlayerUnlockStation': { + 'hash': 2912807649, + 'name': 'PlayerUnlockStation' + } + } + } + } + }, + 'Coal': { + 'hash': 19658, + 'name': 'Coal', + 'embedded': { + 'Coal_19542': { + 'hash': 19542, + 'name': 'Coal', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Coal_Ash': { + 'hash': 2792, + 'name': 'Coal_Ash', + 'embedded': { + 'Coal_Ash_2796': { + 'hash': 2796, + 'name': 'Coal_Ash', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Coal_Boulder_01': { + 'hash': 23502, + 'name': 'Coal_Boulder_01', + 'embedded': { + 'Coal_Boulder_01_23506': { + 'hash': 23506, + 'name': 'Coal_Boulder_01', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Coal_Boulder_02': { + 'hash': 57382, + 'name': 'Coal_Boulder_02', + 'embedded': { + 'Coal_Boulder_02_57386': { + 'hash': 57386, + 'name': 'Coal_Boulder_02', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Coal_Boulder_03': { + 'hash': 23788, + 'name': 'Coal_Boulder_03', + 'embedded': { + 'Coal_Boulder_03_23792': { + 'hash': 23792, + 'name': 'Coal_Boulder_03', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Coal_Training': { + 'hash': 51610, + 'name': 'Coal_Training', + 'embedded': { + 'Coal_Training_51606': { + 'hash': 51606, + 'name': 'Coal_Training', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Coin_Press': { + 'hash': 31306, + 'name': 'Coin_Press', + 'embedded': { + 'Coin_Press_65312': { + 'hash': 65312, + 'name': 'Coin_Press', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + }, + 'Input_36080': { + 'hash': 36080, + 'name': 'Input', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Lever_Physics_45996': { + 'hash': 45996, + 'name': 'Lever_Physics', + 'savables': { + 'Lever': { + 'hash': 1594932294, + 'name': 'Lever' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Output_52720': { + 'hash': 52720, + 'name': 'Output', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + } + } + }, + 'Concoction_Crate': { + 'hash': 23304, + 'name': 'Concoction_Crate', + 'embedded': { + 'Concoction_Crate_21538': { + 'hash': 21538, + 'name': 'Concoction_Crate', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + }, + 'LiquidContainer': { + 'hash': 4179293747, + 'name': 'LiquidContainer' + } + } + }, + 'Heat_Area_15578': { + 'hash': 15578, + 'name': 'Heat_Area', + 'savables': {} + } + } + }, + 'Constant': { + 'hash': 42424, + 'name': 'Constant', + 'embedded': {} + }, + 'Cooking_Stand': { + 'hash': 6742, + 'name': 'Cooking_Stand', + 'embedded': { + 'Cooking_Stand_51236': { + 'hash': 51236, + 'name': 'Cooking_Stand', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + }, + 'Crank_19094': { + 'hash': 19094, + 'name': 'Crank', + 'savables': {} + }, + 'Handle_16064': { + 'hash': 16064, + 'name': 'Handle', + 'savables': { + 'Crank': { + 'hash': 1588536425, + 'name': 'Crank' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Hangable_Dock_5626': { + 'hash': 5626, + 'name': 'Hangable_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Long_S_Hook_17940': { + 'hash': 17940, + 'name': 'Long_S_Hook', + 'savables': {} + } + } + }, + 'Copper_Boulder': { + 'hash': 65380, + 'name': 'Copper_Boulder', + 'embedded': { + 'Copper_Boulder_5600': { + 'hash': 5600, + 'name': 'Copper_Boulder', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Spawn_Origin_38012': { + 'hash': 38012, + 'name': 'Spawn_Origin', + 'savables': {} + } + } + }, + 'Copper_Boulder_Parts': { + 'hash': 46024, + 'name': 'Copper_Boulder_Parts', + 'embedded': { + 'Copper_Boulder_Parts_4828': { + 'hash': 4828, + 'name': 'Copper_Boulder_Parts', + 'savables': {} + }, + 'Copper_Boulder_part_01_4846': { + 'hash': 4846, + 'name': 'Copper_Boulder_part_01', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Copper_Boulder_part_02_13706': { + 'hash': 13706, + 'name': 'Copper_Boulder_part_02', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Copper_Boulder_part_03_13714': { + 'hash': 13714, + 'name': 'Copper_Boulder_part_03', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Copper_Boulder_part_04_13722': { + 'hash': 13722, + 'name': 'Copper_Boulder_part_04', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Copper_Boulder_part_05_13718': { + 'hash': 13718, + 'name': 'Copper_Boulder_part_05', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Copper_Cluster': { + 'hash': 20646, + 'name': 'Copper_Cluster', + 'embedded': { + 'Copper_Cluster_20644': { + 'hash': 20644, + 'name': 'Copper_Cluster', + 'savables': {} + } + } + }, + 'Copper_Ingot': { + 'hash': 32850, + 'name': 'Copper_Ingot', + 'embedded': { + 'Copper_Ingot_32738': { + 'hash': 32738, + 'name': 'Copper_Ingot', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_12806': { + 'hash': 12806, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Copper_Ore': { + 'hash': 2484, + 'name': 'Copper_Ore', + 'embedded': { + 'Copper_Ore_24090': { + 'hash': 24090, + 'name': 'Copper_Ore', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Craft_Piece_SideFlat_2Way': { + 'hash': 26748, + 'name': 'Craft_Piece_SideFlat_2Way', + 'embedded': { + 'Craft_Piece_SideFlat_2Way_24176': { + 'hash': 24176, + 'name': 'Craft_Piece_SideFlat_2Way', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_5256': { + 'hash': 5256, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_Edgetype_Craft_57508': { + 'hash': 57508, + 'name': 'Insert_Edgetype_Craft', + 'savables': {} + }, + 'Slot_EdgeType_39368': { + 'hash': 39368, + 'name': 'Slot_EdgeType', + 'savables': {} + }, + 'Slot_EdgeType_51672': { + 'hash': 51672, + 'name': 'Slot_EdgeType', + 'savables': {} + }, + 'Slot_EdgeType_51674': { + 'hash': 51674, + 'name': 'Slot_EdgeType', + 'savables': {} + }, + 'Slot_EdgeType_57506': { + 'hash': 57506, + 'name': 'Slot_EdgeType', + 'savables': {} + } + } + }, + 'Craft_Piece_Side_1Way': { + 'hash': 1274, + 'name': 'Craft_Piece_Side_1Way', + 'embedded': { + 'Craft_Piece_Side_1Way_58156': { + 'hash': 58156, + 'name': 'Craft_Piece_Side_1Way', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_3876': { + 'hash': 3876, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_AxeType_Craft_39368': { + 'hash': 39368, + 'name': 'Insert_AxeType_Craft', + 'savables': {} + }, + 'Slot_AxeType_7170': { + 'hash': 7170, + 'name': 'Slot_AxeType', + 'savables': {} + } + } + }, + 'Craft_Piece_Side_2Way': { + 'hash': 24046, + 'name': 'Craft_Piece_Side_2Way', + 'embedded': { + 'Craft_Piece_Side_2Way_21146': { + 'hash': 21146, + 'name': 'Craft_Piece_Side_2Way', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_4164': { + 'hash': 4164, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_AxeType_Craft_39368': { + 'hash': 39368, + 'name': 'Insert_AxeType_Craft', + 'savables': {} + }, + 'Slot_AxeType_15316': { + 'hash': 15316, + 'name': 'Slot_AxeType', + 'savables': {} + }, + 'Slot_AxeType_15318': { + 'hash': 15318, + 'name': 'Slot_AxeType', + 'savables': {} + } + } + }, + 'Craft_Piece_Side_4Way': { + 'hash': 32160, + 'name': 'Craft_Piece_Side_4Way', + 'embedded': { + 'Craft_Piece_Side_4Way_30046': { + 'hash': 30046, + 'name': 'Craft_Piece_Side_4Way', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_4512': { + 'hash': 4512, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_AxeType_Craft_15432': { + 'hash': 15432, + 'name': 'Insert_AxeType_Craft', + 'savables': {} + }, + 'Slot_AxeType_17932': { + 'hash': 17932, + 'name': 'Slot_AxeType', + 'savables': {} + }, + 'Slot_AxeType_18636': { + 'hash': 18636, + 'name': 'Slot_AxeType', + 'savables': {} + }, + 'Slot_AxeType_19782': { + 'hash': 19782, + 'name': 'Slot_AxeType', + 'savables': {} + }, + 'Slot_AxeType_40654': { + 'hash': 40654, + 'name': 'Slot_AxeType', + 'savables': {} + } + } + }, + 'Craft_Piece_Side_Flat_1Way': { + 'hash': 38606, + 'name': 'Craft_Piece_Side_Flat_1Way', + 'embedded': { + 'Craft_Piece_Side_Flat_1Way_36346': { + 'hash': 36346, + 'name': 'Craft_Piece_Side_Flat_1Way', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_4868': { + 'hash': 4868, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_Edgetype_Craft_15580': { + 'hash': 15580, + 'name': 'Insert_Edgetype_Craft', + 'savables': {} + }, + 'Slot_EdgeType_38338': { + 'hash': 38338, + 'name': 'Slot_EdgeType', + 'savables': {} + }, + 'Slot_EdgeType_39368': { + 'hash': 39368, + 'name': 'Slot_EdgeType', + 'savables': {} + } + } + }, + 'Crafting_Deck': { + 'hash': 28396, + 'name': 'Crafting_Deck', + 'embedded': { + 'Crafting_Deck_64040': { + 'hash': 64040, + 'name': 'Crafting_Deck', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + }, + 'GenericCraftingStation': { + 'hash': 766675725, + 'name': 'GenericCraftingStation' + } + } + }, + 'Crafting_Deck_Crank_Handle_01_16064': { + 'hash': 16064, + 'name': 'Crafting_Deck_Crank_Handle_01', + 'savables': { + 'Crank': { + 'hash': 1588536425, + 'name': 'Crank' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Crafting_Deck_Crank_Handle_02_19132': { + 'hash': 19132, + 'name': 'Crafting_Deck_Crank_Handle_02', + 'savables': { + 'Crank': { + 'hash': 1588536425, + 'name': 'Crank' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Crafting_Deck_Top_MOVE_25974': { + 'hash': 25974, + 'name': 'Crafting_Deck_Top_MOVE', + 'savables': {} + }, + 'Crafting_Deck_top_ROTATE_21724': { + 'hash': 21724, + 'name': 'Crafting_Deck_top_ROTATE', + 'savables': {} + }, + 'GameObject_47008': { + 'hash': 47008, + 'name': 'GameObject', + 'savables': {} + }, + 'Page_Slot_29114': { + 'hash': 29114, + 'name': 'Page_Slot', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + } + } + }, + 'Crane_Center_Piece': { + 'hash': 25456, + 'name': 'Crane_Center_Piece', + 'embedded': { + 'Crane_Center_Piece_6864': { + 'hash': 6864, + 'name': 'Crane_Center_Piece', + 'savables': {} + } + } + }, + 'Crank': { + 'hash': 15392, + 'name': 'Crank', + 'embedded': {} + }, + 'Crate': { + 'hash': 36180, + 'name': 'Crate', + 'embedded': { + 'Crate_14764': { + 'hash': 14764, + 'name': 'Crate', + 'savables': { + 'GeneratedLoot': { + 'hash': 3642863935, + 'name': 'GeneratedLoot' + } + } + }, + 'Dock_1_2780': { + 'hash': 2780, + 'name': 'Dock_1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_2_31842': { + 'hash': 31842, + 'name': 'Dock_2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_3_31266': { + 'hash': 31266, + 'name': 'Dock_3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_4_30878': { + 'hash': 30878, + 'name': 'Dock_4', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + } + } + }, + 'Crate_Stack_Spawner': { + 'hash': 38974, + 'name': 'Crate_Stack_Spawner', + 'embedded': { + 'Crate_Stack_Spawner_14614': { + 'hash': 14614, + 'name': 'Crate_Stack_Spawner', + 'savables': {} + } + } + }, + 'Crater_Gcore_Dynamic': { + 'hash': 21218, + 'name': 'Crater_Gcore_Dynamic', + 'embedded': { + 'Crater_Gcore_Dynamic_53304': { + 'hash': 53304, + 'name': 'Crater_Gcore_Dynamic', + 'savables': {} + }, + 'Enemy_Spawn_30256': { + 'hash': 30256, + 'name': 'Enemy_Spawn', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + } + } + }, + 'Cross_Slash': { + 'hash': 38008, + 'name': 'Cross_Slash', + 'embedded': { + 'Cross_Slash_34552': { + 'hash': 34552, + 'name': 'Cross_Slash', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Crystal_Blue': { + 'hash': 38178, + 'name': 'Crystal_Blue', + 'embedded': { + 'Crystal_Blue_40232': { + 'hash': 40232, + 'name': 'Crystal_Blue', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Crystal_Blue_NoLight': { + 'hash': 14778, + 'name': 'Crystal_Blue_NoLight', + 'embedded': { + 'Crystal_Blue_NoLight_40232': { + 'hash': 40232, + 'name': 'Crystal_Blue_NoLight', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Crystal_Cluster_Blue': { + 'hash': 18096, + 'name': 'Crystal_Cluster_Blue', + 'embedded': { + 'Crystal_Cluster_Blue_24556': { + 'hash': 24556, + 'name': 'Crystal_Cluster_Blue', + 'savables': {} + } + } + }, + 'Crystal_Gem_Blue': { + 'hash': 8002, + 'name': 'Crystal_Gem_Blue', + 'embedded': { + 'Crystal_Gem_Blue_11514': { + 'hash': 11514, + 'name': 'Crystal_Gem_Blue', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Crystal_Lance_Blue': { + 'hash': 23400, + 'name': 'Crystal_Lance_Blue', + 'embedded': { + 'Crystal_Lance_Blue_26000': { + 'hash': 26000, + 'name': 'Crystal_Lance_Blue', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Crystal_Pick_Blue': { + 'hash': 2924, + 'name': 'Crystal_Pick_Blue', + 'embedded': { + 'Crystal_Pick_Blue_5368': { + 'hash': 5368, + 'name': 'Crystal_Pick_Blue', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Crystal_Shard_Blue': { + 'hash': 7092, + 'name': 'Crystal_Shard_Blue', + 'embedded': { + 'Crystal_Shard_Blue_9072': { + 'hash': 9072, + 'name': 'Crystal_Shard_Blue', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Insert_Deco_112': { + 'hash': 112, + 'name': 'Insert_Deco', + 'savables': {} + } + } + }, + 'Crystal_Structure_Blue': { + 'hash': 51128, + 'name': 'Crystal_Structure_Blue', + 'embedded': { + 'Crystal_Structure_Blue_54360': { + 'hash': 54360, + 'name': 'Crystal_Structure_Blue', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Crystal_Structure_Rocks': { + 'hash': 34144, + 'name': 'Crystal_Structure_Rocks', + 'embedded': { + 'Crystal_Structure_Rocks_54772': { + 'hash': 54772, + 'name': 'Crystal_Structure_Rocks', + 'savables': {} + } + } + }, + 'Crystal_Sword_Blue': { + 'hash': 56894, + 'name': 'Crystal_Sword_Blue', + 'embedded': { + 'Crystal_Sword_Blue_59644': { + 'hash': 59644, + 'name': 'Crystal_Sword_Blue', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Crystal_Wyrm': { + 'hash': 37392, + 'name': 'Crystal_Wyrm', + 'embedded': { + 'Animation_6144': { + 'hash': 6144, + 'name': 'Animation', + 'savables': {} + }, + 'Body_1052': { + 'hash': 1052, + 'name': 'Body', + 'savables': {} + }, + 'Crystal_Wyrm_37044': { + 'hash': 37044, + 'name': 'Crystal_Wyrm', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Crystal_Wyrm_AI_46146': { + 'hash': 46146, + 'name': 'Crystal_Wyrm_AI', + 'savables': {} + }, + 'Gameplay_42330': { + 'hash': 42330, + 'name': 'Gameplay', + 'savables': {} + }, + 'Ground_58968': { + 'hash': 58968, + 'name': 'Ground', + 'savables': {} + }, + 'SlashDamage_L_57358': { + 'hash': 57358, + 'name': 'SlashDamage_L', + 'savables': {} + }, + 'SlashDamage_R_59218': { + 'hash': 59218, + 'name': 'SlashDamage_R', + 'savables': {} + }, + 'Spawner_240': { + 'hash': 240, + 'name': 'Spawner', + 'savables': {} + }, + 'scythe_l_jnt_544': { + 'hash': 544, + 'name': 'scythe_l_jnt', + 'savables': {} + }, + 'scythe_r_jnt_542': { + 'hash': 542, + 'name': 'scythe_r_jnt', + 'savables': {} + } + } + }, + 'Crystal_Wyrm_(Trial)': { + 'hash': 48128, + 'name': 'Crystal_Wyrm_(Trial)', + 'embedded': { + 'Animation_6144': { + 'hash': 6144, + 'name': 'Animation', + 'savables': {} + }, + 'Body_1052': { + 'hash': 1052, + 'name': 'Body', + 'savables': {} + }, + 'Crystal_Wyrm_(Trial)_37044': { + 'hash': 37044, + 'name': 'Crystal_Wyrm_(Trial)', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Crystal_Wyrm_AI_46146': { + 'hash': 46146, + 'name': 'Crystal_Wyrm_AI', + 'savables': {} + }, + 'Gameplay_42330': { + 'hash': 42330, + 'name': 'Gameplay', + 'savables': {} + }, + 'Ground_58968': { + 'hash': 58968, + 'name': 'Ground', + 'savables': {} + }, + 'SlashDamage_L_57358': { + 'hash': 57358, + 'name': 'SlashDamage_L', + 'savables': {} + }, + 'SlashDamage_R_59218': { + 'hash': 59218, + 'name': 'SlashDamage_R', + 'savables': {} + }, + 'Spawner_240': { + 'hash': 240, + 'name': 'Spawner', + 'savables': {} + }, + 'scythe_l_jnt_544': { + 'hash': 544, + 'name': 'scythe_l_jnt', + 'savables': {} + }, + 'scythe_r_jnt_542': { + 'hash': 542, + 'name': 'scythe_r_jnt', + 'savables': {} + } + } + }, + 'Cube': { + 'hash': 5262, + 'name': 'Cube', + 'embedded': { + 'Cube_5268': { + 'hash': 5268, + 'name': 'Cube', + 'savables': {} + } + } + }, + 'Curled_Wooden_Handle': { + 'hash': 64172, + 'name': 'Curled_Wooden_Handle', + 'embedded': { + 'Curled_Wooden_Handle_63962': { + 'hash': 63962, + 'name': 'Curled_Wooden_Handle', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Dock_32818': { + 'hash': 32818, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Slot_Multi_(1)_2108': { + 'hash': 2108, + 'name': 'Slot_Multi_(1)', + 'savables': {} + }, + 'Slot_Multi_34270': { + 'hash': 34270, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_Multi_34272': { + 'hash': 34272, + 'name': 'Slot_Multi', + 'savables': {} + } + } + }, + 'Customization_Controller': { + 'hash': 5526, + 'name': 'Customization_Controller', + 'embedded': {} + }, + 'Dagger_Blade_Curved': { + 'hash': 9704, + 'name': 'Dagger_Blade_Curved', + 'embedded': { + 'Dagger_Blade_Curved_35392': { + 'hash': 35392, + 'name': 'Dagger_Blade_Curved', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_64976': { + 'hash': 64976, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_Straight_Short_SwordType_7796': { + 'hash': 7796, + 'name': 'Insert_Straight_Short_SwordType', + 'savables': {} + }, + 'metal_blade_dagger_curved_LOD0_13424': { + 'hash': 13424, + 'name': 'metal_blade_dagger_curved_LOD0', + 'savables': {} + } + } + }, + 'Dagger_Blade_Edgy': { + 'hash': 49402, + 'name': 'Dagger_Blade_Edgy', + 'embedded': { + 'Dagger_Blade_Edgy_35392': { + 'hash': 35392, + 'name': 'Dagger_Blade_Edgy', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_65480': { + 'hash': 65480, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_Straight_Short_SwordType_7796': { + 'hash': 7796, + 'name': 'Insert_Straight_Short_SwordType', + 'savables': {} + }, + 'metal_blade_dagger_edgy_geo_LOD0_6500': { + 'hash': 6500, + 'name': 'metal_blade_dagger_edgy_geo_LOD0', + 'savables': {} + } + } + }, + 'Dagger_Blade_Round': { + 'hash': 56720, + 'name': 'Dagger_Blade_Round', + 'embedded': { + 'Dagger_Blade_Round_35392': { + 'hash': 35392, + 'name': 'Dagger_Blade_Round', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_442': { + 'hash': 442, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_Straight_Short_SwordType_7796': { + 'hash': 7796, + 'name': 'Insert_Straight_Short_SwordType', + 'savables': {} + }, + 'metal_blade_dagger_round_full_geo_LOD0_22702': { + 'hash': 22702, + 'name': 'metal_blade_dagger_round_full_geo_LOD0', + 'savables': {} + } + } + }, + 'Dagger_Blade_Wide': { + 'hash': 54482, + 'name': 'Dagger_Blade_Wide', + 'embedded': { + 'Dagger_Blade_Wide_54484': { + 'hash': 54484, + 'name': 'Dagger_Blade_Wide', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_926': { + 'hash': 926, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_Straight_Short_SwordType_7796': { + 'hash': 7796, + 'name': 'Insert_Straight_Short_SwordType', + 'savables': {} + }, + 'metal_blade_dagger_wide_full_geo_LOD0_53410': { + 'hash': 53410, + 'name': 'metal_blade_dagger_wide_full_geo_LOD0', + 'savables': {} + } + } + }, + 'Dais_Antler_Red_Variant': { + 'hash': 18358, + 'name': 'Dais_Antler_Red_Variant', + 'embedded': { + 'Dais_AI_22350': { + 'hash': 22350, + 'name': 'Dais_AI', + 'savables': {} + }, + 'Dais_Antler_Red_Variant_38050': { + 'hash': 38050, + 'name': 'Dais_Antler_Red_Variant', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Dais_Body_12508': { + 'hash': 12508, + 'name': 'Dais_Body', + 'savables': {} + }, + 'Rare_Spawner_53168': { + 'hash': 53168, + 'name': 'Rare_Spawner', + 'savables': {} + } + } + }, + 'Dais_Antler_Variant': { + 'hash': 30180, + 'name': 'Dais_Antler_Variant', + 'embedded': { + 'Dais_AI_22350': { + 'hash': 22350, + 'name': 'Dais_AI', + 'savables': {} + }, + 'Dais_Antler_Variant_38050': { + 'hash': 38050, + 'name': 'Dais_Antler_Variant', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Dais_Body_12508': { + 'hash': 12508, + 'name': 'Dais_Body', + 'savables': {} + }, + 'Rare_Spawner_53168': { + 'hash': 53168, + 'name': 'Rare_Spawner', + 'savables': {} + } + } + }, + 'Dais_Child_Red_Variant': { + 'hash': 13444, + 'name': 'Dais_Child_Red_Variant', + 'embedded': { + 'Dais_AI_22350': { + 'hash': 22350, + 'name': 'Dais_AI', + 'savables': {} + }, + 'Dais_Body_12508': { + 'hash': 12508, + 'name': 'Dais_Body', + 'savables': {} + }, + 'Dais_Child_Red_Variant_38050': { + 'hash': 38050, + 'name': 'Dais_Child_Red_Variant', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Rare_Spawner_53168': { + 'hash': 53168, + 'name': 'Rare_Spawner', + 'savables': {} + } + } + }, + 'Dais_Child_Variant': { + 'hash': 31838, + 'name': 'Dais_Child_Variant', + 'embedded': { + 'Dais_AI_22350': { + 'hash': 22350, + 'name': 'Dais_AI', + 'savables': {} + }, + 'Dais_Body_12508': { + 'hash': 12508, + 'name': 'Dais_Body', + 'savables': {} + }, + 'Dais_Child_Variant_38050': { + 'hash': 38050, + 'name': 'Dais_Child_Variant', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Rare_Spawner_53168': { + 'hash': 53168, + 'name': 'Rare_Spawner', + 'savables': {} + } + } + }, + 'Dais_Meat_Full_Burnt': { + 'hash': 41870, + 'name': 'Dais_Meat_Full_Burnt', + 'embedded': { + 'Cooking_24500': { + 'hash': 24500, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Dais_Meat_Full_Burnt_47410': { + 'hash': 47410, + 'name': 'Dais_Meat_Full_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Dais_Meat_Full_Cooked': { + 'hash': 43452, + 'name': 'Dais_Meat_Full_Cooked', + 'embedded': { + 'Cooking_24500': { + 'hash': 24500, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Dais_Meat_Full_Cooked_47410': { + 'hash': 47410, + 'name': 'Dais_Meat_Full_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Dais_Meat_Full_Ripe': { + 'hash': 47394, + 'name': 'Dais_Meat_Full_Ripe', + 'embedded': { + 'Cooking_24500': { + 'hash': 24500, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Dais_Meat_Full_Ripe_42392': { + 'hash': 42392, + 'name': 'Dais_Meat_Full_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Dais_Meat_Half_Burnt': { + 'hash': 43674, + 'name': 'Dais_Meat_Half_Burnt', + 'embedded': { + 'Cooking_24500': { + 'hash': 24500, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Dais_Meat_Half_Burnt_47410': { + 'hash': 47410, + 'name': 'Dais_Meat_Half_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Dais_Meat_Half_Cooked': { + 'hash': 43502, + 'name': 'Dais_Meat_Half_Cooked', + 'embedded': { + 'Cooking_24500': { + 'hash': 24500, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Dais_Meat_Half_Cooked_47410': { + 'hash': 47410, + 'name': 'Dais_Meat_Half_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Dais_Meat_Half_Ripe': { + 'hash': 43294, + 'name': 'Dais_Meat_Half_Ripe', + 'embedded': { + 'Cooking_24500': { + 'hash': 24500, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Dais_Meat_Half_Ripe_47410': { + 'hash': 47410, + 'name': 'Dais_Meat_Half_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Dais_Red_Variant': { + 'hash': 8530, + 'name': 'Dais_Red_Variant', + 'embedded': { + 'Dais_AI_22350': { + 'hash': 22350, + 'name': 'Dais_AI', + 'savables': {} + }, + 'Dais_Body_12508': { + 'hash': 12508, + 'name': 'Dais_Body', + 'savables': {} + }, + 'Dais_Red_Variant_38050': { + 'hash': 38050, + 'name': 'Dais_Red_Variant', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Rare_Spawner_53168': { + 'hash': 53168, + 'name': 'Rare_Spawner', + 'savables': {} + } + } + }, + 'Dais_Variant': { + 'hash': 42430, + 'name': 'Dais_Variant', + 'embedded': { + 'Dais_AI_22350': { + 'hash': 22350, + 'name': 'Dais_AI', + 'savables': {} + }, + 'Dais_Body_12508': { + 'hash': 12508, + 'name': 'Dais_Body', + 'savables': {} + }, + 'Dais_Variant_38050': { + 'hash': 38050, + 'name': 'Dais_Variant', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Rare_Spawner_53168': { + 'hash': 53168, + 'name': 'Rare_Spawner', + 'savables': {} + } + } + }, + 'Darksteel_Ingot': { + 'hash': 57556, + 'name': 'Darksteel_Ingot', + 'embedded': {} + }, + 'Death_Fern': { + 'hash': 37642, + 'name': 'Death_Fern', + 'embedded': { + 'Death_Fern_37626': { + 'hash': 37626, + 'name': 'Death_Fern', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Death_Fern_AI_29794': { + 'hash': 29794, + 'name': 'Death_Fern_AI', + 'savables': {} + }, + 'Emit_Gas_Spawner_16984': { + 'hash': 16984, + 'name': 'Emit_Gas_Spawner', + 'savables': {} + } + } + }, + 'Death_Fern_Poison_Cloud': { + 'hash': 39240, + 'name': 'Death_Fern_Poison_Cloud', + 'embedded': { + 'Death_Fern_Poison_Cloud_50236': { + 'hash': 50236, + 'name': 'Death_Fern_Poison_Cloud', + 'savables': {} + } + } + }, + 'Death_Fern_Seed_Planted': { + 'hash': 40824, + 'name': 'Death_Fern_Seed_Planted', + 'embedded': { + 'Death_Fern_Seed_Planted_40780': { + 'hash': 40780, + 'name': 'Death_Fern_Seed_Planted', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'DebugArrow': { + 'hash': 34892, + 'name': 'DebugArrow', + 'embedded': { + 'Arrow_Tip_59378': { + 'hash': 59378, + 'name': 'Arrow_Tip', + 'savables': {} + }, + 'DebugArrow_43746': { + 'hash': 43746, + 'name': 'DebugArrow', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'Embeddable': { + 'hash': 22446553, + 'name': 'Embeddable' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'DebugNet': { + 'hash': 12632, + 'name': 'DebugNet', + 'embedded': {} + }, + 'DebugPlayerStone': { + 'hash': 62120, + 'name': 'DebugPlayerStone', + 'embedded': { + 'DebugPlayerStone_30920': { + 'hash': 30920, + 'name': 'DebugPlayerStone', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Insert_Primitive_SwordType_7796': { + 'hash': 7796, + 'name': 'Insert_Primitive_SwordType', + 'savables': {} + } + } + }, + 'DebugTool': { + 'hash': 16078, + 'name': 'DebugTool', + 'embedded': {} + }, + 'Decrafting_Deck': { + 'hash': 62244, + 'name': 'Decrafting_Deck', + 'embedded': { + 'Decrafting_Deck_13304': { + 'hash': 13304, + 'name': 'Decrafting_Deck', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + }, + 'Lever_Physics_45996': { + 'hash': 45996, + 'name': 'Lever_Physics', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'TwoStepLever': { + 'hash': 2213531414, + 'name': 'TwoStepLever' + } + } + }, + 'Pickup_Holder_65018': { + 'hash': 65018, + 'name': 'Pickup_Holder', + 'savables': {} + } + } + }, + 'Default_Burnt_Stew': { + 'hash': 20108, + 'name': 'Default_Burnt_Stew', + 'embedded': {} + }, + 'Default_Cooked_Stew': { + 'hash': 19398, + 'name': 'Default_Cooked_Stew', + 'embedded': {} + }, + 'Default_Raw_Stew': { + 'hash': 43078, + 'name': 'Default_Raw_Stew', + 'embedded': {} + }, + 'Descent_Shaft_Gcore_Elevator_Dynamic': { + 'hash': 52804, + 'name': 'Descent_Shaft_Gcore_Elevator_Dynamic', + 'embedded': { + 'Crafting_Deck_Crank_Handle_01_16064': { + 'hash': 16064, + 'name': 'Crafting_Deck_Crank_Handle_01', + 'savables': { + 'Crank': { + 'hash': 1588536425, + 'name': 'Crank' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Crafting_Deck_Crank_Handle_01_46520': { + 'hash': 46520, + 'name': 'Crafting_Deck_Crank_Handle_01', + 'savables': { + 'Crank': { + 'hash': 1588536425, + 'name': 'Crank' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Crafting_Deck_Crank_Handle_01_60092': { + 'hash': 60092, + 'name': 'Crafting_Deck_Crank_Handle_01', + 'savables': { + 'Crank': { + 'hash': 1588536425, + 'name': 'Crank' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Descent_Shaft_Gcore_Elevator_Dynamic_26570': { + 'hash': 26570, + 'name': 'Descent_Shaft_Gcore_Elevator_Dynamic', + 'savables': {} + }, + 'Elevator_61068': { + 'hash': 61068, + 'name': 'Elevator', + 'savables': { + 'NetworkedFloatStream': { + 'hash': 2127962967, + 'name': 'NetworkedFloatStream' + } + } + } + } + }, + 'Descent_Shaft_Gcore_Floor_Diggable_Dynamic': { + 'hash': 18120, + 'name': 'Descent_Shaft_Gcore_Floor_Diggable_Dynamic', + 'embedded': { + 'Descent_Shaft_Gcore_Floor_Diggable_Dynamic_26570': { + 'hash': 26570, + 'name': 'Descent_Shaft_Gcore_Floor_Diggable_Dynamic', + 'savables': {} + }, + 'Diggable_Spawner_2456': { + 'hash': 2456, + 'name': 'Diggable_Spawner', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + } + } + }, + 'Descent_Shaft_Gcore_Floor_Mining_Boulder_Dynamic': { + 'hash': 6308, + 'name': 'Descent_Shaft_Gcore_Floor_Mining_Boulder_Dynamic', + 'embedded': { + 'Descent_Shaft_Gcore_Floor_Mining_Boulder_Dynamic_26570': { + 'hash': 26570, + 'name': 'Descent_Shaft_Gcore_Floor_Mining_Boulder_Dynamic', + 'savables': {} + }, + 'Spawner_2456': { + 'hash': 2456, + 'name': 'Spawner', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + } + } + }, + 'Descent_Shaft_Gcore_Wall_Wyrm_Dynamic': { + 'hash': 33338, + 'name': 'Descent_Shaft_Gcore_Wall_Wyrm_Dynamic', + 'embedded': { + 'Descent_Shaft_Gcore_Wall_Wyrm_Dynamic_26570': { + 'hash': 26570, + 'name': 'Descent_Shaft_Gcore_Wall_Wyrm_Dynamic', + 'savables': {} + }, + 'Spawner_36350': { + 'hash': 36350, + 'name': 'Spawner', + 'savables': { + 'CylindricalBoundsSurface': { + 'hash': 34507654, + 'name': 'CylindricalBoundsSurface' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + } + } + }, + 'Digging_Box_Hebios': { + 'hash': 42226, + 'name': 'Digging_Box_Hebios', + 'embedded': { + 'Destroy_Effect_Spawner_61034': { + 'hash': 61034, + 'name': 'Destroy_Effect_Spawner', + 'savables': {} + }, + 'Digging_Box_Hebios_43820': { + 'hash': 43820, + 'name': 'Digging_Box_Hebios', + 'savables': { + 'HealthBasedDigable': { + 'hash': 2126500253, + 'name': 'HealthBasedDigable' + } + } + }, + 'Spawn_Point_42650': { + 'hash': 42650, + 'name': 'Spawn_Point', + 'savables': {} + } + } + }, + 'Digging_Dirt_Mound': { + 'hash': 43924, + 'name': 'Digging_Dirt_Mound', + 'embedded': { + 'Destroy_Effect_Spawner_61034': { + 'hash': 61034, + 'name': 'Destroy_Effect_Spawner', + 'savables': {} + }, + 'Destroy_Gravestone_Spawner_40844': { + 'hash': 40844, + 'name': 'Destroy_Gravestone_Spawner', + 'savables': {} + }, + 'Digging_Dirt_Mound_43820': { + 'hash': 43820, + 'name': 'Digging_Dirt_Mound', + 'savables': { + 'HealthBasedDigable': { + 'hash': 2126500253, + 'name': 'HealthBasedDigable' + } + } + }, + 'Spawn_Point_42650': { + 'hash': 42650, + 'name': 'Spawn_Point', + 'savables': {} + }, + 'Stone_Spawner_6570': { + 'hash': 6570, + 'name': 'Stone_Spawner', + 'savables': {} + } + } + }, + 'Digging_Dirt_Mound_Hebios': { + 'hash': 33570, + 'name': 'Digging_Dirt_Mound_Hebios', + 'embedded': { + 'Destroy_Effect_Spawner_61034': { + 'hash': 61034, + 'name': 'Destroy_Effect_Spawner', + 'savables': {} + }, + 'Destroy_Gravestone_Spawner_40844': { + 'hash': 40844, + 'name': 'Destroy_Gravestone_Spawner', + 'savables': {} + }, + 'Digging_Dirt_Mound_Hebios_43820': { + 'hash': 43820, + 'name': 'Digging_Dirt_Mound_Hebios', + 'savables': { + 'HealthBasedDigable': { + 'hash': 2126500253, + 'name': 'HealthBasedDigable' + } + } + }, + 'Spawn_Point_42650': { + 'hash': 42650, + 'name': 'Spawn_Point', + 'savables': {} + }, + 'Stone_Spawner_6570': { + 'hash': 6570, + 'name': 'Stone_Spawner', + 'savables': {} + } + } + }, + 'Digging_Dirt_Parts': { + 'hash': 2538, + 'name': 'Digging_Dirt_Parts', + 'embedded': { + 'Digging_Dirt_Parts_2554': { + 'hash': 2554, + 'name': 'Digging_Dirt_Parts', + 'savables': {} + }, + 'digging_chunk_01_LOD0_2158': { + 'hash': 2158, + 'name': 'digging_chunk_01_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'digging_chunk_02_LOD0_2166': { + 'hash': 2166, + 'name': 'digging_chunk_02_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'digging_chunk_03_LOD0_2182': { + 'hash': 2182, + 'name': 'digging_chunk_03_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'digging_chunk_04_LOD0_2164': { + 'hash': 2164, + 'name': 'digging_chunk_04_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'digging_chunk_05_LOD0_2180': { + 'hash': 2180, + 'name': 'digging_chunk_05_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'digging_chunk_06_LOD0_2178': { + 'hash': 2178, + 'name': 'digging_chunk_06_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'digging_chunk_07_LOD0_2170': { + 'hash': 2170, + 'name': 'digging_chunk_07_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'digging_chunk_08_LOD0_2168': { + 'hash': 2168, + 'name': 'digging_chunk_08_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'digging_chunk_09_LOD0_2176': { + 'hash': 2176, + 'name': 'digging_chunk_09_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'digging_chunk_10_LOD0_2174': { + 'hash': 2174, + 'name': 'digging_chunk_10_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'digging_chunk_11_LOD0_2162': { + 'hash': 2162, + 'name': 'digging_chunk_11_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'digging_chunk_12_LOD0_2160': { + 'hash': 2160, + 'name': 'digging_chunk_12_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'digging_chunk_13_LOD0_2172': { + 'hash': 2172, + 'name': 'digging_chunk_13_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Digging_Geode': { + 'hash': 55696, + 'name': 'Digging_Geode', + 'embedded': { + 'Destroy_Effect_Spawner_61034': { + 'hash': 61034, + 'name': 'Destroy_Effect_Spawner', + 'savables': {} + }, + 'Digging_Geode_43820': { + 'hash': 43820, + 'name': 'Digging_Geode', + 'savables': { + 'HealthBasedDigable': { + 'hash': 2126500253, + 'name': 'HealthBasedDigable' + } + } + }, + 'Spawn_Point_42650': { + 'hash': 42650, + 'name': 'Spawn_Point', + 'savables': {} + } + } + }, + 'Digging_Material_Box': { + 'hash': 35612, + 'name': 'Digging_Material_Box', + 'embedded': { + 'Destroy_Effect_Spawner_61034': { + 'hash': 61034, + 'name': 'Destroy_Effect_Spawner', + 'savables': {} + }, + 'Digging_Material_Box_43820': { + 'hash': 43820, + 'name': 'Digging_Material_Box', + 'savables': { + 'HealthBasedDigable': { + 'hash': 2126500253, + 'name': 'HealthBasedDigable' + } + } + }, + 'Spawn_Point_42650': { + 'hash': 42650, + 'name': 'Spawn_Point', + 'savables': {} + } + } + }, + 'Directional_Encounter': { + 'hash': 23796, + 'name': 'Directional_Encounter', + 'embedded': { + /** @todo Verify entities and their components. */ + 'Directional_Encounter_43896': { + 'hash': 43896, + 'name': 'Directional_Encounter', + 'savables': { + 'CylindricalBoundsSurface': { + 'hash': 34507654, + 'name': 'CylindricalBoundsSurface' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + } + } + }, + 'Discovery_Landmark': { + 'hash': 37940, + 'name': 'Discovery_Landmark', + 'embedded': {} + }, + 'Disk_Encounter': { + 'hash': 65062, + 'name': 'Disk_Encounter', + 'embedded': { + /** @todo Verify entities and their components. */ + 'Disk_Encounter_43896': { + 'hash': 43896, + 'name': 'Disk_Encounter', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + } + } + }, + 'Dragonfly': { + 'hash': 54404, + 'name': 'Dragonfly', + 'embedded': { + 'Dragonfly_38050': { + 'hash': 38050, + 'name': 'Dragonfly', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Dragonfly_AI_22350': { + 'hash': 22350, + 'name': 'Dragonfly_AI', + 'savables': {} + }, + 'Dragonfly_Body_7558': { + 'hash': 7558, + 'name': 'Dragonfly_Body', + 'savables': {} + } + } + }, + 'Dragonfly_Corpse': { + 'hash': 43552, + 'name': 'Dragonfly_Corpse', + 'embedded': { + 'Dragonfly_Corpse_43536': { + 'hash': 43536, + 'name': 'Dragonfly_Corpse', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Drawbridge_Puzzle_Range': { + 'hash': 40692, + 'name': 'Drawbridge_Puzzle_Range', + 'embedded': { + 'Drawbridge_44588': { + 'hash': 44588, + 'name': 'Drawbridge', + 'savables': { + 'DrawBridgeRangeLogic': { + 'hash': 2801168996, + 'name': 'DrawBridgeRangeLogic' + } + } + }, + 'Drawbridge_Puzzle_Range_48230': { + 'hash': 48230, + 'name': 'Drawbridge_Puzzle_Range', + 'savables': { + 'LogicFloatReceiver': { + 'hash': 3188272159, + 'name': 'LogicFloatReceiver' + } + } + } + } + }, + 'Drawbridge_Puzzle_Range_long': { + 'hash': 58514, + 'name': 'Drawbridge_Puzzle_Range_long', + 'embedded': { + 'Drawbridge_Puzzle_Range_long_62878': { + 'hash': 62878, + 'name': 'Drawbridge_Puzzle_Range_long', + 'savables': { + 'DrawBridgeRangeLogic': { + 'hash': 2801168996, + 'name': 'DrawBridgeRangeLogic' + }, + 'LinearPartCloner': { + 'hash': 566175523, + 'name': 'LinearPartCloner' + }, + 'LogicFloatReceiver': { + 'hash': 3188272159, + 'name': 'LogicFloatReceiver' + } + } + } + } + }, + 'Drawbridge_Puzzle_Toggle': { + 'hash': 24580, + 'name': 'Drawbridge_Puzzle_Toggle', + 'embedded': { + 'Drawbridge_Puzzle_Toggle_41872': { + 'hash': 41872, + 'name': 'Drawbridge_Puzzle_Toggle', + 'savables': { + 'DrawBridgeLogic': { + 'hash': 2978042925, + 'name': 'DrawBridgeLogic' + }, + 'DrawBridgeRangeLogic': { + 'hash': 2801168996, + 'name': 'DrawBridgeRangeLogic' + }, + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + } + } + } + } + }, + 'Dried_Grass_Bush': { + 'hash': 24480, + 'name': 'Dried_Grass_Bush', + 'embedded': { + 'Dried_Grass_Bush_24440': { + 'hash': 24440, + 'name': 'Dried_Grass_Bush', + 'savables': {} + } + } + }, + 'Dummy_Shelf_Short': { + 'hash': 62404, + 'name': 'Dummy_Shelf_Short', + 'embedded': { + 'Dock_58090': { + 'hash': 58090, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dummy_Shelf_Short_60158': { + 'hash': 60158, + 'name': 'Dummy_Shelf_Short', + 'savables': {} + } + } + }, + 'Duplicate_Paper_Variant': { + 'hash': 11048, + 'name': 'Duplicate_Paper_Variant', + 'embedded': {} + }, + 'Dynamite': { + 'hash': 31326, + 'name': 'Dynamite', + 'embedded': { + 'Dynamite_40522': { + 'hash': 40522, + 'name': 'Dynamite', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Explosion_58370': { + 'hash': 58370, + 'name': 'Explosion', + 'savables': {} + }, + 'Fuse_15214': { + 'hash': 15214, + 'name': 'Fuse', + 'savables': { + 'Fire': { + 'hash': 3457519710, + 'name': 'Fire' + }, + 'Fuse': { + 'hash': 3665939353, + 'name': 'Fuse' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Easter_Egg_01': { + 'hash': 55462, + 'name': 'Easter_Egg_01', + 'embedded': { + 'Easter_Egg_01_21224': { + 'hash': 21224, + 'name': 'Easter_Egg_01', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Easter_Egg_02': { + 'hash': 57998, + 'name': 'Easter_Egg_02', + 'embedded': { + 'Easter_Egg_02_28794': { + 'hash': 28794, + 'name': 'Easter_Egg_02', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Easter_Egg_03': { + 'hash': 20128, + 'name': 'Easter_Egg_03', + 'embedded': { + 'Easter_Egg_03_28794': { + 'hash': 28794, + 'name': 'Easter_Egg_03', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Easter_Egg_04': { + 'hash': 21558, + 'name': 'Easter_Egg_04', + 'embedded': { + 'Easter_Egg_04_28794': { + 'hash': 28794, + 'name': 'Easter_Egg_04', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Edge_Blade_Long_Curve': { + 'hash': 17478, + 'name': 'Edge_Blade_Long_Curve', + 'embedded': { + 'Edge_Blade_Long_Curve_15172': { + 'hash': 15172, + 'name': 'Edge_Blade_Long_Curve', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_5674': { + 'hash': 5674, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_Edgetype_7796': { + 'hash': 7796, + 'name': 'Insert_Edgetype', + 'savables': {} + }, + 'edge_blade_longCurve_LOD0_22044': { + 'hash': 22044, + 'name': 'edge_blade_longCurve_LOD0', + 'savables': {} + } + } + }, + 'Edge_Curved_Blade': { + 'hash': 11938, + 'name': 'Edge_Curved_Blade', + 'embedded': { + 'Edge_Curved_Blade_9684': { + 'hash': 9684, + 'name': 'Edge_Curved_Blade', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_6064': { + 'hash': 6064, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_Edgetype_7796': { + 'hash': 7796, + 'name': 'Insert_Edgetype', + 'savables': {} + }, + 'edge_blade_curved_LOD0_8062': { + 'hash': 8062, + 'name': 'edge_blade_curved_LOD0', + 'savables': {} + } + } + }, + 'Edge_Short_Curve_Blade': { + 'hash': 20892, + 'name': 'Edge_Short_Curve_Blade', + 'embedded': { + 'Edge_Short_Curve_Blade_18048': { + 'hash': 18048, + 'name': 'Edge_Short_Curve_Blade', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_6416': { + 'hash': 6416, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_Edgetype_7796': { + 'hash': 7796, + 'name': 'Insert_Edgetype', + 'savables': {} + }, + 'edge_blade_shortCurve_LOD0_64382': { + 'hash': 64382, + 'name': 'edge_blade_shortCurve_LOD0', + 'savables': {} + } + } + }, + 'Edge_Straight_Blade': { + 'hash': 30124, + 'name': 'Edge_Straight_Blade', + 'embedded': { + 'Edge_Straight_Blade_27748': { + 'hash': 27748, + 'name': 'Edge_Straight_Blade', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_6764': { + 'hash': 6764, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_Edgetype_7796': { + 'hash': 7796, + 'name': 'Insert_Edgetype', + 'savables': {} + }, + 'edge_blade_straight_LOD0_35880': { + 'hash': 35880, + 'name': 'edge_blade_straight_LOD0', + 'savables': {} + } + } + }, + 'Eggplant_Flower_Bloom': { + 'hash': 27848, + 'name': 'Eggplant_Flower_Bloom', + 'embedded': { + 'Eggplant_Flower_Bloom_42092': { + 'hash': 42092, + 'name': 'Eggplant_Flower_Bloom', + 'savables': {} + } + } + }, + 'Eggplant_Flower_Bud': { + 'hash': 27850, + 'name': 'Eggplant_Flower_Bud', + 'embedded': { + 'Eggplant_Flower_Bud_42164': { + 'hash': 42164, + 'name': 'Eggplant_Flower_Bud', + 'savables': {} + } + } + }, + 'Eggplant_Full_Burnt': { + 'hash': 55030, + 'name': 'Eggplant_Full_Burnt', + 'embedded': { + 'Cooking_29582': { + 'hash': 29582, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Eggplant_Full_Burnt_54596': { + 'hash': 54596, + 'name': 'Eggplant_Full_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Eggplant_Full_Cooked': { + 'hash': 54506, + 'name': 'Eggplant_Full_Cooked', + 'embedded': { + 'Cooking_29092': { + 'hash': 29092, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Eggplant_Full_Cooked_54072': { + 'hash': 54072, + 'name': 'Eggplant_Full_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Eggplant_Full_Ripe': { + 'hash': 53982, + 'name': 'Eggplant_Full_Ripe', + 'embedded': { + 'Cooking_28602': { + 'hash': 28602, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Eggplant_Full_Ripe_53548': { + 'hash': 53548, + 'name': 'Eggplant_Full_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Eggplant_Full_Unripe': { + 'hash': 53458, + 'name': 'Eggplant_Full_Unripe', + 'embedded': { + 'Cooking_28112': { + 'hash': 28112, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Eggplant_Full_Unripe_53024': { + 'hash': 53024, + 'name': 'Eggplant_Full_Unripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Eggplant_Growth': { + 'hash': 19304, + 'name': 'Eggplant_Growth', + 'embedded': { + 'Eggplant_Growth_33458': { + 'hash': 33458, + 'name': 'Eggplant_Growth', + 'savables': { + 'GrowerComponent': { + 'hash': 3402094521, + 'name': 'GrowerComponent' + } + } + } + } + }, + 'Eggplant_Half_Burnt': { + 'hash': 62546, + 'name': 'Eggplant_Half_Burnt', + 'embedded': { + 'Cooking_37586': { + 'hash': 37586, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Eggplant_Half_Burnt_62208': { + 'hash': 62208, + 'name': 'Eggplant_Half_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Eggplant_Half_Cooked': { + 'hash': 62142, + 'name': 'Eggplant_Half_Cooked', + 'embedded': { + 'Cooking_37240': { + 'hash': 37240, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Eggplant_Half_Cooked_61804': { + 'hash': 61804, + 'name': 'Eggplant_Half_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Eggplant_Half_Ripe': { + 'hash': 61738, + 'name': 'Eggplant_Half_Ripe', + 'embedded': { + 'Cooking_36894': { + 'hash': 36894, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Eggplant_Half_Ripe_61400': { + 'hash': 61400, + 'name': 'Eggplant_Half_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Eggplant_Half_Unripe': { + 'hash': 61334, + 'name': 'Eggplant_Half_Unripe', + 'embedded': { + 'Cooking_36548': { + 'hash': 36548, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Eggplant_Half_Unripe_60996': { + 'hash': 60996, + 'name': 'Eggplant_Half_Unripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'RaycastCrafter': { + 'hash': 2815374842, + 'name': 'RaycastCrafter' + } + } + } + } + }, + 'Eggplant_Potato_Recipe_Burnt_Stew': { + 'hash': 57688, + 'name': 'Eggplant_Potato_Recipe_Burnt_Stew', + 'embedded': {} + }, + 'Eggplant_Potato_Recipe_Cooked_Stew': { + 'hash': 57712, + 'name': 'Eggplant_Potato_Recipe_Cooked_Stew', + 'embedded': {} + }, + 'Eggplant_Potato_Recipe_Raw_Stew': { + 'hash': 57736, + 'name': 'Eggplant_Potato_Recipe_Raw_Stew', + 'embedded': {} + }, + 'Eggplant_Tree': { + 'hash': 27004, + 'name': 'Eggplant_Tree', + 'embedded': { + 'Eggplant_Tree_24994': { + 'hash': 24994, + 'name': 'Eggplant_Tree', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Eggplant_Tree_Growth': { + 'hash': 15090, + 'name': 'Eggplant_Tree_Growth', + 'embedded': { + 'Eggplant_Tree_Growth_33458': { + 'hash': 33458, + 'name': 'Eggplant_Tree_Growth', + 'savables': { + 'GrowerComponent': { + 'hash': 3402094521, + 'name': 'GrowerComponent' + } + } + } + } + }, + 'Eggplant_Tree_Separated': { + 'hash': 17770, + 'name': 'Eggplant_Tree_Separated', + 'embedded': {} + }, + 'Eggplant_Tree_Stage_1': { + 'hash': 14282, + 'name': 'Eggplant_Tree_Stage_1', + 'embedded': { + 'Eggplant_Tree_Stage_1_63514': { + 'hash': 63514, + 'name': 'Eggplant_Tree_Stage_1', + 'savables': {} + } + } + }, + 'Eggplant_Tree_Stage_2': { + 'hash': 14440, + 'name': 'Eggplant_Tree_Stage_2', + 'embedded': { + 'Eggplant_Tree_Stage_2_26756': { + 'hash': 26756, + 'name': 'Eggplant_Tree_Stage_2', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Eggplant_Tree_Stage_3': { + 'hash': 16154, + 'name': 'Eggplant_Tree_Stage_3', + 'embedded': { + 'Eggplant_Tree_Stage_3_22270': { + 'hash': 22270, + 'name': 'Eggplant_Tree_Stage_3', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Elevator': { + 'hash': 44898, + 'name': 'Elevator', + 'embedded': { + 'Crafting_Deck_Crank_Handle_01_16064': { + 'hash': 16064, + 'name': 'Crafting_Deck_Crank_Handle_01', + 'savables': { + 'Crank': { + 'hash': 1588536425, + 'name': 'Crank' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Crafting_Deck_Crank_Handle_01_46520': { + 'hash': 46520, + 'name': 'Crafting_Deck_Crank_Handle_01', + 'savables': { + 'Crank': { + 'hash': 1588536425, + 'name': 'Crank' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Elevator_26570': { + 'hash': 26570, + 'name': 'Elevator', + 'savables': { + 'WayPointPath': { + 'hash': 1063725326, + 'name': 'WayPointPath' + } + } + } + } + }, + 'Elevator_Puzzle_Crank': { + 'hash': 64134, + 'name': 'Elevator_Puzzle_Crank', + 'embedded': { + 'Crafting_Deck_Crank_Handle_01_16064': { + 'hash': 16064, + 'name': 'Crafting_Deck_Crank_Handle_01', + 'savables': { + 'Crank': { + 'hash': 1588536425, + 'name': 'Crank' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Crafting_Deck_Crank_Handle_01_46520': { + 'hash': 46520, + 'name': 'Crafting_Deck_Crank_Handle_01', + 'savables': { + 'Crank': { + 'hash': 1588536425, + 'name': 'Crank' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Elevator_26570': { + 'hash': 26570, + 'name': 'Elevator', + 'savables': { + 'WayPointPath': { + 'hash': 1063725326, + 'name': 'WayPointPath' + } + } + }, + 'Elevator_Puzzle_Crank_52968': { + 'hash': 52968, + 'name': 'Elevator_Puzzle_Crank', + 'savables': { + 'LogicFloatReceiver': { + 'hash': 3188272159, + 'name': 'LogicFloatReceiver' + } + } + } + } + }, + 'Elevator_Puzzle_Rope': { + 'hash': 20484, + 'name': 'Elevator_Puzzle_Rope', + 'embedded': { + 'Elevator_26570': { + 'hash': 26570, + 'name': 'Elevator', + 'savables': { + 'WayPointPath': { + 'hash': 1063725326, + 'name': 'WayPointPath' + } + } + }, + 'Elevator_Puzzle_Rope_27070': { + 'hash': 27070, + 'name': 'Elevator_Puzzle_Rope', + 'savables': { + 'LogicFloatReceiver': { + 'hash': 3188272159, + 'name': 'LogicFloatReceiver' + } + } + } + } + }, + 'Empty': { + 'hash': 40954, + 'name': 'Empty', + 'embedded': {} + }, + 'Etheral_Arrow': { + 'hash': 52366, + 'name': 'Etheral_Arrow', + 'embedded': { + 'Etheral_Arrow_43746': { + 'hash': 43746, + 'name': 'Etheral_Arrow', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Spike_grp_58940': { + 'hash': 58940, + 'name': 'Spike_grp', + 'savables': {} + } + } + }, + 'Evinon_Steel_Ingot': { + 'hash': 32198, + 'name': 'Evinon_Steel_Ingot', + 'embedded': { + 'Evinon_Steel_Ingot_32738': { + 'hash': 32738, + 'name': 'Evinon_Steel_Ingot', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_12930': { + 'hash': 12930, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Explosion_Boulder': { + 'hash': 44162, + 'name': 'Explosion_Boulder', + 'embedded': { + 'Explosion_Boulder_13178': { + 'hash': 13178, + 'name': 'Explosion_Boulder', + 'savables': { + 'ModifiableAdditionalStaticContent': { + 'hash': 159391088, + 'name': 'ModifiableAdditionalStaticContent' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Explosion_Boulder_Large': { + 'hash': 30854, + 'name': 'Explosion_Boulder_Large', + 'embedded': { + 'Explosion_Boulder_Large_30852': { + 'hash': 30852, + 'name': 'Explosion_Boulder_Large', + 'savables': { + 'ModifiableAdditionalStaticContent': { + 'hash': 159391088, + 'name': 'ModifiableAdditionalStaticContent' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Explosive_Spike': { + 'hash': 50412, + 'name': 'Explosive_Spike', + 'embedded': { + 'Explosion_58370': { + 'hash': 58370, + 'name': 'Explosion', + 'savables': {} + }, + 'Explosive_Spike_15532': { + 'hash': 15532, + 'name': 'Explosive_Spike', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Insert_Deco_112': { + 'hash': 112, + 'name': 'Insert_Deco', + 'savables': {} + } + } + }, + 'Fake_Player_combat_dummy': { + 'hash': 45454, + 'name': 'Fake_Player_combat_dummy', + 'embedded': { + 'Fake_Player_combat_dummy_57314': { + 'hash': 57314, + 'name': 'Fake_Player_combat_dummy', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'dummy_arm_l_01_jnt_46272': { + 'hash': 46272, + 'name': 'dummy_arm_l_01_jnt', + 'savables': {} + }, + 'dummy_arm_l_02_jnt_46248': { + 'hash': 46248, + 'name': 'dummy_arm_l_02_jnt', + 'savables': {} + }, + 'dummy_arm_l_03_jnt_46250': { + 'hash': 46250, + 'name': 'dummy_arm_l_03_jnt', + 'savables': {} + }, + 'dummy_arm_r_01_jnt_46246': { + 'hash': 46246, + 'name': 'dummy_arm_r_01_jnt', + 'savables': {} + }, + 'dummy_arm_r_02_jnt_46254': { + 'hash': 46254, + 'name': 'dummy_arm_r_02_jnt', + 'savables': {} + }, + 'dummy_arm_r_03_jnt_46256': { + 'hash': 46256, + 'name': 'dummy_arm_r_03_jnt', + 'savables': {} + }, + 'dummy_head_01_jnt_46270': { + 'hash': 46270, + 'name': 'dummy_head_01_jnt', + 'savables': {} + }, + 'dummy_head_02_jnt_46264': { + 'hash': 46264, + 'name': 'dummy_head_02_jnt', + 'savables': {} + }, + 'dummy_head_03_jnt_46262': { + 'hash': 46262, + 'name': 'dummy_head_03_jnt', + 'savables': {} + }, + 'dummy_neck_jnt_46268': { + 'hash': 46268, + 'name': 'dummy_neck_jnt', + 'savables': {} + }, + 'dummy_spineMid_jnt_46274': { + 'hash': 46274, + 'name': 'dummy_spineMid_jnt', + 'savables': {} + }, + 'dummy_spine_01_jnt_46258': { + 'hash': 46258, + 'name': 'dummy_spine_01_jnt', + 'savables': {} + }, + 'dummy_spine_02_jnt_46260': { + 'hash': 46260, + 'name': 'dummy_spine_02_jnt', + 'savables': {} + }, + 'dummy_spine_03_jnt_46266': { + 'hash': 46266, + 'name': 'dummy_spine_03_jnt', + 'savables': {} + }, + 'dummy_sternum_jnt_46252': { + 'hash': 46252, + 'name': 'dummy_sternum_jnt', + 'savables': {} + } + } + }, + 'Feather_Red_Training': { + 'hash': 80, + 'name': 'Feather_Red_Training', + 'embedded': { + 'Feather_Red_Training_74': { + 'hash': 74, + 'name': 'Feather_Red_Training', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Firebug': { + 'hash': 40478, + 'name': 'Firebug', + 'embedded': { + 'Firebug_38050': { + 'hash': 38050, + 'name': 'Firebug', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Firebug_AI_22350': { + 'hash': 22350, + 'name': 'Firebug_AI', + 'savables': {} + }, + 'firebug_7558': { + 'hash': 7558, + 'name': 'firebug', + 'savables': {} + } + } + }, + 'Firework': { + 'hash': 40748, + 'name': 'Firework', + 'embedded': { + 'Explosion_58370': { + 'hash': 58370, + 'name': 'Explosion', + 'savables': { + 'ColoredExplosive': { + 'hash': 3920618075, + 'name': 'ColoredExplosive' + } + } + }, + 'Firework_40732': { + 'hash': 40732, + 'name': 'Firework', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'RaycastCrafter': { + 'hash': 2815374842, + 'name': 'RaycastCrafter' + } + } + }, + 'Fuse__15214': { + 'hash': 15214, + 'name': 'Fuse_', + 'savables': { + 'Fire': { + 'hash': 3457519710, + 'name': 'Fire' + }, + 'Fuse': { + 'hash': 3665939353, + 'name': 'Fuse' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Fixed_Light_Bag_Attachment': { + 'hash': 1056, + 'name': 'Fixed_Light_Bag_Attachment', + 'embedded': { + 'Dock_62078': { + 'hash': 62078, + 'name': 'Dock', + 'savables': { + 'AdditionalOwnedDock': { + 'hash': 2592242915, + 'name': 'AdditionalOwnedDock' + } + } + }, + 'Fixed_Light_Bag_Attachment_7868': { + 'hash': 7868, + 'name': 'Fixed_Light_Bag_Attachment', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Insert_Bag_Tool_Attachment_7796': { + 'hash': 7796, + 'name': 'Insert_Bag_Tool_Attachment', + 'savables': {} + }, + 'Storage_38218': { + 'hash': 38218, + 'name': 'Storage', + 'savables': {} + }, + 'bag_lighting_attachment_pin_49786': { + 'hash': 49786, + 'name': 'bag_lighting_attachment_pin', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'bag_lighting_attachment_ropeWrap_01_49802': { + 'hash': 49802, + 'name': 'bag_lighting_attachment_ropeWrap_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'bag_lighting_attachment_ropeWrap_02_49798': { + 'hash': 49798, + 'name': 'bag_lighting_attachment_ropeWrap_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'bag_lighting_attachment_rope_01_49778': { + 'hash': 49778, + 'name': 'bag_lighting_attachment_rope_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'bag_lighting_attachment_rope_02_49774': { + 'hash': 49774, + 'name': 'bag_lighting_attachment_rope_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'bag_lighting_attachment_rope_03_49770': { + 'hash': 49770, + 'name': 'bag_lighting_attachment_rope_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'bag_lighting_attachment_stick_01_49794': { + 'hash': 49794, + 'name': 'bag_lighting_attachment_stick_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'bag_lighting_attachment_stick_02_49790': { + 'hash': 49790, + 'name': 'bag_lighting_attachment_stick_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'bag_lighting_attachment_stick_03_49782': { + 'hash': 49782, + 'name': 'bag_lighting_attachment_stick_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Flame_Step_Effect_Proto': { + 'hash': 24020, + 'name': 'Flame_Step_Effect_Proto', + 'embedded': { + 'Flame_Step_Effect_Proto_26204': { + 'hash': 26204, + 'name': 'Flame_Step_Effect_Proto', + 'savables': {} + }, + 'Heating_Bit_26176': { + 'hash': 26176, + 'name': 'Heating_Bit', + 'savables': {} + }, + 'Hurting_Bit_26178': { + 'hash': 26178, + 'name': 'Hurting_Bit', + 'savables': {} + } + } + }, + 'Flame_Step_Effect_Proto_Lava_Test_Long_Variant': { + 'hash': 54460, + 'name': 'Flame_Step_Effect_Proto_Lava_Test_Long_Variant', + 'embedded': { + 'Flame_Step_Effect_Proto_Lava_Test_Long_Variant_63786': { + 'hash': 63786, + 'name': 'Flame_Step_Effect_Proto_Lava_Test_Long_Variant', + 'savables': {} + }, + 'Heating_Bit_26176': { + 'hash': 26176, + 'name': 'Heating_Bit', + 'savables': {} + }, + 'Hurting_Bit_26178': { + 'hash': 26178, + 'name': 'Hurting_Bit', + 'savables': {} + } + } + }, + 'Flame_Step_Effect_Proto_Lava_Test_Variant': { + 'hash': 41226, + 'name': 'Flame_Step_Effect_Proto_Lava_Test_Variant', + 'embedded': { + 'Flame_Step_Effect_Proto_Lava_Test_Variant_63786': { + 'hash': 63786, + 'name': 'Flame_Step_Effect_Proto_Lava_Test_Variant', + 'savables': {} + }, + 'Heating_Bit_26176': { + 'hash': 26176, + 'name': 'Heating_Bit', + 'savables': {} + }, + 'Hurting_Bit_26178': { + 'hash': 26178, + 'name': 'Hurting_Bit', + 'savables': {} + } + } + }, + 'Flame_Step_Effect_Proto_Vent_test': { + 'hash': 5142, + 'name': 'Flame_Step_Effect_Proto_Vent_test', + 'embedded': { + 'Flame_Step_Effect_Proto_Vent_test_10768': { + 'hash': 10768, + 'name': 'Flame_Step_Effect_Proto_Vent_test', + 'savables': {} + }, + 'Heating_Bit_26176': { + 'hash': 26176, + 'name': 'Heating_Bit', + 'savables': {} + }, + 'Hurting_Bit_26178': { + 'hash': 26178, + 'name': 'Hurting_Bit', + 'savables': {} + } + } + }, + 'Flaming_Coalbed': { + 'hash': 13480, + 'name': 'Flaming_Coalbed', + 'embedded': { + 'Flaming_Coalbed_26204': { + 'hash': 26204, + 'name': 'Flaming_Coalbed', + 'savables': {} + }, + 'Heating_Bit_26176': { + 'hash': 26176, + 'name': 'Heating_Bit', + 'savables': {} + }, + 'Hurting_Bit_26178': { + 'hash': 26178, + 'name': 'Hurting_Bit', + 'savables': {} + } + } + }, + 'Flashlight_Lantern': { + 'hash': 23642, + 'name': 'Flashlight_Lantern', + 'embedded': { + 'Fire_54948': { + 'hash': 54948, + 'name': 'Fire', + 'savables': { + 'Fire': { + 'hash': 3457519710, + 'name': 'Fire' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Flashlight_Lantern_23664': { + 'hash': 23664, + 'name': 'Flashlight_Lantern', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Fuel_Dock_63110': { + 'hash': 63110, + 'name': 'Fuel_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'flashlight_body_63430': { + 'hash': 63430, + 'name': 'flashlight_body', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'flashlight_body_pin_01_63422': { + 'hash': 63422, + 'name': 'flashlight_body_pin_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'flashlight_body_pin_02_63418': { + 'hash': 63418, + 'name': 'flashlight_body_pin_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'flashlight_body_pin_03_63414': { + 'hash': 63414, + 'name': 'flashlight_body_pin_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'flashlight_focusCylinder_63410': { + 'hash': 63410, + 'name': 'flashlight_focusCylinder', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'flashlight_fuelDoor_axel_63402': { + 'hash': 63402, + 'name': 'flashlight_fuelDoor_axel', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'flashlight_fuelDoor_body_63398': { + 'hash': 63398, + 'name': 'flashlight_fuelDoor_body', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'flashlight_handle_body_63394': { + 'hash': 63394, + 'name': 'flashlight_handle_body', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'flashlight_handle_pin_01_63390': { + 'hash': 63390, + 'name': 'flashlight_handle_pin_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'flashlight_handle_pin_02_63426': { + 'hash': 63426, + 'name': 'flashlight_handle_pin_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'flashlight_handle_wraps_63406': { + 'hash': 63406, + 'name': 'flashlight_handle_wraps', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Flint': { + 'hash': 39484, + 'name': 'Flint', + 'embedded': { + 'Flint_39368': { + 'hash': 39368, + 'name': 'Flint', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Insert_Primitive_SwordType_7796': { + 'hash': 7796, + 'name': 'Insert_Primitive_SwordType', + 'savables': {} + } + } + }, + 'Flint_Training': { + 'hash': 2356, + 'name': 'Flint_Training', + 'embedded': { + 'Flint_Training_2350': { + 'hash': 2350, + 'name': 'Flint_Training', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Float_Range_Operator': { + 'hash': 50768, + 'name': 'Float_Range_Operator', + 'embedded': { + 'Float_Range_Operator_13344': { + 'hash': 13344, + 'name': 'Float_Range_Operator', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'LogicFloatRangeReceiver': { + 'hash': 2700376822, + 'name': 'LogicFloatRangeReceiver' + } + } + } + } + }, + 'Flower_Blue': { + 'hash': 23514, + 'name': 'Flower_Blue', + 'embedded': { + 'Flower_Blue_28136': { + 'hash': 28136, + 'name': 'Flower_Blue', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Flower_Red': { + 'hash': 61634, + 'name': 'Flower_Red', + 'embedded': { + 'Flower_Red_27280': { + 'hash': 27280, + 'name': 'Flower_Red', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'FlyCam_Player': { + 'hash': 44058, + 'name': 'FlyCam_Player', + 'embedded': {} + }, + 'Forage_Basket_Bag': { + 'hash': 39880, + 'name': 'Forage_Basket_Bag', + 'embedded': { + 'Bag_Body_42972': { + 'hash': 42972, + 'name': 'Bag_Body', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Dock_BL_42978': { + 'hash': 42978, + 'name': 'Dock_BL', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_BM_42976': { + 'hash': 42976, + 'name': 'Dock_BM', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_BR_42974': { + 'hash': 42974, + 'name': 'Dock_BR', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_ML_42984': { + 'hash': 42984, + 'name': 'Dock_ML', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_MM_42982': { + 'hash': 42982, + 'name': 'Dock_MM', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_MR_42980': { + 'hash': 42980, + 'name': 'Dock_MR', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_TL_42990': { + 'hash': 42990, + 'name': 'Dock_TL', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_TM_42988': { + 'hash': 42988, + 'name': 'Dock_TM', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_TR_42986': { + 'hash': 42986, + 'name': 'Dock_TR', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Forage_Basket_Bag_43012': { + 'hash': 43012, + 'name': 'Forage_Basket_Bag', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_Bag_Attach_30776': { + 'hash': 30776, + 'name': 'Slot_Bag_Attach', + 'savables': {} + }, + 'Slot_Bag_Attach_55164': { + 'hash': 55164, + 'name': 'Slot_Bag_Attach', + 'savables': {} + }, + 'basket_bag_handle_wraps_56574': { + 'hash': 56574, + 'name': 'basket_bag_handle_wraps', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_bottomStick_01_56570': { + 'hash': 56570, + 'name': 'basket_bottomStick_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_bottomStick_02_56610': { + 'hash': 56610, + 'name': 'basket_bottomStick_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_bottomStick_03_56558': { + 'hash': 56558, + 'name': 'basket_bottomStick_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_bottomStick_04_56618': { + 'hash': 56618, + 'name': 'basket_bottomStick_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_bottomStick_05_56614': { + 'hash': 56614, + 'name': 'basket_bottomStick_05', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_handle_56602': { + 'hash': 56602, + 'name': 'basket_handle', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_outerPillar_01_56554': { + 'hash': 56554, + 'name': 'basket_outerPillar_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_outerPillar_02_56566': { + 'hash': 56566, + 'name': 'basket_outerPillar_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_outerPillar_03_56622': { + 'hash': 56622, + 'name': 'basket_outerPillar_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_outerPillar_04_56550': { + 'hash': 56550, + 'name': 'basket_outerPillar_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_outerPillar_05_56590': { + 'hash': 56590, + 'name': 'basket_outerPillar_05', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_rim_01_56598': { + 'hash': 56598, + 'name': 'basket_rim_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_rim_02_56578': { + 'hash': 56578, + 'name': 'basket_rim_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_rim_03_56562': { + 'hash': 56562, + 'name': 'basket_rim_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_thatch_body_56594': { + 'hash': 56594, + 'name': 'basket_thatch_body', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_topStick_01_56546': { + 'hash': 56546, + 'name': 'basket_topStick_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_topStick_02_56606': { + 'hash': 56606, + 'name': 'basket_topStick_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_topStick_03_56534': { + 'hash': 56534, + 'name': 'basket_topStick_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_topStick_04_56586': { + 'hash': 56586, + 'name': 'basket_topStick_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_topStick_05_56538': { + 'hash': 56538, + 'name': 'basket_topStick_05', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_topStick_06_56582': { + 'hash': 56582, + 'name': 'basket_topStick_06', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_top_rim_56542': { + 'hash': 56542, + 'name': 'basket_top_rim', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Forage_Side_Pouch_Attachment': { + 'hash': 32874, + 'name': 'Forage_Side_Pouch_Attachment', + 'embedded': { + 'Dock_45700': { + 'hash': 45700, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62078': { + 'hash': 62078, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Forage_Side_Pouch_Attachment_7868': { + 'hash': 7868, + 'name': 'Forage_Side_Pouch_Attachment', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Insert_Bag_Attach_7796': { + 'hash': 7796, + 'name': 'Insert_Bag_Attach', + 'savables': {} + }, + 'Storage_62414': { + 'hash': 62414, + 'name': 'Storage', + 'savables': {} + }, + 'forage_basket_attachment_cover_27470': { + 'hash': 27470, + 'name': 'forage_basket_attachment_cover', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'forage_basket_attachment_knot_01_27466': { + 'hash': 27466, + 'name': 'forage_basket_attachment_knot_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'forage_basket_attachment_stick_01_30790': { + 'hash': 30790, + 'name': 'forage_basket_attachment_stick_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'forage_basket_attachment_stick_02_30786': { + 'hash': 30786, + 'name': 'forage_basket_attachment_stick_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'forage_basket_rim_01_30798': { + 'hash': 30798, + 'name': 'forage_basket_rim_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'forage_basket_rim_02_30794': { + 'hash': 30794, + 'name': 'forage_basket_rim_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Forest_Chunk_Point_Generator': { + 'hash': 45732, + 'name': 'Forest_Chunk_Point_Generator', + 'embedded': { + 'Forest_Chunk_Point_Generator_16642': { + 'hash': 16642, + 'name': 'Forest_Chunk_Point_Generator', + 'savables': {} + } + } + }, + 'Forest_Population': { + 'hash': 18818, + 'name': 'Forest_Population', + 'embedded': { + 'Forest_Population_16642': { + 'hash': 16642, + 'name': 'Forest_Population', + 'savables': { + 'BasicPopulationFolder': { + 'hash': 1931537627, + 'name': 'BasicPopulationFolder' + } + } + } + } + }, + 'Forge': { + 'hash': 11872, + 'name': 'Forge', + 'embedded': { + 'Fire_30100': { + 'hash': 30100, + 'name': 'Fire', + 'savables': { + 'Fire': { + 'hash': 3457519710, + 'name': 'Fire' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Forge_61848': { + 'hash': 61848, + 'name': 'Forge', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + }, + 'Forge_Area_43486': { + 'hash': 43486, + 'name': 'Forge_Area', + 'savables': {} + } + } + }, + 'Forge_Training': { + 'hash': 33628, + 'name': 'Forge_Training', + 'embedded': { + 'Forge_Training_31154': { + 'hash': 31154, + 'name': 'Forge_Training', + 'savables': {} + }, + 'Heat_Area_43486': { + 'hash': 43486, + 'name': 'Heat_Area', + 'savables': {} + } + } + }, + 'Friend_Request_Token': { + 'hash': 15314, + 'name': 'Friend_Request_Token', + 'embedded': {} + }, + 'Fruit_Tree_Path': { + 'hash': 40982, + 'name': 'Fruit_Tree_Path', + 'embedded': { + 'Fruit_Tree_Path_54338': { + 'hash': 54338, + 'name': 'Fruit_Tree_Path', + 'savables': { + 'PopulationPath': { + 'hash': 7704646, + 'name': 'PopulationPath' + } + } + } + } + }, + 'Gacha_Handle_': { + 'hash': 34422, + 'name': 'Gacha_Handle_', + 'embedded': { + 'Gacha_Handle__58484': { + 'hash': 58484, + 'name': 'Gacha_Handle_', + 'savables': {} + }, + 'Handle_Pickup_13422': { + 'hash': 13422, + 'name': 'Handle_Pickup', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Garlic_Full_Burnt': { + 'hash': 52934, + 'name': 'Garlic_Full_Burnt', + 'embedded': { + 'Cooking_64222': { + 'hash': 64222, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Garlic_Full_Burnt_52596': { + 'hash': 52596, + 'name': 'Garlic_Full_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Garlic_Full_Cooked': { + 'hash': 52530, + 'name': 'Garlic_Full_Cooked', + 'embedded': { + 'Cooking_63850': { + 'hash': 63850, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Garlic_Full_Cooked_52192': { + 'hash': 52192, + 'name': 'Garlic_Full_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Garlic_Full_Ripe': { + 'hash': 52126, + 'name': 'Garlic_Full_Ripe', + 'embedded': { + 'Cooking_61942': { + 'hash': 61942, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Garlic_Full_Ripe_49740': { + 'hash': 49740, + 'name': 'Garlic_Full_Ripe', + 'savables': { + 'BuildupPickup': { + 'hash': 3373651539, + 'name': 'BuildupPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Leaves_Parent_41624': { + 'hash': 41624, + 'name': 'Leaves_Parent', + 'savables': {} + }, + 'Root_Parent_41626': { + 'hash': 41626, + 'name': 'Root_Parent', + 'savables': {} + } + } + }, + 'Garlic_Full_Unripe': { + 'hash': 49162, + 'name': 'Garlic_Full_Unripe', + 'embedded': { + 'Cooking_61546': { + 'hash': 61546, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Garlic_Full_Unripe_48792': { + 'hash': 48792, + 'name': 'Garlic_Full_Unripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Garlic_Half_Burnt': { + 'hash': 60930, + 'name': 'Garlic_Half_Burnt', + 'embedded': { + 'Cooking_36210': { + 'hash': 36210, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Garlic_Half_Burnt_60592': { + 'hash': 60592, + 'name': 'Garlic_Half_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Garlic_Half_Cooked': { + 'hash': 60526, + 'name': 'Garlic_Half_Cooked', + 'embedded': { + 'Cooking_35152': { + 'hash': 35152, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Garlic_Half_Cooked_60188': { + 'hash': 60188, + 'name': 'Garlic_Half_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Garlic_Half_Ripe': { + 'hash': 60122, + 'name': 'Garlic_Half_Ripe', + 'embedded': { + 'Cooking_34454': { + 'hash': 34454, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Garlic_Half_Ripe_59784': { + 'hash': 59784, + 'name': 'Garlic_Half_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Garlic_Half_Unripe': { + 'hash': 59718, + 'name': 'Garlic_Half_Unripe', + 'embedded': { + 'Cooking_34116': { + 'hash': 34116, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Garlic_Half_Unripe_59380': { + 'hash': 59380, + 'name': 'Garlic_Half_Unripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Garlic_Leaves': { + 'hash': 1266, + 'name': 'Garlic_Leaves', + 'embedded': { + 'Garlic_Leaves_57126': { + 'hash': 57126, + 'name': 'Garlic_Leaves', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'PullPickup_32134': { + 'hash': 32134, + 'name': 'PullPickup', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Garlic_Roots': { + 'hash': 57564, + 'name': 'Garlic_Roots', + 'embedded': { + 'Garlic_Roots_34536': { + 'hash': 34536, + 'name': 'Garlic_Roots', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'PullPickup_32134': { + 'hash': 32134, + 'name': 'PullPickup', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Geode_Tier_1': { + 'hash': 59336, + 'name': 'Geode_Tier_1', + 'embedded': { + 'Geode_Tier_1_56136': { + 'hash': 56136, + 'name': 'Geode_Tier_1', + 'savables': { + 'MultiHandPickup': { + 'hash': 1556697998, + 'name': 'MultiHandPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Geode_Tier_1_Half_01': { + 'hash': 29678, + 'name': 'Geode_Tier_1_Half_01', + 'embedded': { + 'Geode_Tier_1_Half_01_26864': { + 'hash': 26864, + 'name': 'Geode_Tier_1_Half_01', + 'savables': { + 'MultiHandPickup': { + 'hash': 1556697998, + 'name': 'MultiHandPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Geode_Tier_1_Half_02': { + 'hash': 38512, + 'name': 'Geode_Tier_1_Half_02', + 'embedded': { + 'Geode_Tier_1_Half_02_35456': { + 'hash': 35456, + 'name': 'Geode_Tier_1_Half_02', + 'savables': { + 'MultiHandPickup': { + 'hash': 1556697998, + 'name': 'MultiHandPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Gift_Mail_Box': { + 'hash': 56348, + 'name': 'Gift_Mail_Box', + 'embedded': { + 'Gift_Mail_Box_17050': { + 'hash': 17050, + 'name': 'Gift_Mail_Box', + 'savables': { + 'MultiHandPickup': { + 'hash': 1556697998, + 'name': 'MultiHandPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'SentGift': { + 'hash': 661497638, + 'name': 'SentGift' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Glowing_Mushroom_Recipe_Burnt_Stew': { + 'hash': 47384, + 'name': 'Glowing_Mushroom_Recipe_Burnt_Stew', + 'embedded': {} + }, + 'Glowing_Mushroom_Recipe_Cooked_Stew': { + 'hash': 47362, + 'name': 'Glowing_Mushroom_Recipe_Cooked_Stew', + 'embedded': {} + }, + 'Glowing_Mushroom_Recipe_Raw_Stew': { + 'hash': 44774, + 'name': 'Glowing_Mushroom_Recipe_Raw_Stew', + 'embedded': {} + }, + 'GoldCoin': { + 'hash': 61648, + 'name': 'GoldCoin', + 'embedded': { + 'GoldCoin_39174': { + 'hash': 39174, + 'name': 'GoldCoin', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_12524': { + 'hash': 12524, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Gold_Boulder': { + 'hash': 2584, + 'name': 'Gold_Boulder', + 'embedded': { + 'Gold_Boulder_3932': { + 'hash': 3932, + 'name': 'Gold_Boulder', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Spawn_Origin_7418': { + 'hash': 7418, + 'name': 'Spawn_Origin', + 'savables': {} + } + } + }, + 'Gold_Boulder_Parts': { + 'hash': 47738, + 'name': 'Gold_Boulder_Parts', + 'embedded': { + 'Gold_Boulder_Part_01_52930': { + 'hash': 52930, + 'name': 'Gold_Boulder_Part_01', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Gold_Boulder_Part_02_52926': { + 'hash': 52926, + 'name': 'Gold_Boulder_Part_02', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Gold_Boulder_Part_03_52922': { + 'hash': 52922, + 'name': 'Gold_Boulder_Part_03', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Gold_Boulder_Part_04_52934': { + 'hash': 52934, + 'name': 'Gold_Boulder_Part_04', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Gold_Boulder_Parts_52902': { + 'hash': 52902, + 'name': 'Gold_Boulder_Parts', + 'savables': {} + } + } + }, + 'Gold_Ingot': { + 'hash': 30092, + 'name': 'Gold_Ingot', + 'embedded': { + 'Gold_Ingot_29980': { + 'hash': 29980, + 'name': 'Gold_Ingot', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_13048': { + 'hash': 13048, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + } + } + }, + 'Gold_Ore': { + 'hash': 61650, + 'name': 'Gold_Ore', + 'embedded': { + 'Gold_Ore_39896': { + 'hash': 39896, + 'name': 'Gold_Ore', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Gotera': { + 'hash': 9466, + 'name': 'Gotera', + 'embedded': { + 'Dart_Shooter_56642': { + 'hash': 56642, + 'name': 'Dart_Shooter', + 'savables': {} + }, + 'Erupt_Area_19858': { + 'hash': 19858, + 'name': 'Erupt_Area', + 'savables': {} + }, + 'Gotera_7278': { + 'hash': 7278, + 'name': 'Gotera', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Gotera_AI_22350': { + 'hash': 22350, + 'name': 'Gotera_AI', + 'savables': {} + }, + 'Gotera_Body_10036': { + 'hash': 10036, + 'name': 'Gotera_Body', + 'savables': {} + }, + 'Impactor_63610': { + 'hash': 63610, + 'name': 'Impactor', + 'savables': {} + }, + 'Physical_Torso_8164': { + 'hash': 8164, + 'name': 'Physical_Torso', + 'savables': {} + }, + 'Seed_Spray_1172': { + 'hash': 1172, + 'name': 'Seed_Spray', + 'savables': {} + }, + 'Spawn_Drop_16220': { + 'hash': 16220, + 'name': 'Spawn_Drop', + 'savables': {} + }, + 'root_jnt_17218': { + 'hash': 17218, + 'name': 'root_jnt', + 'savables': {} + } + } + }, + 'Gotera_Ash_Bomb': { + 'hash': 56764, + 'name': 'Gotera_Ash_Bomb', + 'embedded': { + 'AI_16472': { + 'hash': 16472, + 'name': 'AI', + 'savables': {} + }, + 'Explosion_7834': { + 'hash': 7834, + 'name': 'Explosion', + 'savables': {} + }, + 'Gotera_Ash_Bomb_40780': { + 'hash': 40780, + 'name': 'Gotera_Ash_Bomb', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Gotera_Ash_Variant': { + 'hash': 61448, + 'name': 'Gotera_Ash_Variant', + 'embedded': { + 'Dart_Shooter_6022': { + 'hash': 6022, + 'name': 'Dart_Shooter', + 'savables': {} + }, + 'Erupt_Area_19858': { + 'hash': 19858, + 'name': 'Erupt_Area', + 'savables': {} + }, + 'Gotera_AI_22350': { + 'hash': 22350, + 'name': 'Gotera_AI', + 'savables': {} + }, + 'Gotera_Ash_Variant_7278': { + 'hash': 7278, + 'name': 'Gotera_Ash_Variant', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Gotera_Body_10036': { + 'hash': 10036, + 'name': 'Gotera_Body', + 'savables': {} + }, + 'Impactor_63610': { + 'hash': 63610, + 'name': 'Impactor', + 'savables': {} + }, + 'Physical_Torso_8164': { + 'hash': 8164, + 'name': 'Physical_Torso', + 'savables': {} + }, + 'Seed_Spray_1172': { + 'hash': 1172, + 'name': 'Seed_Spray', + 'savables': {} + }, + 'Spawn_Drop_16220': { + 'hash': 16220, + 'name': 'Spawn_Drop', + 'savables': {} + }, + 'root_jnt_17218': { + 'hash': 17218, + 'name': 'root_jnt', + 'savables': {} + } + } + }, + 'Gotera_Big_Dart': { + 'hash': 26780, + 'name': 'Gotera_Big_Dart', + 'embedded': { + 'Dart_62940': { + 'hash': 62940, + 'name': 'Dart', + 'savables': {} + }, + 'Gotera_Big_Dart_3092': { + 'hash': 3092, + 'name': 'Gotera_Big_Dart', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Gotera_Big_Seed_Spray': { + 'hash': 18468, + 'name': 'Gotera_Big_Seed_Spray', + 'embedded': { + 'Gotera_Big_Seed_Spray_44772': { + 'hash': 44772, + 'name': 'Gotera_Big_Seed_Spray', + 'savables': {} + } + } + }, + 'Gotera_Birch_Variant': { + 'hash': 2370, + 'name': 'Gotera_Birch_Variant', + 'embedded': { + 'Dart_Shooter_6022': { + 'hash': 6022, + 'name': 'Dart_Shooter', + 'savables': {} + }, + 'Erupt_Area_19858': { + 'hash': 19858, + 'name': 'Erupt_Area', + 'savables': {} + }, + 'Gotera_AI_22350': { + 'hash': 22350, + 'name': 'Gotera_AI', + 'savables': {} + }, + 'Gotera_Birch_Variant_7278': { + 'hash': 7278, + 'name': 'Gotera_Birch_Variant', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Gotera_Body_10036': { + 'hash': 10036, + 'name': 'Gotera_Body', + 'savables': {} + }, + 'Impactor_63610': { + 'hash': 63610, + 'name': 'Impactor', + 'savables': {} + }, + 'Physical_Torso_8164': { + 'hash': 8164, + 'name': 'Physical_Torso', + 'savables': {} + }, + 'Seed_Spray_1172': { + 'hash': 1172, + 'name': 'Seed_Spray', + 'savables': {} + }, + 'Spawn_Drop_16220': { + 'hash': 16220, + 'name': 'Spawn_Drop', + 'savables': {} + }, + 'root_jnt_17218': { + 'hash': 17218, + 'name': 'root_jnt', + 'savables': {} + } + } + }, + 'Gotera_Dart': { + 'hash': 3088, + 'name': 'Gotera_Dart', + 'embedded': { + 'Dart_62940': { + 'hash': 62940, + 'name': 'Dart', + 'savables': {} + }, + 'Gotera_Dart_3092': { + 'hash': 3092, + 'name': 'Gotera_Dart', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Gotera_Redwood_Variant': { + 'hash': 27128, + 'name': 'Gotera_Redwood_Variant', + 'embedded': { + 'Dart_Shooter_56642': { + 'hash': 56642, + 'name': 'Dart_Shooter', + 'savables': {} + }, + 'Erupt_Area_19858': { + 'hash': 19858, + 'name': 'Erupt_Area', + 'savables': {} + }, + 'Gotera_AI_22350': { + 'hash': 22350, + 'name': 'Gotera_AI', + 'savables': {} + }, + 'Gotera_Body_10036': { + 'hash': 10036, + 'name': 'Gotera_Body', + 'savables': {} + }, + 'Gotera_Redwood_Variant_7278': { + 'hash': 7278, + 'name': 'Gotera_Redwood_Variant', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Impactor_19042': { + 'hash': 19042, + 'name': 'Impactor', + 'savables': {} + }, + 'Impactor_19160': { + 'hash': 19160, + 'name': 'Impactor', + 'savables': {} + }, + 'Impactor_63610': { + 'hash': 63610, + 'name': 'Impactor', + 'savables': {} + }, + 'Physical_Torso_8164': { + 'hash': 8164, + 'name': 'Physical_Torso', + 'savables': {} + }, + 'Seed_Spray_1172': { + 'hash': 1172, + 'name': 'Seed_Spray', + 'savables': {} + }, + 'Spawn_Drop_16220': { + 'hash': 16220, + 'name': 'Spawn_Drop', + 'savables': {} + }, + 'root_jnt_17218': { + 'hash': 17218, + 'name': 'root_jnt', + 'savables': {} + } + } + }, + 'Gotera_Seed_Spray': { + 'hash': 31540, + 'name': 'Gotera_Seed_Spray', + 'embedded': { + 'Gotera_Seed_Spray_44772': { + 'hash': 44772, + 'name': 'Gotera_Seed_Spray', + 'savables': {} + } + } + }, + 'Gotera_Seedling_Orb': { + 'hash': 59342, + 'name': 'Gotera_Seedling_Orb', + 'embedded': { + 'Gotera_Seedling_Orb_59268': { + 'hash': 59268, + 'name': 'Gotera_Seedling_Orb', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Stun_Explosion_58370': { + 'hash': 58370, + 'name': 'Stun_Explosion', + 'savables': {} + } + } + }, + 'Gotera_Walnut_Bomb': { + 'hash': 35174, + 'name': 'Gotera_Walnut_Bomb', + 'embedded': { + 'Explosion_7834': { + 'hash': 7834, + 'name': 'Explosion', + 'savables': {} + }, + 'Gotera_Walnut_Bomb_40780': { + 'hash': 40780, + 'name': 'Gotera_Walnut_Bomb', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Gotera_Walnut_Variant': { + 'hash': 38096, + 'name': 'Gotera_Walnut_Variant', + 'embedded': { + 'Big_Dart_Shooter_(1)_4010': { + 'hash': 4010, + 'name': 'Big_Dart_Shooter_(1)', + 'savables': {} + }, + 'Big_Dart_Shooter_(2)_4572': { + 'hash': 4572, + 'name': 'Big_Dart_Shooter_(2)', + 'savables': {} + }, + 'Big_Dart_Shooter_5974': { + 'hash': 5974, + 'name': 'Big_Dart_Shooter', + 'savables': {} + }, + 'Dart_Shooter_(1)_37542': { + 'hash': 37542, + 'name': 'Dart_Shooter_(1)', + 'savables': {} + }, + 'Dart_Shooter_56642': { + 'hash': 56642, + 'name': 'Dart_Shooter', + 'savables': {} + }, + 'Dart_Shooter_5986': { + 'hash': 5986, + 'name': 'Dart_Shooter', + 'savables': {} + }, + 'Dart_Shooter_5998': { + 'hash': 5998, + 'name': 'Dart_Shooter', + 'savables': {} + }, + 'Dart_Shooter_6010': { + 'hash': 6010, + 'name': 'Dart_Shooter', + 'savables': {} + }, + 'Dart_Shooter_6022': { + 'hash': 6022, + 'name': 'Dart_Shooter', + 'savables': {} + }, + 'Erupt_Area_19858': { + 'hash': 19858, + 'name': 'Erupt_Area', + 'savables': {} + }, + 'Gotera_AI_22350': { + 'hash': 22350, + 'name': 'Gotera_AI', + 'savables': {} + }, + 'Gotera_Body_10036': { + 'hash': 10036, + 'name': 'Gotera_Body', + 'savables': {} + }, + 'Gotera_Walnut_Variant_7278': { + 'hash': 7278, + 'name': 'Gotera_Walnut_Variant', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Impactor_63610': { + 'hash': 63610, + 'name': 'Impactor', + 'savables': {} + }, + 'Physical_Torso_8164': { + 'hash': 8164, + 'name': 'Physical_Torso', + 'savables': {} + }, + 'Seed_Spray_1172': { + 'hash': 1172, + 'name': 'Seed_Spray', + 'savables': {} + }, + 'Spawn_Drop_16220': { + 'hash': 16220, + 'name': 'Spawn_Drop', + 'savables': {} + }, + 'root_jnt_17218': { + 'hash': 17218, + 'name': 'root_jnt', + 'savables': {} + } + } + }, + 'Gourd_Canteen': { + 'hash': 29032, + 'name': 'Gourd_Canteen', + 'embedded': { + 'Gourd_Canteen_26784': { + 'hash': 26784, + 'name': 'Gourd_Canteen', + 'savables': { + 'LiquidContainer': { + 'hash': 4179293747, + 'name': 'LiquidContainer' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Lid_Pickup_27480': { + 'hash': 27480, + 'name': 'Lid_Pickup', + 'savables': { + 'CapPickup': { + 'hash': 3082855726, + 'name': 'CapPickup' + } + } + } + } + }, + 'Grass_Clump': { + 'hash': 57872, + 'name': 'Grass_Clump', + 'embedded': { + 'Fire_30100': { + 'hash': 30100, + 'name': 'Fire', + 'savables': { + 'Fire': { + 'hash': 3457519710, + 'name': 'Fire' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Grass_Clump_12138': { + 'hash': 12138, + 'name': 'Grass_Clump', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'RaycastCrafter': { + 'hash': 2815374842, + 'name': 'RaycastCrafter' + } + } + }, + 'Insert_Grass_7796': { + 'hash': 7796, + 'name': 'Insert_Grass', + 'savables': {} + } + } + }, + 'Gravestone_Parts': { + 'hash': 2596, + 'name': 'Gravestone_Parts', + 'embedded': { + 'Gravestone_Parts_37752': { + 'hash': 37752, + 'name': 'Gravestone_Parts', + 'savables': {} + }, + 'gravestone_base_LOD0_1602': { + 'hash': 1602, + 'name': 'gravestone_base_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'gravestone_brick_type1_LOD0_1578': { + 'hash': 1578, + 'name': 'gravestone_brick_type1_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'gravestone_brick_type1_LOD0_1596': { + 'hash': 1596, + 'name': 'gravestone_brick_type1_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'gravestone_brick_type1_LOD0_1604': { + 'hash': 1604, + 'name': 'gravestone_brick_type1_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'gravestone_brick_type1_LOD0_1608': { + 'hash': 1608, + 'name': 'gravestone_brick_type1_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'gravestone_brick_type2_LOD0_1590': { + 'hash': 1590, + 'name': 'gravestone_brick_type2_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'gravestone_brick_type2_LOD0_1606': { + 'hash': 1606, + 'name': 'gravestone_brick_type2_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'gravestone_brick_type2_LOD0_1610': { + 'hash': 1610, + 'name': 'gravestone_brick_type2_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'gravestone_brick_type2_LOD0_1614': { + 'hash': 1614, + 'name': 'gravestone_brick_type2_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'gravestone_brick_type3_LOD0_1572': { + 'hash': 1572, + 'name': 'gravestone_brick_type3_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'gravestone_brick_type3_LOD0_1594': { + 'hash': 1594, + 'name': 'gravestone_brick_type3_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'gravestone_brick_type3_LOD0_1600': { + 'hash': 1600, + 'name': 'gravestone_brick_type3_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'gravestone_brick_type3_LOD0_1612': { + 'hash': 1612, + 'name': 'gravestone_brick_type3_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'gravestone_brick_type4_LOD0_1576': { + 'hash': 1576, + 'name': 'gravestone_brick_type4_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'gravestone_brick_type4_LOD0_1582': { + 'hash': 1582, + 'name': 'gravestone_brick_type4_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'gravestone_brick_type4_LOD0_1586': { + 'hash': 1586, + 'name': 'gravestone_brick_type4_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'gravestone_spike_large_LOD0_1580': { + 'hash': 1580, + 'name': 'gravestone_spike_large_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'gravestone_spike_large_LOD0_1588': { + 'hash': 1588, + 'name': 'gravestone_spike_large_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'gravestone_spike_large_LOD0_1598': { + 'hash': 1598, + 'name': 'gravestone_spike_large_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'gravestone_spike_small_LOD0_1584': { + 'hash': 1584, + 'name': 'gravestone_spike_small_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'gravestone_spike_small_LOD0_1592': { + 'hash': 1592, + 'name': 'gravestone_spike_small_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'gravestone_torus_LOD0_1574': { + 'hash': 1574, + 'name': 'gravestone_torus_LOD0', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Great_Sword_Blade': { + 'hash': 63886, + 'name': 'Great_Sword_Blade', + 'embedded': { + 'Great_Sword_Blade_84': { + 'hash': 84, + 'name': 'Great_Sword_Blade', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_62004': { + 'hash': 62004, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_Large_SwordType_7796': { + 'hash': 7796, + 'name': 'Insert_Large_SwordType', + 'savables': {} + }, + 'metal_blade_greatsword_full_geo_LOD0_60392': { + 'hash': 60392, + 'name': 'metal_blade_greatsword_full_geo_LOD0', + 'savables': {} + } + } + }, + 'Greater_Gotera_Charge_Explosion': { + 'hash': 5316, + 'name': 'Greater_Gotera_Charge_Explosion', + 'embedded': { + 'Greater_Gotera_Charge_Explosion_58370': { + 'hash': 58370, + 'name': 'Greater_Gotera_Charge_Explosion', + 'savables': {} + } + } + }, + 'Greater_Gotera_Seed_Spray': { + 'hash': 13476, + 'name': 'Greater_Gotera_Seed_Spray', + 'embedded': { + 'Greater_Gotera_Seed_Spray_44772': { + 'hash': 44772, + 'name': 'Greater_Gotera_Seed_Spray', + 'savables': {} + } + } + }, + 'Green_Crystal_cluster_03': { + 'hash': 23836, + 'name': 'Green_Crystal_cluster_03', + 'embedded': { + 'Green_Crystal_cluster_03_54542': { + 'hash': 54542, + 'name': 'Green_Crystal_cluster_03', + 'savables': {} + } + } + }, + 'Guard': { + 'hash': 51672, + 'name': 'Guard', + 'embedded': { + 'Guard_51546': { + 'hash': 51546, + 'name': 'Guard', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_56294': { + 'hash': 56294, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_SwordType_Craft_39368': { + 'hash': 39368, + 'name': 'Insert_SwordType_Craft', + 'savables': {} + }, + 'Slot_SwordType_39370': { + 'hash': 39370, + 'name': 'Slot_SwordType', + 'savables': {} + } + } + }, + 'Guard_Fancy': { + 'hash': 62140, + 'name': 'Guard_Fancy', + 'embedded': { + 'Guard_Fancy_51546': { + 'hash': 51546, + 'name': 'Guard_Fancy', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_56592': { + 'hash': 56592, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_SwordType_Deco_39368': { + 'hash': 39368, + 'name': 'Insert_SwordType_Deco', + 'savables': {} + }, + 'Slot_SwordType_39370': { + 'hash': 39370, + 'name': 'Slot_SwordType', + 'savables': {} + } + } + }, + 'Guard_Handle': { + 'hash': 43186, + 'name': 'Guard_Handle', + 'embedded': { + 'Guard_Handle_51546': { + 'hash': 51546, + 'name': 'Guard_Handle', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Insert_Mid_39368': { + 'hash': 39368, + 'name': 'Insert_Mid', + 'savables': {} + }, + 'Slot_End_39370': { + 'hash': 39370, + 'name': 'Slot_End', + 'savables': {} + } + } + }, + 'Guard_Hemisphere': { + 'hash': 34428, + 'name': 'Guard_Hemisphere', + 'embedded': { + 'Guard_Hemisphere_51546': { + 'hash': 51546, + 'name': 'Guard_Hemisphere', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_56886': { + 'hash': 56886, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_SwordType_Deco_39368': { + 'hash': 39368, + 'name': 'Insert_SwordType_Deco', + 'savables': {} + }, + 'Slot_SwordType_39370': { + 'hash': 39370, + 'name': 'Slot_SwordType', + 'savables': {} + } + } + }, + 'Guard_Pointy_Ends': { + 'hash': 28160, + 'name': 'Guard_Pointy_Ends', + 'embedded': { + 'Guard_Pointy_Ends_51546': { + 'hash': 51546, + 'name': 'Guard_Pointy_Ends', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_57188': { + 'hash': 57188, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_SwordType_Craft_39368': { + 'hash': 39368, + 'name': 'Insert_SwordType_Craft', + 'savables': {} + }, + 'Slot_Multi_31108': { + 'hash': 31108, + 'name': 'Slot_Multi', + 'savables': {} + } + } + }, + 'Guard_Round_Ends': { + 'hash': 21776, + 'name': 'Guard_Round_Ends', + 'embedded': { + 'Guard_Round_Ends_51546': { + 'hash': 51546, + 'name': 'Guard_Round_Ends', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Insert_Mid_39368': { + 'hash': 39368, + 'name': 'Insert_Mid', + 'savables': {} + }, + 'Slot_End_39370': { + 'hash': 39370, + 'name': 'Slot_End', + 'savables': {} + } + } + }, + 'Guard_Straight_Ends': { + 'hash': 17348, + 'name': 'Guard_Straight_Ends', + 'embedded': { + 'Guard_Straight_Ends_51546': { + 'hash': 51546, + 'name': 'Guard_Straight_Ends', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_57430': { + 'hash': 57430, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_SwordType_Craft_39368': { + 'hash': 39368, + 'name': 'Insert_SwordType_Craft', + 'savables': {} + }, + 'Slot_Multi_30024': { + 'hash': 30024, + 'name': 'Slot_Multi', + 'savables': {} + } + } + }, + 'Gymnasium_Prefab_Spawner': { + 'hash': 25312, + 'name': 'Gymnasium_Prefab_Spawner', + 'embedded': { + 'Gymnasium_Prefab_Spawner_25334': { + 'hash': 25334, + 'name': 'Gymnasium_Prefab_Spawner', + 'savables': { + 'GymnasiumOnDemandPrefabSpawner': { + 'hash': 701033518, + 'name': 'GymnasiumOnDemandPrefabSpawner' + } + } + }, + 'Spawn_Area_4162': { + 'hash': 4162, + 'name': 'Spawn_Area', + 'savables': { + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + } + } + }, + 'Gymnasium_Teleport_Tablet': { + 'hash': 2718, + 'name': 'Gymnasium_Teleport_Tablet', + 'embedded': { + 'Collision_27112': { + 'hash': 27112, + 'name': 'Collision', + 'savables': {} + }, + 'Gymnasium_Teleport_Tablet_2062': { + 'hash': 2062, + 'name': 'Gymnasium_Teleport_Tablet', + 'savables': {} + } + } + }, + 'Gymnasium_Xp_Display_View': { + 'hash': 57304, + 'name': 'Gymnasium_Xp_Display_View', + 'embedded': { + 'Back_Button_17050': { + 'hash': 17050, + 'name': 'Back_Button', + 'savables': {} + }, + 'Forward_Button_17050': { + 'hash': 17050, + 'name': 'Forward_Button', + 'savables': {} + }, + 'Gymnasium_Xp_Display_View_57232': { + 'hash': 57232, + 'name': 'Gymnasium_Xp_Display_View', + 'savables': {} + }, + 'Increase_Button_17050': { + 'hash': 17050, + 'name': 'Increase_Button', + 'savables': {} + }, + 'Increase_Max_Button_17050': { + 'hash': 17050, + 'name': 'Increase_Max_Button', + 'savables': {} + }, + 'Reset_Button_17050': { + 'hash': 17050, + 'name': 'Reset_Button', + 'savables': {} + } + } + }, + 'Hammer': { + 'hash': 61660, + 'name': 'Hammer', + 'embedded': {} + }, + 'Hammer_Head': { + 'hash': 43146, + 'name': 'Hammer_Head', + 'embedded': { + 'Hammer_Head_42978': { + 'hash': 42978, + 'name': 'Hammer_Head', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_10366': { + 'hash': 10366, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_HammerType_End_Cap_52192': { + 'hash': 52192, + 'name': 'Insert_HammerType_End_Cap', + 'savables': {} + } + } + }, + 'Hammer_Head_Small': { + 'hash': 15476, + 'name': 'Hammer_Head_Small', + 'embedded': { + 'Hammer_Head_Small_18788': { + 'hash': 18788, + 'name': 'Hammer_Head_Small', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_10670': { + 'hash': 10670, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_HammerType_End_Cap_18784': { + 'hash': 18784, + 'name': 'Insert_HammerType_End_Cap', + 'savables': {} + } + } + }, + 'Hammer_Training': { + 'hash': 47018, + 'name': 'Hammer_Training', + 'embedded': { + 'Hammer_Training_44084': { + 'hash': 44084, + 'name': 'Hammer_Training', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Hand_Camera': { + 'hash': 59806, + 'name': 'Hand_Camera', + 'embedded': {} + }, + 'Handle_Bow': { + 'hash': 64410, + 'name': 'Handle_Bow', + 'embedded': { + 'Handle_Bow_1188': { + 'hash': 1188, + 'name': 'Handle_Bow', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_Grass_11474': { + 'hash': 11474, + 'name': 'Slot_Grass', + 'savables': {} + }, + 'Slot_Grass_29036': { + 'hash': 29036, + 'name': 'Slot_Grass', + 'savables': {} + } + } + }, + 'Handle_Fist': { + 'hash': 22988, + 'name': 'Handle_Fist', + 'embedded': { + 'Handle_Fist_45004': { + 'hash': 45004, + 'name': 'Handle_Fist', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_7356': { + 'hash': 7356, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Slot_Deco_22982': { + 'hash': 22982, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_22992': { + 'hash': 22992, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_23002': { + 'hash': 23002, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_54114': { + 'hash': 54114, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Multi_22990': { + 'hash': 22990, + 'name': 'Slot_Multi', + 'savables': {} + } + } + }, + 'Handle_Large_Branch': { + 'hash': 61098, + 'name': 'Handle_Large_Branch', + 'embedded': { + 'Handle_Large_Branch_61094': { + 'hash': 61094, + 'name': 'Handle_Large_Branch', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_Multi_20330': { + 'hash': 20330, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_Primitive_AxeType_55026': { + 'hash': 55026, + 'name': 'Slot_Primitive_AxeType', + 'savables': {} + } + } + }, + 'Handle_Large_Cool': { + 'hash': 25290, + 'name': 'Handle_Large_Cool', + 'embedded': { + 'Handle_Large_Cool_25294': { + 'hash': 25294, + 'name': 'Handle_Large_Cool', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_37768': { + 'hash': 37768, + 'name': 'Heat_Point', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Slot_EdgeType_Craft_43172': { + 'hash': 43172, + 'name': 'Slot_EdgeType_Craft', + 'savables': {} + }, + 'Slot_EdgeType_Craft_64610': { + 'hash': 64610, + 'name': 'Slot_EdgeType_Craft', + 'savables': {} + }, + 'Slot_Multi_29320': { + 'hash': 29320, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_Multi_43166': { + 'hash': 43166, + 'name': 'Slot_Multi', + 'savables': {} + } + } + }, + 'Handle_Large_Standard': { + 'hash': 43252, + 'name': 'Handle_Large_Standard', + 'embedded': {} + }, + 'Handle_Long_Straight': { + 'hash': 20300, + 'name': 'Handle_Long_Straight', + 'embedded': { + 'Dock_32818': { + 'hash': 32818, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Handle_Long_Straight_25294': { + 'hash': 25294, + 'name': 'Handle_Long_Straight', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_EdgeType_Craft_53492': { + 'hash': 53492, + 'name': 'Slot_EdgeType_Craft', + 'savables': {} + }, + 'Slot_EdgeType_Craft_53692': { + 'hash': 53692, + 'name': 'Slot_EdgeType_Craft', + 'savables': {} + }, + 'Slot_Multi_(1)_63178': { + 'hash': 63178, + 'name': 'Slot_Multi_(1)', + 'savables': {} + }, + 'Slot_Multi_53060': { + 'hash': 53060, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_Multi_53074': { + 'hash': 53074, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_Multi_63218': { + 'hash': 63218, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_Straight_Short_Sword_Type_63270': { + 'hash': 63270, + 'name': 'Slot_Straight_Short_Sword_Type', + 'savables': {} + }, + 'Slot_Straight_Short_Sword_Type_63318': { + 'hash': 63318, + 'name': 'Slot_Straight_Short_Sword_Type', + 'savables': {} + } + } + }, + 'Handle_Medium_Branch': { + 'hash': 61400, + 'name': 'Handle_Medium_Branch', + 'embedded': { + 'Handle_Medium_Branch_61404': { + 'hash': 61404, + 'name': 'Handle_Medium_Branch', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_EdgeType_Craft_45470': { + 'hash': 45470, + 'name': 'Slot_EdgeType_Craft', + 'savables': {} + }, + 'Slot_Multi_15462': { + 'hash': 15462, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_Multi_29458': { + 'hash': 29458, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_Multi_52880': { + 'hash': 52880, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_PommelType_55836': { + 'hash': 55836, + 'name': 'Slot_PommelType', + 'savables': {} + } + } + }, + 'Handle_Medium_Cool': { + 'hash': 61856, + 'name': 'Handle_Medium_Cool', + 'embedded': { + 'Handle_Medium_Cool_61852': { + 'hash': 61852, + 'name': 'Handle_Medium_Cool', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_8548': { + 'hash': 8548, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Slot_EdgeType_Craft_57058': { + 'hash': 57058, + 'name': 'Slot_EdgeType_Craft', + 'savables': {} + }, + 'Slot_EdgeType_Craft_59436': { + 'hash': 59436, + 'name': 'Slot_EdgeType_Craft', + 'savables': {} + }, + 'Slot_Multi_3558': { + 'hash': 3558, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_Multi_59224': { + 'hash': 59224, + 'name': 'Slot_Multi', + 'savables': {} + } + } + }, + 'Handle_Medium_Curved': { + 'hash': 19316, + 'name': 'Handle_Medium_Curved', + 'embedded': { + 'Handle_Medium_Curved_19318': { + 'hash': 19318, + 'name': 'Handle_Medium_Curved', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_9036': { + 'hash': 9036, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Slot_EdgeType_Craft_51182': { + 'hash': 51182, + 'name': 'Slot_EdgeType_Craft', + 'savables': {} + }, + 'Slot_Multi_7860': { + 'hash': 7860, + 'name': 'Slot_Multi', + 'savables': {} + } + } + }, + 'Handle_Medium_Ridged': { + 'hash': 60598, + 'name': 'Handle_Medium_Ridged', + 'embedded': { + 'Handle_Medium_Ridged_44084': { + 'hash': 44084, + 'name': 'Handle_Medium_Ridged', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_Pole_19996': { + 'hash': 19996, + 'name': 'Slot_Pole', + 'savables': {} + }, + 'Slot_Pole_64914': { + 'hash': 64914, + 'name': 'Slot_Pole', + 'savables': {} + } + } + }, + 'Handle_Medium_Standard': { + 'hash': 41438, + 'name': 'Handle_Medium_Standard', + 'embedded': { + 'Handle_Medium_Standard_44084': { + 'hash': 44084, + 'name': 'Handle_Medium_Standard', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_Pole_20070': { + 'hash': 20070, + 'name': 'Slot_Pole', + 'savables': {} + }, + 'Slot_Pole_64914': { + 'hash': 64914, + 'name': 'Slot_Pole', + 'savables': {} + } + } + }, + 'Handle_Medium_Straight': { + 'hash': 19180, + 'name': 'Handle_Medium_Straight', + 'embedded': { + 'Dock_39120': { + 'hash': 39120, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Handle_Medium_Straight_19154': { + 'hash': 19154, + 'name': 'Handle_Medium_Straight', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_EdgeType_Craft_53492': { + 'hash': 53492, + 'name': 'Slot_EdgeType_Craft', + 'savables': {} + }, + 'Slot_EdgeType_Craft_53692': { + 'hash': 53692, + 'name': 'Slot_EdgeType_Craft', + 'savables': {} + }, + 'Slot_Multi_(1)_63178': { + 'hash': 63178, + 'name': 'Slot_Multi_(1)', + 'savables': {} + }, + 'Slot_Multi_53060': { + 'hash': 53060, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_Multi_53074': { + 'hash': 53074, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_Multi_63218': { + 'hash': 63218, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_Straight_Short_Sword_Type_63270': { + 'hash': 63270, + 'name': 'Slot_Straight_Short_Sword_Type', + 'savables': {} + }, + 'Slot_Straight_Short_Sword_Type_63318': { + 'hash': 63318, + 'name': 'Slot_Straight_Short_Sword_Type', + 'savables': {} + } + } + }, + 'Handle_Round_Fist': { + 'hash': 3506, + 'name': 'Handle_Round_Fist', + 'embedded': { + 'Handle_Round_Fist_3514': { + 'hash': 3514, + 'name': 'Handle_Round_Fist', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_Deco_31482': { + 'hash': 31482, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_38156': { + 'hash': 38156, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_50738': { + 'hash': 50738, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_57746': { + 'hash': 57746, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Multi_54114': { + 'hash': 54114, + 'name': 'Slot_Multi', + 'savables': {} + } + } + }, + 'Handle_Short': { + 'hash': 42230, + 'name': 'Handle_Short', + 'embedded': { + 'Handle_Short_42104': { + 'hash': 42104, + 'name': 'Handle_Short', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_Large_SwordType_Craft_54356': { + 'hash': 54356, + 'name': 'Slot_Large_SwordType_Craft', + 'savables': {} + }, + 'Slot_Large_SwordType_Craft_6134': { + 'hash': 6134, + 'name': 'Slot_Large_SwordType_Craft', + 'savables': {} + }, + 'Slot_Multi_6136': { + 'hash': 6136, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_Multi_6138': { + 'hash': 6138, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_PommelType_20654': { + 'hash': 20654, + 'name': 'Slot_PommelType', + 'savables': {} + }, + 'Slot_PommelType_30776': { + 'hash': 30776, + 'name': 'Slot_PommelType', + 'savables': {} + } + } + }, + 'Handle_Short_C_Curve': { + 'hash': 34898, + 'name': 'Handle_Short_C_Curve', + 'embedded': { + 'Handle_Short_C_Curve_44084': { + 'hash': 44084, + 'name': 'Handle_Short_C_Curve', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_9524': { + 'hash': 9524, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Slot_Large_SwordType_Craft_5628': { + 'hash': 5628, + 'name': 'Slot_Large_SwordType_Craft', + 'savables': {} + }, + 'Slot_Large_SwordType_Craft_5714': { + 'hash': 5714, + 'name': 'Slot_Large_SwordType_Craft', + 'savables': {} + }, + 'Slot_Multi_5624': { + 'hash': 5624, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_Multi_5626': { + 'hash': 5626, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_PommelType_5686': { + 'hash': 5686, + 'name': 'Slot_PommelType', + 'savables': {} + }, + 'Slot_PommelType_5700': { + 'hash': 5700, + 'name': 'Slot_PommelType', + 'savables': {} + } + } + }, + 'Handle_Short_Cool': { + 'hash': 5920, + 'name': 'Handle_Short_Cool', + 'embedded': { + 'Handle_Short_Cool_5922': { + 'hash': 5922, + 'name': 'Handle_Short_Cool', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_51674': { + 'hash': 51674, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Slot_EdgeType_Craft_43890': { + 'hash': 43890, + 'name': 'Slot_EdgeType_Craft', + 'savables': {} + }, + 'Slot_Large_SwordType_Craft_33946': { + 'hash': 33946, + 'name': 'Slot_Large_SwordType_Craft', + 'savables': {} + }, + 'Slot_Multi_48480': { + 'hash': 48480, + 'name': 'Slot_Multi', + 'savables': {} + } + } + }, + 'Handle_Short_Pointy_End': { + 'hash': 28636, + 'name': 'Handle_Short_Pointy_End', + 'embedded': { + 'Handle_Short_Pointy_End_44084': { + 'hash': 44084, + 'name': 'Handle_Short_Pointy_End', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Heat_Point_Collection_10000': { + 'hash': 10000, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Slot_EdgeType_Craft_14502': { + 'hash': 14502, + 'name': 'Slot_EdgeType_Craft', + 'savables': {} + }, + 'Slot_Large_SwordType_Craft_9736': { + 'hash': 9736, + 'name': 'Slot_Large_SwordType_Craft', + 'savables': {} + }, + 'Slot_Multi_18472': { + 'hash': 18472, + 'name': 'Slot_Multi', + 'savables': {} + } + } + }, + 'Handle_Short_S_Curve': { + 'hash': 27820, + 'name': 'Handle_Short_S_Curve', + 'embedded': { + 'Handle_Short_S_Curve_44084': { + 'hash': 44084, + 'name': 'Handle_Short_S_Curve', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_Mid_20238': { + 'hash': 20238, + 'name': 'Slot_Mid', + 'savables': {} + }, + 'Slot_Mid_64914': { + 'hash': 64914, + 'name': 'Slot_Mid', + 'savables': {} + } + } + }, + 'Handle_Short_Taper': { + 'hash': 24198, + 'name': 'Handle_Short_Taper', + 'embedded': { + 'Handle_Short_Taper_24200': { + 'hash': 24200, + 'name': 'Handle_Short_Taper', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_Mid_20296': { + 'hash': 20296, + 'name': 'Slot_Mid', + 'savables': {} + }, + 'Slot_Mid_64914': { + 'hash': 64914, + 'name': 'Slot_Mid', + 'savables': {} + } + } + }, + 'Handle_Spear': { + 'hash': 20640, + 'name': 'Handle_Spear', + 'embedded': { + 'Handle_Spear_24200': { + 'hash': 24200, + 'name': 'Handle_Spear', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_Deco_4866': { + 'hash': 4866, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Pole_64914': { + 'hash': 64914, + 'name': 'Slot_Pole', + 'savables': {} + } + } + }, + 'Handle_Tonfa': { + 'hash': 57838, + 'name': 'Handle_Tonfa', + 'embedded': { + 'Handle_Tonfa_57844': { + 'hash': 57844, + 'name': 'Handle_Tonfa', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_EdgeType_Craft_52822': { + 'hash': 52822, + 'name': 'Slot_EdgeType_Craft', + 'savables': {} + }, + 'Slot_HammerType_End_Cap_47874': { + 'hash': 47874, + 'name': 'Slot_HammerType_End_Cap', + 'savables': {} + }, + 'Slot_Multi_64782': { + 'hash': 64782, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_Shield_37414': { + 'hash': 37414, + 'name': 'Slot_Shield', + 'savables': {} + } + } + }, + 'Handy_Cam': { + 'hash': 13790, + 'name': 'Handy_Cam', + 'embedded': {} + }, + 'Hanging_Health_Vine_01': { + 'hash': 52952, + 'name': 'Hanging_Health_Vine_01', + 'embedded': { + 'Directional_Encounter_43896': { + 'hash': 43896, + 'name': 'Directional_Encounter', + 'savables': { + 'CylindricalBoundsSurface': { + 'hash': 34507654, + 'name': 'CylindricalBoundsSurface' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + }, + 'Hanging_Health_Vine_01_6398': { + 'hash': 6398, + 'name': 'Hanging_Health_Vine_01', + 'savables': {} + } + } + }, + 'Hanging_Health_Vine_02': { + 'hash': 56796, + 'name': 'Hanging_Health_Vine_02', + 'embedded': { + 'Directional_Encounter_43896': { + 'hash': 43896, + 'name': 'Directional_Encounter', + 'savables': { + 'CylindricalBoundsSurface': { + 'hash': 34507654, + 'name': 'CylindricalBoundsSurface' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + }, + 'Hanging_Health_Vine_02_6398': { + 'hash': 6398, + 'name': 'Hanging_Health_Vine_02', + 'savables': {} + } + } + }, + 'Hanging_Health_Vine_03': { + 'hash': 53496, + 'name': 'Hanging_Health_Vine_03', + 'embedded': { + 'Directional_Encounter_43896': { + 'hash': 43896, + 'name': 'Directional_Encounter', + 'savables': { + 'CylindricalBoundsSurface': { + 'hash': 34507654, + 'name': 'CylindricalBoundsSurface' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + }, + 'Hanging_Health_Vine_03_6398': { + 'hash': 6398, + 'name': 'Hanging_Health_Vine_03', + 'savables': {} + } + } + }, + 'Hanging_Loot_Box_Platform': { + 'hash': 54462, + 'name': 'Hanging_Loot_Box_Platform', + 'embedded': { + 'Hanging_Loot_Box_Platform_12670': { + 'hash': 12670, + 'name': 'Hanging_Loot_Box_Platform', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Spawn_Boxes_(1)_18788': { + 'hash': 18788, + 'name': 'Spawn_Boxes_(1)', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + }, + 'Spawn_Boxes_(2)_18856': { + 'hash': 18856, + 'name': 'Spawn_Boxes_(2)', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + }, + 'Spawn_Boxes_(3)_18766': { + 'hash': 18766, + 'name': 'Spawn_Boxes_(3)', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + }, + 'Spawn_Boxes_53424': { + 'hash': 53424, + 'name': 'Spawn_Boxes', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + } + } + }, + 'Hanging_Loot_Sack': { + 'hash': 49658, + 'name': 'Hanging_Loot_Sack', + 'embedded': { + 'Box_5934': { + 'hash': 5934, + 'name': 'Box', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Hanging_Loot_Sack_12670': { + 'hash': 12670, + 'name': 'Hanging_Loot_Sack', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Link_5938': { + 'hash': 5938, + 'name': 'Link', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Hard_Metal_Small_Bits': { + 'hash': 62594, + 'name': 'Hard_Metal_Small_Bits', + 'embedded': { + 'Hard_Metal_Small_Bits_62578': { + 'hash': 62578, + 'name': 'Hard_Metal_Small_Bits', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Hard_Plate_Metal_Medium_Square': { + 'hash': 50988, + 'name': 'Hard_Plate_Metal_Medium_Square', + 'embedded': { + 'Hard_Plate_Metal_Medium_Square_51004': { + 'hash': 51004, + 'name': 'Hard_Plate_Metal_Medium_Square', + 'savables': { + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Mesh_51176': { + 'hash': 51176, + 'name': 'Mesh', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'hardPlate_metal_medium_square_LOD0_52344': { + 'hash': 52344, + 'name': 'hardPlate_metal_medium_square_LOD0', + 'savables': {} + } + } + }, + 'Healing_Pod': { + 'hash': 44360, + 'name': 'Healing_Pod', + 'embedded': { + 'Explosion_58370': { + 'hash': 58370, + 'name': 'Explosion', + 'savables': {} + }, + 'Healing_Pod_15532': { + 'hash': 15532, + 'name': 'Healing_Pod', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Insert_Deco_112': { + 'hash': 112, + 'name': 'Insert_Deco', + 'savables': {} + } + } + }, + 'Healing_Pod_Plant': { + 'hash': 48826, + 'name': 'Healing_Pod_Plant', + 'embedded': { + 'Healing_Pod_Plant_64192': { + 'hash': 64192, + 'name': 'Healing_Pod_Plant', + 'savables': {} + }, + 'PullPickup_51602': { + 'hash': 51602, + 'name': 'PullPickup', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Spawn_Buried_57238': { + 'hash': 57238, + 'name': 'Spawn_Buried', + 'savables': { + 'SpawnBuried': { + 'hash': 654225716, + 'name': 'SpawnBuried' + } + } + } + } + }, + 'Heart_Receptacle': { + 'hash': 56090, + 'name': 'Heart_Receptacle', + 'embedded': { + 'Fake_Interactable_64848': { + 'hash': 64848, + 'name': 'Fake_Interactable', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Heart_Receptacle_37620': { + 'hash': 37620, + 'name': 'Heart_Receptacle', + 'savables': {} + } + } + }, + 'Hebios_Buried_Spawn_Area': { + 'hash': 51290, + 'name': 'Hebios_Buried_Spawn_Area', + 'embedded': { + 'Hebios_Buried_Spawn_Area_51274': { + 'hash': 51274, + 'name': 'Hebios_Buried_Spawn_Area', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + } + } + }, + 'Hebios_Camp_Barren': { + 'hash': 56012, + 'name': 'Hebios_Camp_Barren', + 'embedded': {} + }, + 'Hebios_Camp_Barren_Dynamic': { + 'hash': 56012, + 'name': 'Hebios_Camp_Barren_Dynamic', + 'embedded': { + 'Closed_Crate_Spawner_26166': { + 'hash': 26166, + 'name': 'Closed_Crate_Spawner', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + }, + 'Enemy_Spawn_30256': { + 'hash': 30256, + 'name': 'Enemy_Spawn', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + }, + 'Hebios_Camp_Barren_Dynamic_53304': { + 'hash': 53304, + 'name': 'Hebios_Camp_Barren_Dynamic', + 'savables': {} + }, + 'Hebios_Camp_Fire_Spawner_55752': { + 'hash': 55752, + 'name': 'Hebios_Camp_Fire_Spawner', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + }, + 'Open_Crate_Spawner_48408': { + 'hash': 48408, + 'name': 'Open_Crate_Spawner', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + } + } + }, + 'Hebios_Camp_Spawner': { + 'hash': 43300, + 'name': 'Hebios_Camp_Spawner', + 'embedded': {} + }, + 'Hebios_Camp_Valley': { + 'hash': 42062, + 'name': 'Hebios_Camp_Valley', + 'embedded': { + 'Hebios_Camp_Valley_38962': { + 'hash': 38962, + 'name': 'Hebios_Camp_Valley', + 'savables': { + 'StaticGenerationParent': { + 'hash': 2975913730, + 'name': 'StaticGenerationParent' + } + } + } + } + }, + 'Hebios_Camp_Valley_Center_Section_NEW': { + 'hash': 5350, + 'name': 'Hebios_Camp_Valley_Center_Section_NEW', + 'embedded': {} + }, + 'Hebios_Camp_Valley_Center_Section_Pond': { + 'hash': 54680, + 'name': 'Hebios_Camp_Valley_Center_Section_Pond', + 'embedded': {} + }, + 'Hebios_Camp_Valley_Front_Section_Spike_Gate': { + 'hash': 42358, + 'name': 'Hebios_Camp_Valley_Front_Section_Spike_Gate', + 'embedded': {} + }, + 'Hebios_Camp_Valley_Front_Section_Stone_Cliff': { + 'hash': 19412, + 'name': 'Hebios_Camp_Valley_Front_Section_Stone_Cliff', + 'embedded': {} + }, + 'Hebios_Camp_Valley_Left_Section_Archway': { + 'hash': 40482, + 'name': 'Hebios_Camp_Valley_Left_Section_Archway', + 'embedded': {} + }, + 'Hebios_Camp_Valley_Left_Section_Hilly_Forest': { + 'hash': 37966, + 'name': 'Hebios_Camp_Valley_Left_Section_Hilly_Forest', + 'embedded': {} + }, + 'Hebios_Closed_Crate_Spawner': { + 'hash': 46524, + 'name': 'Hebios_Closed_Crate_Spawner', + 'embedded': { + 'Hebios_Closed_Crate_Spawner_19058': { + 'hash': 19058, + 'name': 'Hebios_Closed_Crate_Spawner', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + } + } + }, + 'Hebios_Crafted_Mould': { + 'hash': 22498, + 'name': 'Hebios_Crafted_Mould', + 'embedded': { + 'Hebios_Crafted_Mould_14710': { + 'hash': 14710, + 'name': 'Hebios_Crafted_Mould', + 'savables': { + 'Mould': { + 'hash': 391977879, + 'name': 'Mould' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'hebios_mould_centerFrame_grp_18498': { + 'hash': 18498, + 'name': 'hebios_mould_centerFrame_grp', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hebios_mould_emblem_grp_9986': { + 'hash': 9986, + 'name': 'hebios_mould_emblem_grp', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hebios_mould_frame_horizontal_grp_01_18458': { + 'hash': 18458, + 'name': 'hebios_mould_frame_horizontal_grp_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hebios_mould_frame_horizontal_grp_02_18482': { + 'hash': 18482, + 'name': 'hebios_mould_frame_horizontal_grp_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hebios_mould_frame_vertical_grp_01_18462': { + 'hash': 18462, + 'name': 'hebios_mould_frame_vertical_grp_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hebios_mould_frame_vertical_grp_02_18486': { + 'hash': 18486, + 'name': 'hebios_mould_frame_vertical_grp_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hebios_mould_grassKnot_grp_01_18450': { + 'hash': 18450, + 'name': 'hebios_mould_grassKnot_grp_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hebios_mould_grassKnot_grp_02_18446': { + 'hash': 18446, + 'name': 'hebios_mould_grassKnot_grp_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hebios_mould_grassKnot_grp_03_18502': { + 'hash': 18502, + 'name': 'hebios_mould_grassKnot_grp_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hebios_mould_grassKnot_grp_04_18474': { + 'hash': 18474, + 'name': 'hebios_mould_grassKnot_grp_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hebios_mould_ingotGraphic_grp_18494': { + 'hash': 18494, + 'name': 'hebios_mould_ingotGraphic_grp', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hebios_mould_railSlot_grp_01_18490': { + 'hash': 18490, + 'name': 'hebios_mould_railSlot_grp_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hebios_mould_railSlot_grp_02_18454': { + 'hash': 18454, + 'name': 'hebios_mould_railSlot_grp_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hebios_mould_railSlot_grp_03_18470': { + 'hash': 18470, + 'name': 'hebios_mould_railSlot_grp_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hebios_mould_railSlot_grp_04_18466': { + 'hash': 18466, + 'name': 'hebios_mould_railSlot_grp_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hebios_mould_timesGraphic_grp_18478': { + 'hash': 18478, + 'name': 'hebios_mould_timesGraphic_grp', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'katana_guard_grp_63702': { + 'hash': 63702, + 'name': 'katana_guard_grp', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'redwood_gotera_core_emblemPart_grp_52708': { + 'hash': 52708, + 'name': 'redwood_gotera_core_emblemPart_grp', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'redwood_gotera_core_leafPart_grp_52712': { + 'hash': 52712, + 'name': 'redwood_gotera_core_leafPart_grp', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Hebios_Guard': { + 'hash': 5144, + 'name': 'Hebios_Guard', + 'embedded': { + 'Heat_Point_Collection_56294': { + 'hash': 56294, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Hebios_Guard_36330': { + 'hash': 36330, + 'name': 'Hebios_Guard', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Insert_SwordType_Craft_39368': { + 'hash': 39368, + 'name': 'Insert_SwordType_Craft', + 'savables': {} + }, + 'Slot_SwordType_39370': { + 'hash': 39370, + 'name': 'Slot_SwordType', + 'savables': {} + } + } + }, + 'Hebios_Handle_Katana': { + 'hash': 53200, + 'name': 'Hebios_Handle_Katana', + 'embedded': { + 'Hebios_Handle_Katana_40148': { + 'hash': 40148, + 'name': 'Hebios_Handle_Katana', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'Enchantable': { + 'hash': 4134534481, + 'name': 'Enchantable' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Joint_Group_SwordType_63178': { + 'hash': 63178, + 'name': 'Joint_Group_SwordType', + 'savables': {} + }, + 'Slot_EdgeType_Craft_53492': { + 'hash': 53492, + 'name': 'Slot_EdgeType_Craft', + 'savables': {} + }, + 'Slot_Straight_Short_Sword_Type_63318': { + 'hash': 63318, + 'name': 'Slot_Straight_Short_Sword_Type', + 'savables': {} + } + } + }, + 'Hebios_Handle_Kunai': { + 'hash': 18456, + 'name': 'Hebios_Handle_Kunai', + 'embedded': { + 'Hebios_Handle_Kunai_14986': { + 'hash': 14986, + 'name': 'Hebios_Handle_Kunai', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'Embeddable': { + 'hash': 22446553, + 'name': 'Embeddable' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_Multi_6136': { + 'hash': 6136, + 'name': 'Slot_Multi', + 'savables': {} + } + } + }, + 'Hebios_Handle_Naginata': { + 'hash': 24220, + 'name': 'Hebios_Handle_Naginata', + 'embedded': { + 'Hebios_Handle_Naginata_26368': { + 'hash': 26368, + 'name': 'Hebios_Handle_Naginata', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'Enchantable': { + 'hash': 4134534481, + 'name': 'Enchantable' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_EdgeType_Craft_53692': { + 'hash': 53692, + 'name': 'Slot_EdgeType_Craft', + 'savables': {} + }, + 'Slot_Multi_53060': { + 'hash': 53060, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_Multi_63218': { + 'hash': 63218, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_Straight_Short_Sword_Type_63270': { + 'hash': 63270, + 'name': 'Slot_Straight_Short_Sword_Type', + 'savables': {} + } + } + }, + 'Hebios_Handle_Wakizashi': { + 'hash': 47662, + 'name': 'Hebios_Handle_Wakizashi', + 'embedded': { + 'Hebios_Handle_Wakizashi_47666': { + 'hash': 47666, + 'name': 'Hebios_Handle_Wakizashi', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'Enchantable': { + 'hash': 4134534481, + 'name': 'Enchantable' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Joint_Group_SwordType_63178': { + 'hash': 63178, + 'name': 'Joint_Group_SwordType', + 'savables': {} + }, + 'Slot_Straight_Short_Sword_Type_63318': { + 'hash': 63318, + 'name': 'Slot_Straight_Short_Sword_Type', + 'savables': {} + } + } + }, + 'Hebios_Katana_Blade_Part_01': { + 'hash': 12388, + 'name': 'Hebios_Katana_Blade_Part_01', + 'embedded': { + 'Hebios_Katana_Blade_Part_01_46162': { + 'hash': 46162, + 'name': 'Hebios_Katana_Blade_Part_01', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Hebios_Katana_Blade_Part_02': { + 'hash': 12386, + 'name': 'Hebios_Katana_Blade_Part_02', + 'embedded': { + 'Hebios_Katana_Blade_Part_02_46162': { + 'hash': 46162, + 'name': 'Hebios_Katana_Blade_Part_02', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Hebios_Katana_Blade_Part_Full': { + 'hash': 17266, + 'name': 'Hebios_Katana_Blade_Part_Full', + 'embedded': { + 'Hebios_Katana_Blade_Part_Full_40924': { + 'hash': 40924, + 'name': 'Hebios_Katana_Blade_Part_Full', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Insert_Straight_SwordType_7796': { + 'hash': 7796, + 'name': 'Insert_Straight_SwordType', + 'savables': {} + }, + 'hebios_katana_blade_part_01_56656': { + 'hash': 56656, + 'name': 'hebios_katana_blade_part_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hebios_katana_blade_part_02_56652': { + 'hash': 56652, + 'name': 'hebios_katana_blade_part_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Hebios_Naginata_Blade_Part_01': { + 'hash': 17238, + 'name': 'Hebios_Naginata_Blade_Part_01', + 'embedded': { + 'Hebios_Naginata_Blade_Part_01_46162': { + 'hash': 46162, + 'name': 'Hebios_Naginata_Blade_Part_01', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Hebios_Naginata_Blade_Part_02': { + 'hash': 42894, + 'name': 'Hebios_Naginata_Blade_Part_02', + 'embedded': { + 'Hebios_Naginata_Blade_Part_02_46162': { + 'hash': 46162, + 'name': 'Hebios_Naginata_Blade_Part_02', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Hebios_Naginata_Blade_Part_Full': { + 'hash': 17420, + 'name': 'Hebios_Naginata_Blade_Part_Full', + 'embedded': { + 'Hebios_Naginata_Blade_Part_Full_40924': { + 'hash': 40924, + 'name': 'Hebios_Naginata_Blade_Part_Full', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Insert_Straight_SwordType_7796': { + 'hash': 7796, + 'name': 'Insert_Straight_SwordType', + 'savables': {} + }, + 'naginata_blade_part_01_grp_21404': { + 'hash': 21404, + 'name': 'naginata_blade_part_01_grp', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'naginata_blade_part_02_grp_21408': { + 'hash': 21408, + 'name': 'naginata_blade_part_02_grp', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Hebios_Open_Crate_Spawner': { + 'hash': 46522, + 'name': 'Hebios_Open_Crate_Spawner', + 'embedded': { + 'Hebios_Open_Crate_Spawner_19060': { + 'hash': 19060, + 'name': 'Hebios_Open_Crate_Spawner', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + } + } + }, + 'Hebios_Sai_Blade_Part_01': { + 'hash': 57048, + 'name': 'Hebios_Sai_Blade_Part_01', + 'embedded': { + 'Hebios_Sai_Blade_Part_01_46162': { + 'hash': 46162, + 'name': 'Hebios_Sai_Blade_Part_01', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Hebios_Sai_Blade_Part_02': { + 'hash': 56830, + 'name': 'Hebios_Sai_Blade_Part_02', + 'embedded': { + 'Hebios_Sai_Blade_Part_02_46162': { + 'hash': 46162, + 'name': 'Hebios_Sai_Blade_Part_02', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Hebios_Sai_Blade_Part_Full': { + 'hash': 1600, + 'name': 'Hebios_Sai_Blade_Part_Full', + 'embedded': { + 'Hebios_Sai_Blade_Part_Full_40924': { + 'hash': 40924, + 'name': 'Hebios_Sai_Blade_Part_Full', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Insert_Straight_Short_SwordType_7796': { + 'hash': 7796, + 'name': 'Insert_Straight_Short_SwordType', + 'savables': {} + }, + 'hebios_sai_blade_part_01_50732': { + 'hash': 50732, + 'name': 'hebios_sai_blade_part_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hebios_sai_blade_part_02_50728': { + 'hash': 50728, + 'name': 'hebios_sai_blade_part_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Hebios_Storage_Chest': { + 'hash': 44984, + 'name': 'Hebios_Storage_Chest', + 'embedded': { + 'Bottom_Dock_1_2780': { + 'hash': 2780, + 'name': 'Bottom_Dock_1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_2_2778': { + 'hash': 2778, + 'name': 'Bottom_Dock_2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_3_2776': { + 'hash': 2776, + 'name': 'Bottom_Dock_3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_4_2770': { + 'hash': 2770, + 'name': 'Bottom_Dock_4', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_5_2772': { + 'hash': 2772, + 'name': 'Bottom_Dock_5', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_6_2774': { + 'hash': 2774, + 'name': 'Bottom_Dock_6', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Handle_Left_23970': { + 'hash': 23970, + 'name': 'Handle_Left', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Handle_Right_23964': { + 'hash': 23964, + 'name': 'Handle_Right', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Hebios_Storage_Chest_2788': { + 'hash': 2788, + 'name': 'Hebios_Storage_Chest', + 'savables': { + 'Chest': { + 'hash': 3598052397, + 'name': 'Chest' + } + } + }, + 'Lid_2768': { + 'hash': 2768, + 'name': 'Lid', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Loot_Module_27674': { + 'hash': 27674, + 'name': 'Loot_Module', + 'savables': { + 'LootModule': { + 'hash': 634164392, + 'name': 'LootModule' + } + } + }, + 'Top_Dock_1_2766': { + 'hash': 2766, + 'name': 'Top_Dock_1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_2_2764': { + 'hash': 2764, + 'name': 'Top_Dock_2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_3_2762': { + 'hash': 2762, + 'name': 'Top_Dock_3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_4_2756': { + 'hash': 2756, + 'name': 'Top_Dock_4', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_5_2758': { + 'hash': 2758, + 'name': 'Top_Dock_5', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_6_2760': { + 'hash': 2760, + 'name': 'Top_Dock_6', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + } + } + }, + 'Hebios_Storage_Chest_Climbing': { + 'hash': 35078, + 'name': 'Hebios_Storage_Chest_Climbing', + 'embedded': { + 'Bottom_Dock_1_2780': { + 'hash': 2780, + 'name': 'Bottom_Dock_1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_2_2778': { + 'hash': 2778, + 'name': 'Bottom_Dock_2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_3_2776': { + 'hash': 2776, + 'name': 'Bottom_Dock_3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_4_2770': { + 'hash': 2770, + 'name': 'Bottom_Dock_4', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_5_2772': { + 'hash': 2772, + 'name': 'Bottom_Dock_5', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_6_2774': { + 'hash': 2774, + 'name': 'Bottom_Dock_6', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Handle_Left_23970': { + 'hash': 23970, + 'name': 'Handle_Left', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Handle_Right_23964': { + 'hash': 23964, + 'name': 'Handle_Right', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Hebios_Storage_Chest_Climbing_35076': { + 'hash': 35076, + 'name': 'Hebios_Storage_Chest_Climbing', + 'savables': { + 'Chest': { + 'hash': 3598052397, + 'name': 'Chest' + } + } + }, + 'Lid_2768': { + 'hash': 2768, + 'name': 'Lid', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Loot_Module_27674': { + 'hash': 27674, + 'name': 'Loot_Module', + 'savables': { + 'LootModule': { + 'hash': 634164392, + 'name': 'LootModule' + } + } + }, + 'Top_Dock_1_2766': { + 'hash': 2766, + 'name': 'Top_Dock_1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_2_2764': { + 'hash': 2764, + 'name': 'Top_Dock_2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_3_2762': { + 'hash': 2762, + 'name': 'Top_Dock_3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_4_2756': { + 'hash': 2756, + 'name': 'Top_Dock_4', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_5_2758': { + 'hash': 2758, + 'name': 'Top_Dock_5', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_6_2760': { + 'hash': 2760, + 'name': 'Top_Dock_6', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + } + } + }, + 'Hebios_Storage_Chest_Gcore': { + 'hash': 31618, + 'name': 'Hebios_Storage_Chest_Gcore', + 'embedded': { + 'Bottom_Dock_1_2780': { + 'hash': 2780, + 'name': 'Bottom_Dock_1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_2_2778': { + 'hash': 2778, + 'name': 'Bottom_Dock_2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_3_2776': { + 'hash': 2776, + 'name': 'Bottom_Dock_3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_4_2770': { + 'hash': 2770, + 'name': 'Bottom_Dock_4', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_5_2772': { + 'hash': 2772, + 'name': 'Bottom_Dock_5', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_6_2774': { + 'hash': 2774, + 'name': 'Bottom_Dock_6', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Handle_Left_23970': { + 'hash': 23970, + 'name': 'Handle_Left', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Handle_Right_23964': { + 'hash': 23964, + 'name': 'Handle_Right', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Hebios_Storage_Chest_Gcore_2788': { + 'hash': 2788, + 'name': 'Hebios_Storage_Chest_Gcore', + 'savables': { + 'Chest': { + 'hash': 3598052397, + 'name': 'Chest' + } + } + }, + 'Lid_2768': { + 'hash': 2768, + 'name': 'Lid', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Loot_Module_27674': { + 'hash': 27674, + 'name': 'Loot_Module', + 'savables': { + 'LootModule': { + 'hash': 634164392, + 'name': 'LootModule' + } + } + }, + 'Top_Dock_1_2766': { + 'hash': 2766, + 'name': 'Top_Dock_1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_2_2764': { + 'hash': 2764, + 'name': 'Top_Dock_2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_3_2762': { + 'hash': 2762, + 'name': 'Top_Dock_3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_4_2756': { + 'hash': 2756, + 'name': 'Top_Dock_4', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_5_2758': { + 'hash': 2758, + 'name': 'Top_Dock_5', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_6_2760': { + 'hash': 2760, + 'name': 'Top_Dock_6', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + } + } + }, + 'Hebios_Wakizashi_Blade_Part_01': { + 'hash': 49774, + 'name': 'Hebios_Wakizashi_Blade_Part_01', + 'embedded': { + 'Hebios_Wakizashi_Blade_Part_01_46162': { + 'hash': 46162, + 'name': 'Hebios_Wakizashi_Blade_Part_01', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Hebios_Wakizashi_Blade_Part_02': { + 'hash': 50184, + 'name': 'Hebios_Wakizashi_Blade_Part_02', + 'embedded': { + 'Hebios_Wakizashi_Blade_Part_02_46162': { + 'hash': 46162, + 'name': 'Hebios_Wakizashi_Blade_Part_02', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Hebios_Wakizashi_Blade_Part_Full': { + 'hash': 9018, + 'name': 'Hebios_Wakizashi_Blade_Part_Full', + 'embedded': { + 'Hebios_Wakizashi_Blade_Part_Full_40924': { + 'hash': 40924, + 'name': 'Hebios_Wakizashi_Blade_Part_Full', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Insert_Straight_SwordType_7796': { + 'hash': 7796, + 'name': 'Insert_Straight_SwordType', + 'savables': {} + }, + 'wakizashi_blade_part_01_grp_31190': { + 'hash': 31190, + 'name': 'wakizashi_blade_part_01_grp', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'wakizashi_blade_part_02_grp_31194': { + 'hash': 31194, + 'name': 'wakizashi_blade_part_02_grp', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Hitting_Short_Sword_Training': { + 'hash': 55646, + 'name': 'Hitting_Short_Sword_Training', + 'embedded': { + 'Blade_1152': { + 'hash': 1152, + 'name': 'Blade', + 'savables': {} + }, + 'Hitting_Short_Sword_Training_1152': { + 'hash': 1152, + 'name': 'Hitting_Short_Sword_Training', + 'savables': {} + } + } + }, + 'Hoarder_Bag': { + 'hash': 54214, + 'name': 'Hoarder_Bag', + 'embedded': { + 'Bag_Body_42972': { + 'hash': 42972, + 'name': 'Bag_Body', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Dock_(1)_47074': { + 'hash': 47074, + 'name': 'Dock_(1)', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_464': { + 'hash': 464, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_BL_(1)_1146': { + 'hash': 1146, + 'name': 'Dock_BL_(1)', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_BL_42978': { + 'hash': 42978, + 'name': 'Dock_BL', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_BM_(1)_1148': { + 'hash': 1148, + 'name': 'Dock_BM_(1)', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_BM_42976': { + 'hash': 42976, + 'name': 'Dock_BM', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_BR_(1)_1432': { + 'hash': 1432, + 'name': 'Dock_BR_(1)', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_BR_(2)_1240': { + 'hash': 1240, + 'name': 'Dock_BR_(2)', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_BR_(3)_1150': { + 'hash': 1150, + 'name': 'Dock_BR_(3)', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_BR_42974': { + 'hash': 42974, + 'name': 'Dock_BR', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_ML_42984': { + 'hash': 42984, + 'name': 'Dock_ML', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_MM_42982': { + 'hash': 42982, + 'name': 'Dock_MM', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_MR_(1)_1430': { + 'hash': 1430, + 'name': 'Dock_MR_(1)', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_MR_42980': { + 'hash': 42980, + 'name': 'Dock_MR', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_TL_42990': { + 'hash': 42990, + 'name': 'Dock_TL', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_TM_42988': { + 'hash': 42988, + 'name': 'Dock_TM', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_TR_(1)_1428': { + 'hash': 1428, + 'name': 'Dock_TR_(1)', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_TR_42986': { + 'hash': 42986, + 'name': 'Dock_TR', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Hoarder_Bag_43012': { + 'hash': 43012, + 'name': 'Hoarder_Bag', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_Bag_Attach_10614': { + 'hash': 10614, + 'name': 'Slot_Bag_Attach', + 'savables': {} + }, + 'Slot_Bag_Attach_10616': { + 'hash': 10616, + 'name': 'Slot_Bag_Attach', + 'savables': {} + }, + 'Slot_Bag_Attach_30776': { + 'hash': 30776, + 'name': 'Slot_Bag_Attach', + 'savables': {} + }, + 'Slot_Bag_Attach_55164': { + 'hash': 55164, + 'name': 'Slot_Bag_Attach', + 'savables': {} + }, + 'Slot_Bag_Pin_Collectible_Attach_59540': { + 'hash': 59540, + 'name': 'Slot_Bag_Pin_Collectible_Attach', + 'savables': {} + }, + 'Slot_Bag_Tool_Attachment_1020': { + 'hash': 1020, + 'name': 'Slot_Bag_Tool_Attachment', + 'savables': {} + }, + 'Slot_Bag_Tool_Attachment_918': { + 'hash': 918, + 'name': 'Slot_Bag_Tool_Attachment', + 'savables': {} + }, + 'hoarder_bag_body_39890': { + 'hash': 39890, + 'name': 'hoarder_bag_body', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_clasp_front_L_39810': { + 'hash': 39810, + 'name': 'hoarder_bag_clasp_front_L', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_clasp_front_R_39850': { + 'hash': 39850, + 'name': 'hoarder_bag_clasp_front_R', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_flap_39878': { + 'hash': 39878, + 'name': 'hoarder_bag_flap', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_flap_clasp_39886': { + 'hash': 39886, + 'name': 'hoarder_bag_flap_clasp', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_pin_L_01_39894': { + 'hash': 39894, + 'name': 'hoarder_bag_pin_L_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_pin_L_02_39882': { + 'hash': 39882, + 'name': 'hoarder_bag_pin_L_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_pin_L_03_39930': { + 'hash': 39930, + 'name': 'hoarder_bag_pin_L_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_pin_L_04_39826': { + 'hash': 39826, + 'name': 'hoarder_bag_pin_L_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_pin_L_05_39898': { + 'hash': 39898, + 'name': 'hoarder_bag_pin_L_05', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_pin_L_06_39834': { + 'hash': 39834, + 'name': 'hoarder_bag_pin_L_06', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_pin_L_07_39902': { + 'hash': 39902, + 'name': 'hoarder_bag_pin_L_07', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_pin_R_01_39870': { + 'hash': 39870, + 'name': 'hoarder_bag_pin_R_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_pin_R_02_39858': { + 'hash': 39858, + 'name': 'hoarder_bag_pin_R_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_pin_R_03_39914': { + 'hash': 39914, + 'name': 'hoarder_bag_pin_R_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_pin_R_04_39926': { + 'hash': 39926, + 'name': 'hoarder_bag_pin_R_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_pin_R_05_39806': { + 'hash': 39806, + 'name': 'hoarder_bag_pin_R_05', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_pin_R_06_39874': { + 'hash': 39874, + 'name': 'hoarder_bag_pin_R_06', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_pin_R_07_39814': { + 'hash': 39814, + 'name': 'hoarder_bag_pin_R_07', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_sideBuckle_L_01_39830': { + 'hash': 39830, + 'name': 'hoarder_bag_sideBuckle_L_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_sideBuckle_L_02_39802': { + 'hash': 39802, + 'name': 'hoarder_bag_sideBuckle_L_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_sideBuckle_R_01_39866': { + 'hash': 39866, + 'name': 'hoarder_bag_sideBuckle_R_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_sideBuckle_R_02_39906': { + 'hash': 39906, + 'name': 'hoarder_bag_sideBuckle_R_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_strap_body_39822': { + 'hash': 39822, + 'name': 'hoarder_bag_strap_body', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_strap_bottom_L_39854': { + 'hash': 39854, + 'name': 'hoarder_bag_strap_bottom_L', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_strap_bottom_R_39798': { + 'hash': 39798, + 'name': 'hoarder_bag_strap_bottom_R', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_strap_front_L_39838': { + 'hash': 39838, + 'name': 'hoarder_bag_strap_front_L', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_strap_front_R_39818': { + 'hash': 39818, + 'name': 'hoarder_bag_strap_front_R', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_strap_slot_L_39862': { + 'hash': 39862, + 'name': 'hoarder_bag_strap_slot_L', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_strap_slot_R_39846': { + 'hash': 39846, + 'name': 'hoarder_bag_strap_slot_R', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_strap_top_buckle_L_39922': { + 'hash': 39922, + 'name': 'hoarder_bag_strap_top_buckle_L', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_strap_top_buckle_R_39918': { + 'hash': 39918, + 'name': 'hoarder_bag_strap_top_buckle_R', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_topDetail_01_39910': { + 'hash': 39910, + 'name': 'hoarder_bag_topDetail_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'hoarder_bag_topDetail_02_39842': { + 'hash': 39842, + 'name': 'hoarder_bag_topDetail_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_handle_body_14308': { + 'hash': 14308, + 'name': 'standard_bag_handle_body', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_handle_wraps_14304': { + 'hash': 14304, + 'name': 'standard_bag_handle_wraps', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'HolidayRewardDisplay': { + 'hash': 32158, + 'name': 'HolidayRewardDisplay', + 'embedded': { + 'HolidayRewardDisplay_32140': { + 'hash': 32140, + 'name': 'HolidayRewardDisplay', + 'savables': {} + } + } + }, + 'Hot_Coalbed': { + 'hash': 41234, + 'name': 'Hot_Coalbed', + 'embedded': { + 'Heating_Bit_26176': { + 'hash': 26176, + 'name': 'Heating_Bit', + 'savables': {} + }, + 'Hot_Coalbed_26204': { + 'hash': 26204, + 'name': 'Hot_Coalbed', + 'savables': {} + }, + 'Hurting_Bit_26178': { + 'hash': 26178, + 'name': 'Hurting_Bit', + 'savables': {} + } + } + }, + 'Hover_Piece': { + 'hash': 50934, + 'name': 'Hover_Piece', + 'embedded': { + 'Hover_Piece_5676': { + 'hash': 5676, + 'name': 'Hover_Piece', + 'savables': {} + } + } + }, + 'Infinite_Fire': { + 'hash': 5172, + 'name': 'Infinite_Fire', + 'embedded': { + 'Fire_8488': { + 'hash': 8488, + 'name': 'Fire', + 'savables': { + 'Fire': { + 'hash': 3457519710, + 'name': 'Fire' + } + } + }, + 'Infinite_Fire_24372': { + 'hash': 24372, + 'name': 'Infinite_Fire', + 'savables': { + 'BasicDecay': { + 'hash': 3801256786, + 'name': 'BasicDecay' + } + } + }, + 'Spawner_49628': { + 'hash': 49628, + 'name': 'Spawner', + 'savables': {} + } + } + }, + 'Info_Board': { + 'hash': 51114, + 'name': 'Info_Board', + 'embedded': { + 'Info_Board_63822': { + 'hash': 63822, + 'name': 'Info_Board', + 'savables': { + 'InfoBoard': { + 'hash': 3431876266, + 'name': 'InfoBoard' + } + } + } + } + }, + 'Ingredient_Generator_Shelf': { + 'hash': 51096, + 'name': 'Ingredient_Generator_Shelf', + 'embedded': { + 'Dock_2780': { + 'hash': 2780, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_58082': { + 'hash': 58082, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_58084': { + 'hash': 58084, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_58086': { + 'hash': 58086, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_58088': { + 'hash': 58088, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_58090': { + 'hash': 58090, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_58092': { + 'hash': 58092, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_58094': { + 'hash': 58094, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_58096': { + 'hash': 58096, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_58098': { + 'hash': 58098, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Ingredient_Generator_Shelf_51098': { + 'hash': 51098, + 'name': 'Ingredient_Generator_Shelf', + 'savables': {} + }, + 'Recipe_Dock_60388': { + 'hash': 60388, + 'name': 'Recipe_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + } + } + }, + 'Int_Range_Operator': { + 'hash': 55740, + 'name': 'Int_Range_Operator', + 'embedded': { + 'Int_Range_Operator_13344': { + 'hash': 13344, + 'name': 'Int_Range_Operator', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'LogicIntRangeReceiver': { + 'hash': 2610542999, + 'name': 'LogicIntRangeReceiver' + } + } + } + } + }, + 'Iron_Boulder': { + 'hash': 45344, + 'name': 'Iron_Boulder', + 'embedded': { + 'Iron_Boulder_49644': { + 'hash': 49644, + 'name': 'Iron_Boulder', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Spawn_Origin_48914': { + 'hash': 48914, + 'name': 'Spawn_Origin', + 'savables': {} + } + } + }, + 'Iron_Boulder_Parts': { + 'hash': 18070, + 'name': 'Iron_Boulder_Parts', + 'embedded': { + 'Iron_Boulder_Part_01_64822': { + 'hash': 64822, + 'name': 'Iron_Boulder_Part_01', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Iron_Boulder_Part_02_64818': { + 'hash': 64818, + 'name': 'Iron_Boulder_Part_02', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Iron_Boulder_Part_03_64806': { + 'hash': 64806, + 'name': 'Iron_Boulder_Part_03', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Iron_Boulder_Part_04_64814': { + 'hash': 64814, + 'name': 'Iron_Boulder_Part_04', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Iron_Boulder_Part_05_64810': { + 'hash': 64810, + 'name': 'Iron_Boulder_Part_05', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Iron_Boulder_Part_06_64826': { + 'hash': 64826, + 'name': 'Iron_Boulder_Part_06', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Iron_Boulder_Parts_64778': { + 'hash': 64778, + 'name': 'Iron_Boulder_Parts', + 'savables': {} + } + } + }, + 'Iron_Boulder_Training': { + 'hash': 10140, + 'name': 'Iron_Boulder_Training', + 'embedded': { + 'Iron_Boulder_Training_10130': { + 'hash': 10130, + 'name': 'Iron_Boulder_Training', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Spawn_Origin_48914': { + 'hash': 48914, + 'name': 'Spawn_Origin', + 'savables': {} + } + } + }, + 'Iron_Cluster': { + 'hash': 28272, + 'name': 'Iron_Cluster', + 'embedded': { + 'Iron_Cluster_18314': { + 'hash': 18314, + 'name': 'Iron_Cluster', + 'savables': {} + } + } + }, + 'Iron_Ingot': { + 'hash': 23012, + 'name': 'Iron_Ingot', + 'embedded': { + 'Heat_Point_Collection_13170': { + 'hash': 13170, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Iron_Ingot_22900': { + 'hash': 22900, + 'name': 'Iron_Ingot', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Iron_Ore': { + 'hash': 61652, + 'name': 'Iron_Ore', + 'embedded': { + 'Iron_Ore_37686': { + 'hash': 37686, + 'name': 'Iron_Ore', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Ka_Karimata_Arrow': { + 'hash': 960, + 'name': 'Ka_Karimata_Arrow', + 'embedded': { + 'Ka_Karimata_Arrow_43746': { + 'hash': 43746, + 'name': 'Ka_Karimata_Arrow', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'Embeddable': { + 'hash': 22446553, + 'name': 'Embeddable' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Tip_58698': { + 'hash': 58698, + 'name': 'Tip', + 'savables': {} + } + } + }, + 'Katana': { + 'hash': 34994, + 'name': 'Katana', + 'embedded': { + 'Katana_36330': { + 'hash': 36330, + 'name': 'Katana', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'Enchantable': { + 'hash': 4134534481, + 'name': 'Enchantable' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Key_Standard': { + 'hash': 39744, + 'name': 'Key_Standard', + 'embedded': { + 'Key_Standard_26420': { + 'hash': 26420, + 'name': 'Key_Standard', + 'savables': { + 'KeyItem': { + 'hash': 414036426, + 'name': 'KeyItem' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Kunai': { + 'hash': 32002, + 'name': 'Kunai', + 'embedded': { + 'Kunai_36330': { + 'hash': 36330, + 'name': 'Kunai', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'Embeddable': { + 'hash': 22446553, + 'name': 'Embeddable' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Ladder': { + 'hash': 56168, + 'name': 'Ladder', + 'embedded': { + 'Ladder_53890': { + 'hash': 53890, + 'name': 'Ladder', + 'savables': {} + } + } + }, + 'Lantern': { + 'hash': 41760, + 'name': 'Lantern', + 'embedded': { + 'Fire_54948': { + 'hash': 54948, + 'name': 'Fire', + 'savables': { + 'Fire': { + 'hash': 3457519710, + 'name': 'Fire' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Fuel_Dock_63110': { + 'hash': 63110, + 'name': 'Fuel_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Lantern_56450': { + 'hash': 56450, + 'name': 'Lantern', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'lantern_arm_28726': { + 'hash': 28726, + 'name': 'lantern_arm', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'lantern_bar_01_28734': { + 'hash': 28734, + 'name': 'lantern_bar_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'lantern_bar_02_28742': { + 'hash': 28742, + 'name': 'lantern_bar_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'lantern_bar_03_28770': { + 'hash': 28770, + 'name': 'lantern_bar_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'lantern_bar_04_28766': { + 'hash': 28766, + 'name': 'lantern_bar_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'lantern_bar_05_28738': { + 'hash': 28738, + 'name': 'lantern_bar_05', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'lantern_bar_06_28778': { + 'hash': 28778, + 'name': 'lantern_bar_06', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'lantern_bar_07_28750': { + 'hash': 28750, + 'name': 'lantern_bar_07', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'lantern_base_28746': { + 'hash': 28746, + 'name': 'lantern_base', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'lantern_face_28754': { + 'hash': 28754, + 'name': 'lantern_face', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'lantern_handle_28758': { + 'hash': 28758, + 'name': 'lantern_handle', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'lantern_topCap_28762': { + 'hash': 28762, + 'name': 'lantern_topCap', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'lantern_topSwivel_28774': { + 'hash': 28774, + 'name': 'lantern_topSwivel', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'lantern_visor_28730': { + 'hash': 28730, + 'name': 'lantern_visor', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Large_Cave_Mushroom': { + 'hash': 29690, + 'name': 'Large_Cave_Mushroom', + 'embedded': { + 'Large_Cave_Mushroom_30160': { + 'hash': 30160, + 'name': 'Large_Cave_Mushroom', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Large_Cave_Mushroom_Body_30160': { + 'hash': 30160, + 'name': 'Large_Cave_Mushroom_Body', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Spawner_26386': { + 'hash': 26386, + 'name': 'Spawner', + 'savables': {} + }, + 'cave_mushroom_headEnd_jnt_22906': { + 'hash': 22906, + 'name': 'cave_mushroom_headEnd_jnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'cave_mushroom_spine_jnt_27926': { + 'hash': 27926, + 'name': 'cave_mushroom_spine_jnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Large_Cave_Mushroom_Cluster': { + 'hash': 2422, + 'name': 'Large_Cave_Mushroom_Cluster', + 'embedded': { + 'Large_Cave_Mushroom_Cluster_61380': { + 'hash': 61380, + 'name': 'Large_Cave_Mushroom_Cluster', + 'savables': {} + } + } + }, + 'Large_Cave_Mushroom_OLD': { + 'hash': 36866, + 'name': 'Large_Cave_Mushroom_OLD', + 'embedded': { + 'Large_Cave_Mushroom_OLD_30160': { + 'hash': 30160, + 'name': 'Large_Cave_Mushroom_OLD', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Spawner_26386': { + 'hash': 26386, + 'name': 'Spawner', + 'savables': {} + }, + 'cave_mushroom_headEnd_jnt_22906': { + 'hash': 22906, + 'name': 'cave_mushroom_headEnd_jnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'cave_mushroom_spine_jnt_27926': { + 'hash': 27926, + 'name': 'cave_mushroom_spine_jnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Large_Guard_Rectangle': { + 'hash': 9304, + 'name': 'Large_Guard_Rectangle', + 'embedded': { + 'Heat_Point_Collection_57820': { + 'hash': 57820, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_Large_SwordType_Craft_51894': { + 'hash': 51894, + 'name': 'Insert_Large_SwordType_Craft', + 'savables': {} + }, + 'Large_Guard_Rectangle_51938': { + 'hash': 51938, + 'name': 'Large_Guard_Rectangle', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_Large_SwordType_51896': { + 'hash': 51896, + 'name': 'Slot_Large_SwordType', + 'savables': {} + } + } + }, + 'Large_Guard_TShape': { + 'hash': 23552, + 'name': 'Large_Guard_TShape', + 'embedded': { + 'Heat_Point_Collection_58132': { + 'hash': 58132, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_Large_SwordType_Craft_23506': { + 'hash': 23506, + 'name': 'Insert_Large_SwordType_Craft', + 'savables': {} + }, + 'Large_Guard_TShape_23550': { + 'hash': 23550, + 'name': 'Large_Guard_TShape', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_Large_SwordType_23508': { + 'hash': 23508, + 'name': 'Slot_Large_SwordType', + 'savables': {} + } + } + }, + 'Large_Guard_Wedge': { + 'hash': 39010, + 'name': 'Large_Guard_Wedge', + 'embedded': { + 'Heat_Point_Collection_58440': { + 'hash': 58440, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_Large_SwordType_Craft_38964': { + 'hash': 38964, + 'name': 'Insert_Large_SwordType_Craft', + 'savables': {} + }, + 'Large_Guard_Wedge_39008': { + 'hash': 39008, + 'name': 'Large_Guard_Wedge', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_Large_SwordType_38966': { + 'hash': 38966, + 'name': 'Slot_Large_SwordType', + 'savables': {} + } + } + }, + 'Large_Longsword_Blade': { + 'hash': 56124, + 'name': 'Large_Longsword_Blade', + 'embedded': { + 'Heat_Point_Collection_62508': { + 'hash': 62508, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_Large_SwordType_31944': { + 'hash': 31944, + 'name': 'Insert_Large_SwordType', + 'savables': {} + }, + 'Large_Longsword_Blade_53840': { + 'hash': 53840, + 'name': 'Large_Longsword_Blade', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'large_longsword_LOD0_45786': { + 'hash': 45786, + 'name': 'large_longsword_LOD0', + 'savables': {} + } + } + }, + 'Large_Mythril_Boulder': { + 'hash': 53902, + 'name': 'Large_Mythril_Boulder', + 'embedded': { + 'Large_Mythril_Boulder_29328': { + 'hash': 29328, + 'name': 'Large_Mythril_Boulder', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Spawn_Origin_18860': { + 'hash': 18860, + 'name': 'Spawn_Origin', + 'savables': {} + } + } + }, + 'Large_Spiked_Wooden_Club': { + 'hash': 55914, + 'name': 'Large_Spiked_Wooden_Club', + 'embedded': { + 'Large_Spiked_Wooden_Club_55724': { + 'hash': 55724, + 'name': 'Large_Spiked_Wooden_Club', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Large_Sword': { + 'hash': 8374, + 'name': 'Large_Sword', + 'embedded': {} + }, + 'Lava_Pool': { + 'hash': 34696, + 'name': 'Lava_Pool', + 'embedded': { + 'Heat_Bit_35218': { + 'hash': 35218, + 'name': 'Heat_Bit', + 'savables': {} + }, + 'Hurt_Bit_30842': { + 'hash': 30842, + 'name': 'Hurt_Bit', + 'savables': {} + }, + 'Lava_Pool_16578': { + 'hash': 16578, + 'name': 'Lava_Pool', + 'savables': {} + }, + 'Slow_Bit_34974': { + 'hash': 34974, + 'name': 'Slow_Bit', + 'savables': {} + } + } + }, + 'Leaderboard': { + 'hash': 44390, + 'name': 'Leaderboard', + 'embedded': { + 'Leaderboard_27564': { + 'hash': 27564, + 'name': 'Leaderboard', + 'savables': { + 'Leaderboard': { + 'hash': 3257374625, + 'name': 'Leaderboard' + } + } + } + } + }, + 'Lectern': { + 'hash': 59986, + 'name': 'Lectern', + 'embedded': { + 'Candle_Flame_30100': { + 'hash': 30100, + 'name': 'Candle_Flame', + 'savables': { + 'Fire': { + 'hash': 3457519710, + 'name': 'Fire' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Lectern_57672': { + 'hash': 57672, + 'name': 'Lectern', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + }, + 'BookRestrictor': { + 'hash': 2629079826, + 'name': 'BookRestrictor' + } + } + } + } + }, + 'Lectern_Flat': { + 'hash': 45828, + 'name': 'Lectern_Flat', + 'embedded': { + 'Lectern_Flat_45826': { + 'hash': 45826, + 'name': 'Lectern_Flat', + 'savables': {} + } + } + }, + 'Leveling_Dummy': { + 'hash': 44224, + 'name': 'Leveling_Dummy', + 'embedded': { + 'Leveling_Dummy_39942': { + 'hash': 39942, + 'name': 'Leveling_Dummy', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'dummy_arm_l_01_jnt_46272': { + 'hash': 46272, + 'name': 'dummy_arm_l_01_jnt', + 'savables': {} + }, + 'dummy_arm_l_02_jnt_46248': { + 'hash': 46248, + 'name': 'dummy_arm_l_02_jnt', + 'savables': {} + }, + 'dummy_arm_l_03_jnt_46250': { + 'hash': 46250, + 'name': 'dummy_arm_l_03_jnt', + 'savables': {} + }, + 'dummy_arm_r_01_jnt_46246': { + 'hash': 46246, + 'name': 'dummy_arm_r_01_jnt', + 'savables': {} + }, + 'dummy_arm_r_02_jnt_46254': { + 'hash': 46254, + 'name': 'dummy_arm_r_02_jnt', + 'savables': {} + }, + 'dummy_arm_r_03_jnt_46256': { + 'hash': 46256, + 'name': 'dummy_arm_r_03_jnt', + 'savables': {} + }, + 'dummy_head_01_jnt_46270': { + 'hash': 46270, + 'name': 'dummy_head_01_jnt', + 'savables': {} + }, + 'dummy_head_02_jnt_46264': { + 'hash': 46264, + 'name': 'dummy_head_02_jnt', + 'savables': {} + }, + 'dummy_head_03_jnt_46262': { + 'hash': 46262, + 'name': 'dummy_head_03_jnt', + 'savables': {} + }, + 'dummy_neck_jnt_46268': { + 'hash': 46268, + 'name': 'dummy_neck_jnt', + 'savables': {} + }, + 'dummy_spineMid_jnt_46274': { + 'hash': 46274, + 'name': 'dummy_spineMid_jnt', + 'savables': {} + }, + 'dummy_spine_01_jnt_46258': { + 'hash': 46258, + 'name': 'dummy_spine_01_jnt', + 'savables': {} + }, + 'dummy_spine_02_jnt_46260': { + 'hash': 46260, + 'name': 'dummy_spine_02_jnt', + 'savables': {} + }, + 'dummy_spine_03_jnt_46266': { + 'hash': 46266, + 'name': 'dummy_spine_03_jnt', + 'savables': {} + }, + 'dummy_sternum_jnt_46252': { + 'hash': 46252, + 'name': 'dummy_sternum_jnt', + 'savables': {} + } + } + }, + 'Lever': { + 'hash': 27966, + 'name': 'Lever', + 'embedded': {} + }, + 'LightPuzzle_Test': { + 'hash': 8524, + 'name': 'LightPuzzle_Test', + 'embedded': {} + }, + 'Liquid_Pump': { + 'hash': 39174, + 'name': 'Liquid_Pump', + 'embedded': {} + }, + 'Lockbox': { + 'hash': 6974, + 'name': 'Lockbox', + 'embedded': { + 'Chunk_19700': { + 'hash': 19700, + 'name': 'Chunk', + 'savables': {} + }, + 'Hand_Touch_46540': { + 'hash': 46540, + 'name': 'Hand_Touch', + 'savables': {} + }, + 'Lockbox_9078': { + 'hash': 9078, + 'name': 'Lockbox', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + } + } + }, + 'Lockbox_Docks': { + 'hash': 2226, + 'name': 'Lockbox_Docks', + 'embedded': { + 'Bottom_Dock_1_48412': { + 'hash': 48412, + 'name': 'Bottom_Dock_1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_2_48414': { + 'hash': 48414, + 'name': 'Bottom_Dock_2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_3_48416': { + 'hash': 48416, + 'name': 'Bottom_Dock_3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_4_48422': { + 'hash': 48422, + 'name': 'Bottom_Dock_4', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_5_48420': { + 'hash': 48420, + 'name': 'Bottom_Dock_5', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_6_48418': { + 'hash': 48418, + 'name': 'Bottom_Dock_6', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Lockbox_Docks_64298': { + 'hash': 64298, + 'name': 'Lockbox_Docks', + 'savables': {} + } + } + }, + 'Log_Mallet': { + 'hash': 42518, + 'name': 'Log_Mallet', + 'embedded': {} + }, + 'Log_Mallet_v02': { + 'hash': 42030, + 'name': 'Log_Mallet_v02', + 'embedded': {} + }, + 'LogicBoolOneTimeActivate': { + 'hash': 28136, + 'name': 'LogicBoolOneTimeActivate', + 'embedded': { + 'LogicBoolOneTimeActivate_28066': { + 'hash': 28066, + 'name': 'LogicBoolOneTimeActivate', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + } + } + } + } + }, + 'LogicFloatChangeOnBool': { + 'hash': 62220, + 'name': 'LogicFloatChangeOnBool', + 'embedded': { + 'LogicFloatChangeOnBool_56894': { + 'hash': 56894, + 'name': 'LogicFloatChangeOnBool', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicFloatChangeOnBool': { + 'hash': 200292695, + 'name': 'LogicFloatChangeOnBool' + }, + 'LogicFloatSender': { + 'hash': 2120963769, + 'name': 'LogicFloatSender' + } + } + } + } + }, + 'LogicFloatReset': { + 'hash': 57100, + 'name': 'LogicFloatReset', + 'embedded': { + 'LogicFloatReset_56894': { + 'hash': 56894, + 'name': 'LogicFloatReset', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicFloatReceiver': { + 'hash': 3188272159, + 'name': 'LogicFloatReceiver' + }, + 'LogicFloatReset': { + 'hash': 3245685963, + 'name': 'LogicFloatReset' + }, + 'LogicFloatSender': { + 'hash': 2120963769, + 'name': 'LogicFloatSender' + } + } + } + } + }, + 'LogicReset': { + 'hash': 36976, + 'name': 'LogicReset', + 'embedded': { + 'LogicReset_42904': { + 'hash': 42904, + 'name': 'LogicReset', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicReset': { + 'hash': 1934129787, + 'name': 'LogicReset' + } + } + } + } + }, + 'Logic_Context': { + 'hash': 34630, + 'name': 'Logic_Context', + 'embedded': { + 'Logic_Context_34154': { + 'hash': 34154, + 'name': 'Logic_Context', + 'savables': { + 'GlobalLogicManager': { + 'hash': 967932020, + 'name': 'GlobalLogicManager' + } + } + } + } + }, + 'Logic_Int_To_Bool': { + 'hash': 2454, + 'name': 'Logic_Int_To_Bool', + 'embedded': { + 'Logic_Int_To_Bool_9620': { + 'hash': 9620, + 'name': 'Logic_Int_To_Bool', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'LogicIntReceiver': { + 'hash': 1081247904, + 'name': 'LogicIntReceiver' + }, + 'LogicIntToBool': { + 'hash': 2253011220, + 'name': 'LogicIntToBool' + } + } + } + } + }, + 'Logic_Operator': { + 'hash': 13390, + 'name': 'Logic_Operator', + 'embedded': { + 'Logic_Operator_13344': { + 'hash': 13344, + 'name': 'Logic_Operator', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'LogicGateReceiver': { + 'hash': 1391720462, + 'name': 'LogicGateReceiver' + } + } + } + } + }, + 'Long_S_Hook': { + 'hash': 20598, + 'name': 'Long_S_Hook', + 'embedded': { + 'Hangable_Dock_5626': { + 'hash': 5626, + 'name': 'Hangable_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Long_S_Hook_17940': { + 'hash': 17940, + 'name': 'Long_S_Hook', + 'savables': {} + } + } + }, + 'Loot_Module': { + 'hash': 29544, + 'name': 'Loot_Module', + 'embedded': {} + }, + 'MRK_Activation_Line': { + 'hash': 24096, + 'name': 'MRK_Activation_Line', + 'embedded': { + 'Glow_Ended_44912': { + 'hash': 44912, + 'name': 'Glow_Ended', + 'savables': {} + }, + 'Glow_Started_44908': { + 'hash': 44908, + 'name': 'Glow_Started', + 'savables': {} + }, + 'MRK_Activation_Line_22336': { + 'hash': 22336, + 'name': 'MRK_Activation_Line', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + } + } + } + } + }, + 'MRK_Automated_Pipe_Hazard_Elevator': { + 'hash': 38546, + 'name': 'MRK_Automated_Pipe_Hazard_Elevator', + 'embedded': { + 'Hurting_Bit_26178': { + 'hash': 26178, + 'name': 'Hurting_Bit', + 'savables': {} + }, + 'MRK_Automated_Pipe_Hazard_Elevator_21038': { + 'hash': 21038, + 'name': 'MRK_Automated_Pipe_Hazard_Elevator', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + } + } + }, + 'Reset_Receiver_17642': { + 'hash': 17642, + 'name': 'Reset_Receiver', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + } + } + }, + 'Steam_Spray_61896': { + 'hash': 61896, + 'name': 'Steam_Spray', + 'savables': {} + }, + 'Steam_Start_37968': { + 'hash': 37968, + 'name': 'Steam_Start', + 'savables': {} + }, + 'mrk_risingPipe_body_20878': { + 'hash': 20878, + 'name': 'mrk_risingPipe_body', + 'savables': { + 'CurveOutput': { + 'hash': 2576456808, + 'name': 'CurveOutput' + } + } + } + } + }, + 'MRK_Automated_Pipe_Hazard_Elevator_7.6_Variant': { + 'hash': 61754, + 'name': 'MRK_Automated_Pipe_Hazard_Elevator_7.6_Variant', + 'embedded': { + 'Hurting_Bit_26178': { + 'hash': 26178, + 'name': 'Hurting_Bit', + 'savables': {} + }, + 'MRK_Automated_Pipe_Hazard_Elevator_7.6_Variant_21038': { + 'hash': 21038, + 'name': 'MRK_Automated_Pipe_Hazard_Elevator_7.6_Variant', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + } + } + }, + 'Reset_Receiver_17642': { + 'hash': 17642, + 'name': 'Reset_Receiver', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + } + } + }, + 'Steam_Spray_61896': { + 'hash': 61896, + 'name': 'Steam_Spray', + 'savables': {} + }, + 'Steam_Start_37968': { + 'hash': 37968, + 'name': 'Steam_Start', + 'savables': {} + }, + 'mrk_risingPipe_body_20878': { + 'hash': 20878, + 'name': 'mrk_risingPipe_body', + 'savables': { + 'CurveOutput': { + 'hash': 2576456808, + 'name': 'CurveOutput' + } + } + } + } + }, + 'MRK_Automated_Pipe_Hazard_Elevator_Large_Inverse_Variant': { + 'hash': 34664, + 'name': 'MRK_Automated_Pipe_Hazard_Elevator_Large_Inverse_Variant', + 'embedded': { + 'Hurting_Bit_26178': { + 'hash': 26178, + 'name': 'Hurting_Bit', + 'savables': {} + }, + 'MRK_Automated_Pipe_Hazard_Elevator_Large_Inverse_Variant_21038': { + 'hash': 21038, + 'name': 'MRK_Automated_Pipe_Hazard_Elevator_Large_Inverse_Variant', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + } + } + }, + 'Reset_Receiver_17642': { + 'hash': 17642, + 'name': 'Reset_Receiver', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + } + } + }, + 'Steam_Spray_61896': { + 'hash': 61896, + 'name': 'Steam_Spray', + 'savables': {} + }, + 'Steam_Start_37968': { + 'hash': 37968, + 'name': 'Steam_Start', + 'savables': {} + }, + 'mrk_risingPipe_body_20878': { + 'hash': 20878, + 'name': 'mrk_risingPipe_body', + 'savables': { + 'CurveOutput': { + 'hash': 2576456808, + 'name': 'CurveOutput' + } + } + } + } + }, + 'MRK_Automated_Pipe_Hazard_Elevator_Tall_Variant': { + 'hash': 37626, + 'name': 'MRK_Automated_Pipe_Hazard_Elevator_Tall_Variant', + 'embedded': { + 'Hurting_Bit_26178': { + 'hash': 26178, + 'name': 'Hurting_Bit', + 'savables': {} + }, + 'MRK_Automated_Pipe_Hazard_Elevator_Tall_Variant_21038': { + 'hash': 21038, + 'name': 'MRK_Automated_Pipe_Hazard_Elevator_Tall_Variant', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + } + } + }, + 'Reset_Receiver_17642': { + 'hash': 17642, + 'name': 'Reset_Receiver', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + } + } + }, + 'Steam_Spray_61896': { + 'hash': 61896, + 'name': 'Steam_Spray', + 'savables': {} + }, + 'Steam_Start_37968': { + 'hash': 37968, + 'name': 'Steam_Start', + 'savables': {} + }, + 'mrk_risingPipe_body_20878': { + 'hash': 20878, + 'name': 'mrk_risingPipe_body', + 'savables': { + 'CurveOutput': { + 'hash': 2576456808, + 'name': 'CurveOutput' + } + } + } + } + }, + 'MRK_Fuel_Core': { + 'hash': 65358, + 'name': 'MRK_Fuel_Core', + 'embedded': { + 'MRK_Fuel_Core_63598': { + 'hash': 63598, + 'name': 'MRK_Fuel_Core', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MRK_Horizontal_Lift': { + 'hash': 37822, + 'name': 'MRK_Horizontal_Lift', + 'embedded': { + 'MRK_Horizontal_Lift_37846': { + 'hash': 37846, + 'name': 'MRK_Horizontal_Lift', + 'savables': { + 'LogicFloatReceiver': { + 'hash': 3188272159, + 'name': 'LogicFloatReceiver' + }, + 'NetworkedFloatStream': { + 'hash': 2127962967, + 'name': 'NetworkedFloatStream' + } + } + }, + 'Platform_57570': { + 'hash': 57570, + 'name': 'Platform', + 'savables': { + 'WayPointPath': { + 'hash': 1063725326, + 'name': 'WayPointPath' + } + } + } + } + }, + 'MRK_Lantern_01': { + 'hash': 36130, + 'name': 'MRK_Lantern_01', + 'embedded': { + 'MRK_Lantern_01_992': { + 'hash': 992, + 'name': 'MRK_Lantern_01', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + } + } + } + } + }, + 'MRK_Lantern_Fire': { + 'hash': 29468, + 'name': 'MRK_Lantern_Fire', + 'embedded': { + 'Fire_29440': { + 'hash': 29440, + 'name': 'Fire', + 'savables': { + 'Fire': { + 'hash': 3457519710, + 'name': 'Fire' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MRK_Lantern_Fire_29466': { + 'hash': 29466, + 'name': 'MRK_Lantern_Fire', + 'savables': { + 'FireLogic': { + 'hash': 1509838052, + 'name': 'FireLogic' + }, + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + } + } + } + } + }, + 'MRK_Large_Gear_Variant': { + 'hash': 29874, + 'name': 'MRK_Large_Gear_Variant', + 'embedded': { + 'MRK_Large_Gear_Variant_26800': { + 'hash': 26800, + 'name': 'MRK_Large_Gear_Variant', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + } + } + }, + 'Start_Rotating_5010': { + 'hash': 5010, + 'name': 'Start_Rotating', + 'savables': {} + }, + 'Stop_Rotating_4822': { + 'hash': 4822, + 'name': 'Stop_Rotating', + 'savables': {} + } + } + }, + 'MRK_Large_Lever': { + 'hash': 12812, + 'name': 'MRK_Large_Lever', + 'embedded': { + 'MRK_Large_Lever_9436': { + 'hash': 9436, + 'name': 'MRK_Large_Lever', + 'savables': { + 'Lever': { + 'hash': 1594932294, + 'name': 'Lever' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + } + } + }, + 'mrk_large_lever_handle_ROT_2408': { + 'hash': 2408, + 'name': 'mrk_large_lever_handle_ROT', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'mrk_large_lever_handle_grip_44324': { + 'hash': 44324, + 'name': 'mrk_large_lever_handle_grip', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'MRK_Liftable_Pipe_Gate': { + 'hash': 9344, + 'name': 'MRK_Liftable_Pipe_Gate', + 'embedded': { + 'Bottom_Handle_14368': { + 'hash': 14368, + 'name': 'Bottom_Handle', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Handle_60880': { + 'hash': 60880, + 'name': 'Handle', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Handle_9490': { + 'hash': 9490, + 'name': 'Handle', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'MRK_Liftable_Pipe_Gate_47896': { + 'hash': 47896, + 'name': 'MRK_Liftable_Pipe_Gate', + 'savables': {} + }, + 'mrk_pipe_gate_door_41532': { + 'hash': 41532, + 'name': 'mrk_pipe_gate_door', + 'savables': { + 'MovePickup': { + 'hash': 1874870249, + 'name': 'MovePickup' + } + } + } + } + }, + 'MRK_Molten_Core': { + 'hash': 51764, + 'name': 'MRK_Molten_Core', + 'embedded': { + 'MRK_Molten_Core_21206': { + 'hash': 21206, + 'name': 'MRK_Molten_Core', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MRK_Pipe_Gate': { + 'hash': 49320, + 'name': 'MRK_Pipe_Gate', + 'embedded': { + 'MRK_Pipe_Gate_47896': { + 'hash': 47896, + 'name': 'MRK_Pipe_Gate', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'SlidingDoor': { + 'hash': 3583462804, + 'name': 'SlidingDoor' + } + } + } + } + }, + 'MRK_Puzzle_Core_01': { + 'hash': 14158, + 'name': 'MRK_Puzzle_Core_01', + 'embedded': { + 'MRK_Puzzle_Core_01_12014': { + 'hash': 12014, + 'name': 'MRK_Puzzle_Core_01', + 'savables': { + 'MultiHandPickup': { + 'hash': 1556697998, + 'name': 'MultiHandPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'MRK_Puzzle_Core_02': { + 'hash': 28416, + 'name': 'MRK_Puzzle_Core_02', + 'embedded': { + 'MRK_Puzzle_Core_02_12014': { + 'hash': 12014, + 'name': 'MRK_Puzzle_Core_02', + 'savables': { + 'MultiHandPickup': { + 'hash': 1556697998, + 'name': 'MultiHandPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'MRK_Puzzle_Core_Initial_Stand_01_Variant': { + 'hash': 60550, + 'name': 'MRK_Puzzle_Core_Initial_Stand_01_Variant', + 'embedded': { + 'MRK_Puzzle_Core_Initial_Stand_01_Variant_57012': { + 'hash': 57012, + 'name': 'MRK_Puzzle_Core_Initial_Stand_01_Variant', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'LogicIntSender': { + 'hash': 2880587164, + 'name': 'LogicIntSender' + }, + 'PlaceItemPuzzleLogic': { + 'hash': 1001395212, + 'name': 'PlaceItemPuzzleLogic' + } + } + }, + 'Pedestal_Dock_27002': { + 'hash': 27002, + 'name': 'Pedestal_Dock', + 'savables': { + 'PickupDockPedestalSpawn': { + 'hash': 2592242915, + 'name': 'PickupDockPedestalSpawn' + } + } + } + } + }, + 'MRK_Puzzle_Core_Initial_Stand_02_Variant': { + 'hash': 30056, + 'name': 'MRK_Puzzle_Core_Initial_Stand_02_Variant', + 'embedded': { + 'MRK_Puzzle_Core_Initial_Stand_02_Variant_57012': { + 'hash': 57012, + 'name': 'MRK_Puzzle_Core_Initial_Stand_02_Variant', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'LogicIntSender': { + 'hash': 2880587164, + 'name': 'LogicIntSender' + }, + 'PlaceItemPuzzleLogic': { + 'hash': 1001395212, + 'name': 'PlaceItemPuzzleLogic' + } + } + }, + 'Pedestal_Dock_27002': { + 'hash': 27002, + 'name': 'Pedestal_Dock', + 'savables': { + 'PickupDockPedestalSpawn': { + 'hash': 2592242915, + 'name': 'PickupDockPedestalSpawn' + } + } + } + } + }, + 'MRK_Puzzle_Core_Stand_01': { + 'hash': 58540, + 'name': 'MRK_Puzzle_Core_Stand_01', + 'embedded': { + 'MRK_Puzzle_Core_Stand_01_57012': { + 'hash': 57012, + 'name': 'MRK_Puzzle_Core_Stand_01', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'LogicIntSender': { + 'hash': 2880587164, + 'name': 'LogicIntSender' + }, + 'PlaceItemPuzzleLogic': { + 'hash': 1001395212, + 'name': 'PlaceItemPuzzleLogic' + } + } + }, + 'Pedestal_Dock_27002': { + 'hash': 27002, + 'name': 'Pedestal_Dock', + 'savables': { + 'PickupDockPedestalSpawn': { + 'hash': 2592242915, + 'name': 'PickupDockPedestalSpawn' + } + } + } + } + }, + 'MRK_Puzzle_Core_Stand_02': { + 'hash': 34594, + 'name': 'MRK_Puzzle_Core_Stand_02', + 'embedded': { + 'MRK_Puzzle_Core_Stand_02_57012': { + 'hash': 57012, + 'name': 'MRK_Puzzle_Core_Stand_02', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'LogicIntSender': { + 'hash': 2880587164, + 'name': 'LogicIntSender' + }, + 'PlaceItemPuzzleLogic': { + 'hash': 1001395212, + 'name': 'PlaceItemPuzzleLogic' + } + } + }, + 'Pedestal_Dock_27002': { + 'hash': 27002, + 'name': 'Pedestal_Dock', + 'savables': { + 'PickupDockPedestalSpawn': { + 'hash': 2592242915, + 'name': 'PickupDockPedestalSpawn' + } + } + } + } + }, + 'MRK_Slip_Door': { + 'hash': 14114, + 'name': 'MRK_Slip_Door', + 'embedded': { + 'Grip_22142': { + 'hash': 22142, + 'name': 'Grip', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_22248': { + 'hash': 22248, + 'name': 'Grip', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_Point_21894': { + 'hash': 21894, + 'name': 'Grip_Point', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_Point_21920': { + 'hash': 21920, + 'name': 'Grip_Point', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_Point_22194': { + 'hash': 22194, + 'name': 'Grip_Point', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_Point_22228': { + 'hash': 22228, + 'name': 'Grip_Point', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_Point_22240': { + 'hash': 22240, + 'name': 'Grip_Point', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'MRK_Slip_Door_26828': { + 'hash': 26828, + 'name': 'MRK_Slip_Door', + 'savables': {} + }, + 'mrk_slipDoor_gate_26512': { + 'hash': 26512, + 'name': 'mrk_slipDoor_gate', + 'savables': { + 'MovePickup': { + 'hash': 1874870249, + 'name': 'MovePickup' + } + } + } + } + }, + 'MRK_Small_Lever': { + 'hash': 1330, + 'name': 'MRK_Small_Lever', + 'embedded': { + 'MRK_Small_Lever_9436': { + 'hash': 9436, + 'name': 'MRK_Small_Lever', + 'savables': { + 'Lever': { + 'hash': 1594932294, + 'name': 'Lever' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + } + } + }, + 'mrk_large_lever_handle_grip_44324': { + 'hash': 44324, + 'name': 'mrk_large_lever_handle_grip', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'mrk_small_lever_handle_ROT_29376': { + 'hash': 29376, + 'name': 'mrk_small_lever_handle_ROT', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'MRK_Smelter_Gem_Pedestal_1': { + 'hash': 33006, + 'name': 'MRK_Smelter_Gem_Pedestal_1', + 'embedded': { + 'MRK_Smelter_Gem_Pedestal_1_27194': { + 'hash': 27194, + 'name': 'MRK_Smelter_Gem_Pedestal_1', + 'savables': {} + }, + 'Pedestal_Dock_27002': { + 'hash': 27002, + 'name': 'Pedestal_Dock', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'PickupDockPedestalSpawn': { + 'hash': 2592242915, + 'name': 'PickupDockPedestalSpawn' + } + } + } + } + }, + 'MRK_Smelter_Gem_Pedestal_2': { + 'hash': 56376, + 'name': 'MRK_Smelter_Gem_Pedestal_2', + 'embedded': { + 'MRK_Smelter_Gem_Pedestal_2_27194': { + 'hash': 27194, + 'name': 'MRK_Smelter_Gem_Pedestal_2', + 'savables': {} + }, + 'Pedestal_Dock_27002': { + 'hash': 27002, + 'name': 'Pedestal_Dock', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'PickupDockPedestalSpawn': { + 'hash': 2592242915, + 'name': 'PickupDockPedestalSpawn' + } + } + } + } + }, + 'MRK_Smelter_Gem_Pedestal_3': { + 'hash': 57516, + 'name': 'MRK_Smelter_Gem_Pedestal_3', + 'embedded': { + 'MRK_Smelter_Gem_Pedestal_3_27194': { + 'hash': 27194, + 'name': 'MRK_Smelter_Gem_Pedestal_3', + 'savables': {} + }, + 'Pedestal_Dock_27002': { + 'hash': 27002, + 'name': 'Pedestal_Dock', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'PickupDockPedestalSpawn': { + 'hash': 2592242915, + 'name': 'PickupDockPedestalSpawn' + } + } + } + } + }, + 'MRK_TeleporterOut': { + 'hash': 49418, + 'name': 'MRK_TeleporterOut', + 'embedded': { + 'MRK_Tele_Target_38234': { + 'hash': 38234, + 'name': 'MRK_Tele_Target', + 'savables': {} + }, + 'MRK_TeleporterOut_7710': { + 'hash': 7710, + 'name': 'MRK_TeleporterOut', + 'savables': { + 'LogicVector3Receiver': { + 'hash': 1228539097, + 'name': 'LogicVector3Receiver' + }, + 'LogicVector3Sender': { + 'hash': 2026743731, + 'name': 'LogicVector3Sender' + }, + 'PositionProvider': { + 'hash': 3538443740, + 'name': 'PositionProvider' + }, + 'TeleportationPoint': { + 'hash': 3146178080, + 'name': 'TeleportationPoint' + } + } + }, + 'Teleporter_27092': { + 'hash': 27092, + 'name': 'Teleporter', + 'savables': {} + } + } + }, + 'MRK_Wheel_Bridge': { + 'hash': 61844, + 'name': 'MRK_Wheel_Bridge', + 'embedded': { + 'Crank_Rise_8062': { + 'hash': 8062, + 'name': 'Crank_Rise', + 'savables': {} + }, + 'MRK_Wheel_Bridge_43884': { + 'hash': 43884, + 'name': 'MRK_Wheel_Bridge', + 'savables': { + 'LogicFloatReceiver': { + 'hash': 3188272159, + 'name': 'LogicFloatReceiver' + }, + 'LogicFloatSender': { + 'hash': 2120963769, + 'name': 'LogicFloatSender' + }, + 'RotatePickup': { + 'hash': 2498617949, + 'name': 'RotatePickup' + } + } + }, + 'mrk_large_handle_01_23224': { + 'hash': 23224, + 'name': 'mrk_large_handle_01', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'mrk_large_handle_01_23226': { + 'hash': 23226, + 'name': 'mrk_large_handle_01', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'mrk_large_handle_01_23228': { + 'hash': 23228, + 'name': 'mrk_large_handle_01', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'mrk_large_handle_01_23230': { + 'hash': 23230, + 'name': 'mrk_large_handle_01', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'mrk_large_handle_01_52566': { + 'hash': 52566, + 'name': 'mrk_large_handle_01', + 'savables': { + 'Crank': { + 'hash': 1588536425, + 'name': 'Crank' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'mrk_rotating_platform_ROT_35674': { + 'hash': 35674, + 'name': 'mrk_rotating_platform_ROT', + 'savables': { + 'WheelGrab': { + 'hash': 320224849, + 'name': 'WheelGrab' + } + } + } + } + }, + 'MRK_activation_lever': { + 'hash': 35030, + 'name': 'MRK_activation_lever', + 'embedded': { + 'Cost_Definition_20328': { + 'hash': 20328, + 'name': 'Cost_Definition', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_22852': { + 'hash': 22852, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Gacha_Turn_15766': { + 'hash': 15766, + 'name': 'Gacha_Turn', + 'savables': {} + }, + 'MRK_activation_lever_34108': { + 'hash': 34108, + 'name': 'MRK_activation_lever', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'MRK_ActivationLever': { + 'hash': 2069630919, + 'name': 'MRK_ActivationLever' + } + } + }, + 'Stop_Rotating_48244': { + 'hash': 48244, + 'name': 'Stop_Rotating', + 'savables': {} + }, + 'Stop_Rotating_48620': { + 'hash': 48620, + 'name': 'Stop_Rotating', + 'savables': {} + }, + 'mrk_activation_lever_ROT_8682': { + 'hash': 8682, + 'name': 'mrk_activation_lever_ROT', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'MRK_gate_01': { + 'hash': 3094, + 'name': 'MRK_gate_01', + 'embedded': { + 'MRK_gate_01_42408': { + 'hash': 42408, + 'name': 'MRK_gate_01', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'SlidingDoor': { + 'hash': 3583462804, + 'name': 'SlidingDoor' + } + } + } + } + }, + 'MRK_gate_01_1.5x_Variant': { + 'hash': 64136, + 'name': 'MRK_gate_01_1.5x_Variant', + 'embedded': { + 'MRK_gate_01_1.5x_Variant_42408': { + 'hash': 42408, + 'name': 'MRK_gate_01_1.5x_Variant', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'SlidingDoor': { + 'hash': 3583462804, + 'name': 'SlidingDoor' + } + } + } + } + }, + 'MRK_gate_02': { + 'hash': 54328, + 'name': 'MRK_gate_02', + 'embedded': { + 'MRK_gate_02_42408': { + 'hash': 42408, + 'name': 'MRK_gate_02', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'SlidingDoor': { + 'hash': 3583462804, + 'name': 'SlidingDoor' + } + } + } + } + }, + 'MRK_heartReceptacle_01': { + 'hash': 9566, + 'name': 'MRK_heartReceptacle_01', + 'embedded': { + 'Hand_Touch_13548': { + 'hash': 13548, + 'name': 'Hand_Touch', + 'savables': {} + }, + 'MRK_heartReceptacle_01_7518': { + 'hash': 7518, + 'name': 'MRK_heartReceptacle_01', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'OneTimeUpgradeInteraction': { + 'hash': 3230087383, + 'name': 'OneTimeUpgradeInteraction' + } + } + } + } + }, + 'Mail_Deposit_Box': { + 'hash': 64204, + 'name': 'Mail_Deposit_Box', + 'embedded': { + 'Cost_Dock_9564': { + 'hash': 9564, + 'name': 'Cost_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Handle_23190': { + 'hash': 23190, + 'name': 'Handle', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Mail_Deposit_Box_64110': { + 'hash': 64110, + 'name': 'Mail_Deposit_Box', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + }, + 'Scroller_64946': { + 'hash': 64946, + 'name': 'Scroller', + 'savables': {} + }, + 'Send_Dock_Area_33168': { + 'hash': 33168, + 'name': 'Send_Dock_Area', + 'savables': {} + }, + 'Sending_Dock_1_9562': { + 'hash': 9562, + 'name': 'Sending_Dock_1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Sending_Dock_2_54962': { + 'hash': 54962, + 'name': 'Sending_Dock_2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Sending_Dock_3_9442': { + 'hash': 9442, + 'name': 'Sending_Dock_3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'mail_depositBox_swivel_51358': { + 'hash': 51358, + 'name': 'mail_depositBox_swivel', + 'savables': {} + }, + 'scroller_throttle_handMetal_LOD0_31026': { + 'hash': 31026, + 'name': 'scroller_throttle_handMetal_LOD0', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Main_Menu_Controller': { + 'hash': 58810, + 'name': 'Main_Menu_Controller', + 'embedded': {} + }, + 'Map_Board': { + 'hash': 60974, + 'name': 'Map_Board', + 'embedded': { + 'Hand_Touch_46540': { + 'hash': 46540, + 'name': 'Hand_Touch', + 'savables': {} + }, + 'Map_Board_63822': { + 'hash': 63822, + 'name': 'Map_Board', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + }, + 'Landmark': { + 'hash': 2590537994, + 'name': 'Landmark' + }, + 'LandmarkDiscoverZone': { + 'hash': 4095875831, + 'name': 'LandmarkDiscoverZone' + }, + 'MapBoard': { + 'hash': 2443660852, + 'name': 'MapBoard' + } + } + } + } + }, + 'Material_Box': { + 'hash': 46376, + 'name': 'Material_Box', + 'embedded': { + 'Loot_Spawner_46196': { + 'hash': 46196, + 'name': 'Loot_Spawner', + 'savables': {} + }, + 'Material_Box_46360': { + 'hash': 46360, + 'name': 'Material_Box', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Pieces_Spawner_23704': { + 'hash': 23704, + 'name': 'Pieces_Spawner', + 'savables': {} + } + } + }, + 'Material_Box_Pieces': { + 'hash': 42982, + 'name': 'Material_Box_Pieces', + 'embedded': { + 'Material_Box_Pieces_43372': { + 'hash': 43372, + 'name': 'Material_Box_Pieces', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Metal_Bow': { + 'hash': 25100, + 'name': 'Metal_Bow', + 'embedded': { + 'Arrow_Dock_25108': { + 'hash': 25108, + 'name': 'Arrow_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Metal_Bow_25094': { + 'hash': 25094, + 'name': 'Metal_Bow', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_Bow_Blade_10188': { + 'hash': 10188, + 'name': 'Slot_Bow_Blade', + 'savables': {} + }, + 'Slot_Bow_Blade_252': { + 'hash': 252, + 'name': 'Slot_Bow_Blade', + 'savables': {} + }, + 'Slot_Deco_61122': { + 'hash': 61122, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_65334': { + 'hash': 65334, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'String_25106': { + 'hash': 25106, + 'name': 'String', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Metal_Hammer_Head': { + 'hash': 22876, + 'name': 'Metal_Hammer_Head', + 'embedded': { + 'Heat_Point_Collection_1368': { + 'hash': 1368, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_HammerType_End_Cap_52192': { + 'hash': 52192, + 'name': 'Insert_HammerType_End_Cap', + 'savables': {} + }, + 'Metal_Hammer_Head_42978': { + 'hash': 42978, + 'name': 'Metal_Hammer_Head', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_Deco_37872': { + 'hash': 37872, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_48318': { + 'hash': 48318, + 'name': 'Slot_Deco', + 'savables': {} + } + } + }, + 'Metal_Hebios_Katana_Blade': { + 'hash': 17174, + 'name': 'Metal_Hebios_Katana_Blade', + 'embedded': { + 'Insert_Straight_SwordType_7796': { + 'hash': 7796, + 'name': 'Insert_Straight_SwordType', + 'savables': {} + }, + 'Metal_Hebios_Katana_Blade_57166': { + 'hash': 57166, + 'name': 'Metal_Hebios_Katana_Blade', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'katana_blade_part_full_30124': { + 'hash': 30124, + 'name': 'katana_blade_part_full', + 'savables': {} + } + } + }, + 'Metal_Hebios_Naginata_Blade': { + 'hash': 15124, + 'name': 'Metal_Hebios_Naginata_Blade', + 'embedded': { + 'Insert_Straight_SwordType_7796': { + 'hash': 7796, + 'name': 'Insert_Straight_SwordType', + 'savables': {} + }, + 'Metal_Hebios_Naginata_Blade_57606': { + 'hash': 57606, + 'name': 'Metal_Hebios_Naginata_Blade', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'naginata_blade_LOD0_56264': { + 'hash': 56264, + 'name': 'naginata_blade_LOD0', + 'savables': {} + } + } + }, + 'Metal_Hebios_Sai_Blade': { + 'hash': 53124, + 'name': 'Metal_Hebios_Sai_Blade', + 'embedded': { + 'Insert_Straight_Short_SwordType_7796': { + 'hash': 7796, + 'name': 'Insert_Straight_Short_SwordType', + 'savables': {} + }, + 'Metal_Hebios_Sai_Blade_57606': { + 'hash': 57606, + 'name': 'Metal_Hebios_Sai_Blade', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'sai_blade_LOD0_11144': { + 'hash': 11144, + 'name': 'sai_blade_LOD0', + 'savables': {} + } + } + }, + 'Metal_Hebios_Wakizashi_Blade': { + 'hash': 48902, + 'name': 'Metal_Hebios_Wakizashi_Blade', + 'embedded': { + 'Insert_Straight_Short_SwordType_7796': { + 'hash': 7796, + 'name': 'Insert_Straight_Short_SwordType', + 'savables': {} + }, + 'Metal_Hebios_Wakizashi_Blade_57606': { + 'hash': 57606, + 'name': 'Metal_Hebios_Wakizashi_Blade', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'wakizashi_blade_26702': { + 'hash': 26702, + 'name': 'wakizashi_blade', + 'savables': {} + } + } + }, + 'Metal_Tap': { + 'hash': 17334, + 'name': 'Metal_Tap', + 'embedded': { + 'Metal_Tap_20796': { + 'hash': 20796, + 'name': 'Metal_Tap', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Metal_Wall_Hook': { + 'hash': 61180, + 'name': 'Metal_Wall_Hook', + 'embedded': {} + }, + 'Mining_Base_Generator': { + 'hash': 6714, + 'name': 'Mining_Base_Generator', + 'embedded': { + 'Mining_Base_Generator_6374': { + 'hash': 6374, + 'name': 'Mining_Base_Generator', + 'savables': {} + } + } + }, + 'Mining_Path': { + 'hash': 30950, + 'name': 'Mining_Path', + 'embedded': { + 'Mining_Path_30946': { + 'hash': 30946, + 'name': 'Mining_Path', + 'savables': { + 'PopulationPath': { + 'hash': 7704646, + 'name': 'PopulationPath' + } + } + } + } + }, + 'Modular_Backpack': { + 'hash': 12060, + 'name': 'Modular_Backpack', + 'embedded': {} + }, + 'Modular_Hook': { + 'hash': 60188, + 'name': 'Modular_Hook', + 'embedded': {} + }, + 'Modular_Sack': { + 'hash': 8344, + 'name': 'Modular_Sack', + 'embedded': {} + }, + 'Mother_Fern': { + 'hash': 65004, + 'name': 'Mother_Fern', + 'embedded': { + 'Death_Fern_AI_29794': { + 'hash': 29794, + 'name': 'Death_Fern_AI', + 'savables': {} + }, + 'Emit_Gas_Spawner_16984': { + 'hash': 16984, + 'name': 'Emit_Gas_Spawner', + 'savables': {} + }, + 'Mesh_15308': { + 'hash': 15308, + 'name': 'Mesh', + 'savables': {} + }, + 'Mother_Fern_37626': { + 'hash': 37626, + 'name': 'Mother_Fern', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Seed_Spray_1172': { + 'hash': 1172, + 'name': 'Seed_Spray', + 'savables': {} + } + } + }, + 'Mother_Fern_Seed_Spray': { + 'hash': 26710, + 'name': 'Mother_Fern_Seed_Spray', + 'embedded': { + 'Mother_Fern_Seed_Spray_44772': { + 'hash': 44772, + 'name': 'Mother_Fern_Seed_Spray', + 'savables': {} + } + } + }, + 'Mould': { + 'hash': 14826, + 'name': 'Mould', + 'embedded': { + 'Mould_14710': { + 'hash': 14710, + 'name': 'Mould', + 'savables': { + 'Mould': { + 'hash': 391977879, + 'name': 'Mould' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Mould_Press_Hebios': { + 'hash': 2594, + 'name': 'Mould_Press_Hebios', + 'embedded': { + 'Input_36080': { + 'hash': 36080, + 'name': 'Input', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Lever_Physics_45996': { + 'hash': 45996, + 'name': 'Lever_Physics', + 'savables': { + 'Lever': { + 'hash': 1594932294, + 'name': 'Lever' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Mould_Press_Hebios_65312': { + 'hash': 65312, + 'name': 'Mould_Press_Hebios', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + }, + 'Output_52720': { + 'hash': 52720, + 'name': 'Output', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + } + } + }, + 'Mould_Press_Standard': { + 'hash': 13362, + 'name': 'Mould_Press_Standard', + 'embedded': { + 'Input_36080': { + 'hash': 36080, + 'name': 'Input', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Lever_Physics_45996': { + 'hash': 45996, + 'name': 'Lever_Physics', + 'savables': { + 'Lever': { + 'hash': 1594932294, + 'name': 'Lever' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Mould_Press_Standard_65312': { + 'hash': 65312, + 'name': 'Mould_Press_Standard', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + }, + 'Output_52720': { + 'hash': 52720, + 'name': 'Output', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + } + } + }, + 'Mould_Rack': { + 'hash': 4070, + 'name': 'Mould_Rack', + 'embedded': { + 'Dock_57418': { + 'hash': 57418, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_57450': { + 'hash': 57450, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_57456': { + 'hash': 57456, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_57470': { + 'hash': 57470, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_57504': { + 'hash': 57504, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_57528': { + 'hash': 57528, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_57550': { + 'hash': 57550, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_57556': { + 'hash': 57556, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Mould_Rack_498': { + 'hash': 498, + 'name': 'Mould_Rack', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + }, + 'Rope_Grab_57800': { + 'hash': 57800, + 'name': 'Rope_Grab', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'RopeGrab': { + 'hash': 237360636, + 'name': 'RopeGrab' + } + } + }, + 'Rope_Length_57794': { + 'hash': 57794, + 'name': 'Rope_Length', + 'savables': {} + } + } + }, + 'Mould_Restriction_Zone': { + 'hash': 4900, + 'name': 'Mould_Restriction_Zone', + 'embedded': { + 'Mould_Restriction_Zone_2804': { + 'hash': 2804, + 'name': 'Mould_Restriction_Zone', + 'savables': { + 'MouldRestrictor': { + 'hash': 1571096900, + 'name': 'MouldRestrictor' + } + } + } + } + }, + 'MushroomBrown_Full_Burnt': { + 'hash': 47126, + 'name': 'MushroomBrown_Full_Burnt', + 'embedded': { + 'Cooking_35920': { + 'hash': 35920, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomBrown_Full_Burnt_36010': { + 'hash': 36010, + 'name': 'MushroomBrown_Full_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomBrown_Full_Cooked': { + 'hash': 46510, + 'name': 'MushroomBrown_Full_Cooked', + 'embedded': { + 'Cooking_32900': { + 'hash': 32900, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomBrown_Full_Cooked_32990': { + 'hash': 32990, + 'name': 'MushroomBrown_Full_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomBrown_Full_Ripe': { + 'hash': 61666, + 'name': 'MushroomBrown_Full_Ripe', + 'embedded': { + 'Cooking_30802': { + 'hash': 30802, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomBrown_Full_Ripe_30892': { + 'hash': 30892, + 'name': 'MushroomBrown_Full_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomBrown_Half_Burnt': { + 'hash': 53372, + 'name': 'MushroomBrown_Half_Burnt', + 'embedded': { + 'Cooking_28740': { + 'hash': 28740, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomBrown_Half_Burnt_28794': { + 'hash': 28794, + 'name': 'MushroomBrown_Half_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomBrown_Half_Cooked': { + 'hash': 50916, + 'name': 'MushroomBrown_Half_Cooked', + 'embedded': { + 'Cooking_26756': { + 'hash': 26756, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomBrown_Half_Cooked_26810': { + 'hash': 26810, + 'name': 'MushroomBrown_Half_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomBrown_Half_Ripe': { + 'hash': 48460, + 'name': 'MushroomBrown_Half_Ripe', + 'embedded': { + 'Cooking_24846': { + 'hash': 24846, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomBrown_Half_Ripe_24900': { + 'hash': 24900, + 'name': 'MushroomBrown_Half_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomCaveLarge_Half_Burnt': { + 'hash': 60330, + 'name': 'MushroomCaveLarge_Half_Burnt', + 'embedded': { + 'Cooking_60736': { + 'hash': 60736, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomCaveLarge_Half_Burnt_61496': { + 'hash': 61496, + 'name': 'MushroomCaveLarge_Half_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomCaveLarge_Half_Cooked': { + 'hash': 9414, + 'name': 'MushroomCaveLarge_Half_Cooked', + 'embedded': { + 'Cooking_55004': { + 'hash': 55004, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomCaveLarge_Half_Cooked_55764': { + 'hash': 55764, + 'name': 'MushroomCaveLarge_Half_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomCaveLarge_Half_Ripe': { + 'hash': 54182, + 'name': 'MushroomCaveLarge_Half_Ripe', + 'embedded': { + 'Cooking_49572': { + 'hash': 49572, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomCaveLarge_Half_Ripe_50332': { + 'hash': 50332, + 'name': 'MushroomCaveLarge_Half_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomCaveSmall_Full_Burnt': { + 'hash': 29148, + 'name': 'MushroomCaveSmall_Full_Burnt', + 'embedded': { + 'Cooking_27474': { + 'hash': 27474, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomCaveSmall_Full_Burnt_28332': { + 'hash': 28332, + 'name': 'MushroomCaveSmall_Full_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomCaveSmall_Full_Cooked': { + 'hash': 40066, + 'name': 'MushroomCaveSmall_Full_Cooked', + 'embedded': { + 'Cooking_34902': { + 'hash': 34902, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomCaveSmall_Full_Cooked_35760': { + 'hash': 35760, + 'name': 'MushroomCaveSmall_Full_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomCaveSmall_Full_Ripe': { + 'hash': 58270, + 'name': 'MushroomCaveSmall_Full_Ripe', + 'embedded': { + 'Cooking_28844': { + 'hash': 28844, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomCaveSmall_Full_Ripe_29702': { + 'hash': 29702, + 'name': 'MushroomCaveSmall_Full_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomCaveSmall_Half_Burnt': { + 'hash': 47142, + 'name': 'MushroomCaveSmall_Half_Burnt', + 'embedded': { + 'Cooking_23588': { + 'hash': 23588, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomCaveSmall_Half_Burnt_23644': { + 'hash': 23644, + 'name': 'MushroomCaveSmall_Half_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomCaveSmall_Half_Cooked': { + 'hash': 44488, + 'name': 'MushroomCaveSmall_Half_Cooked', + 'embedded': { + 'Cooking_21474': { + 'hash': 21474, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomCaveSmall_Half_Cooked_21530': { + 'hash': 21530, + 'name': 'MushroomCaveSmall_Half_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomCaveSmall_Half_Ripe': { + 'hash': 41834, + 'name': 'MushroomCaveSmall_Half_Ripe', + 'embedded': { + 'Cooking_19434': { + 'hash': 19434, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomCaveSmall_Half_Ripe_19490': { + 'hash': 19490, + 'name': 'MushroomCaveSmall_Half_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomGlowing_Full_Burnt': { + 'hash': 43856, + 'name': 'MushroomGlowing_Full_Burnt', + 'embedded': { + 'Cooking_13584': { + 'hash': 13584, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomGlowing_Full_Burnt_41450': { + 'hash': 41450, + 'name': 'MushroomGlowing_Full_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomGlowing_Full_Cooked': { + 'hash': 41428, + 'name': 'MushroomGlowing_Full_Cooked', + 'embedded': { + 'Cooking_6452': { + 'hash': 6452, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomGlowing_Full_Cooked_14334': { + 'hash': 14334, + 'name': 'MushroomGlowing_Full_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomGlowing_Full_Ripe': { + 'hash': 38966, + 'name': 'MushroomGlowing_Full_Ripe', + 'embedded': { + 'Cooking_1062': { + 'hash': 1062, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomGlowing_Full_Ripe_33808': { + 'hash': 33808, + 'name': 'MushroomGlowing_Full_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomGlowing_Half_Burnt': { + 'hash': 36504, + 'name': 'MushroomGlowing_Half_Burnt', + 'embedded': { + 'Cooking_61912': { + 'hash': 61912, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomGlowing_Half_Burnt_37030': { + 'hash': 37030, + 'name': 'MushroomGlowing_Half_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomGlowing_Half_Cooked': { + 'hash': 34042, + 'name': 'MushroomGlowing_Half_Cooked', + 'embedded': { + 'Cooking_60048': { + 'hash': 60048, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomGlowing_Half_Cooked_14126': { + 'hash': 14126, + 'name': 'MushroomGlowing_Half_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomGlowing_Half_Ripe': { + 'hash': 31580, + 'name': 'MushroomGlowing_Half_Ripe', + 'embedded': { + 'Cooking_58186': { + 'hash': 58186, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomGlowing_Half_Ripe_59620': { + 'hash': 59620, + 'name': 'MushroomGlowing_Half_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomRed_Full_Burnt': { + 'hash': 46660, + 'name': 'MushroomRed_Full_Burnt', + 'embedded': { + 'Cooking_15932': { + 'hash': 15932, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomRed_Full_Burnt_16724': { + 'hash': 16724, + 'name': 'MushroomRed_Full_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomRed_Full_Cooked': { + 'hash': 46888, + 'name': 'MushroomRed_Full_Cooked', + 'embedded': { + 'Cooking_29424': { + 'hash': 29424, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomRed_Full_Cooked_30216': { + 'hash': 30216, + 'name': 'MushroomRed_Full_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomRed_Full_Ripe': { + 'hash': 61658, + 'name': 'MushroomRed_Full_Ripe', + 'embedded': { + 'Cooking_23868': { + 'hash': 23868, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomRed_Full_Ripe_24660': { + 'hash': 24660, + 'name': 'MushroomRed_Full_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomRed_Half_Burnt': { + 'hash': 43272, + 'name': 'MushroomRed_Half_Burnt', + 'embedded': { + 'Cooking_19050': { + 'hash': 19050, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomRed_Half_Burnt_19104': { + 'hash': 19104, + 'name': 'MushroomRed_Half_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomRed_Half_Cooked': { + 'hash': 40816, + 'name': 'MushroomRed_Half_Cooked', + 'embedded': { + 'Cooking_17118': { + 'hash': 17118, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomRed_Half_Cooked_17172': { + 'hash': 17172, + 'name': 'MushroomRed_Half_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'MushroomRed_Half_Ripe': { + 'hash': 38360, + 'name': 'MushroomRed_Half_Ripe', + 'embedded': { + 'Cooking_15260': { + 'hash': 15260, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'MushroomRed_Half_Ripe_15314': { + 'hash': 15314, + 'name': 'MushroomRed_Half_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Mushroom_Fairy_Circle_Puzzle': { + 'hash': 46706, + 'name': 'Mushroom_Fairy_Circle_Puzzle', + 'embedded': { + 'Mushroom_Fairy_Circle_Puzzle_28402': { + 'hash': 28402, + 'name': 'Mushroom_Fairy_Circle_Puzzle', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'SpawnInCircle': { + 'hash': 1714180166, + 'name': 'SpawnInCircle' + } + } + } + } + }, + 'Mushroom_Fairy_Circle_Puzzle_OLD': { + 'hash': 44688, + 'name': 'Mushroom_Fairy_Circle_Puzzle_OLD', + 'embedded': {} + }, + 'Mushroom_Fairy_Circle_Puzzle_Teleport': { + 'hash': 28040, + 'name': 'Mushroom_Fairy_Circle_Puzzle_Teleport', + 'embedded': { + 'Mushroom_Fairy_Circle_Puzzle_Teleport_8726': { + 'hash': 8726, + 'name': 'Mushroom_Fairy_Circle_Puzzle_Teleport', + 'savables': { + 'LogicVector3Receiver': { + 'hash': 1228539097, + 'name': 'LogicVector3Receiver' + }, + 'LogicVector3Sender': { + 'hash': 2026743731, + 'name': 'LogicVector3Sender' + }, + 'PositionProvider': { + 'hash': 3538443740, + 'name': 'PositionProvider' + }, + 'SpawnInCircle': { + 'hash': 1714180166, + 'name': 'SpawnInCircle' + }, + 'TeleportationPoint': { + 'hash': 3146178080, + 'name': 'TeleportationPoint' + } + } + } + } + }, + 'Mushroom_Mix_Recipe_Burnt_Stew': { + 'hash': 27398, + 'name': 'Mushroom_Mix_Recipe_Burnt_Stew', + 'embedded': {} + }, + 'Mushroom_Mix_Recipe_Cooked_Stew': { + 'hash': 27376, + 'name': 'Mushroom_Mix_Recipe_Cooked_Stew', + 'embedded': {} + }, + 'Mushroom_Mix_Recipe_Raw_Stew': { + 'hash': 14914, + 'name': 'Mushroom_Mix_Recipe_Raw_Stew', + 'embedded': {} + }, + 'Mushroom_Poultry_Recipe_Burnt_Stew': { + 'hash': 54614, + 'name': 'Mushroom_Poultry_Recipe_Burnt_Stew', + 'embedded': {} + }, + 'Mushroom_Poultry_Recipe_Cooked_Stew': { + 'hash': 55358, + 'name': 'Mushroom_Poultry_Recipe_Cooked_Stew', + 'embedded': {} + }, + 'Mushroom_Poultry_Recipe_Raw_Stew': { + 'hash': 55978, + 'name': 'Mushroom_Poultry_Recipe_Raw_Stew', + 'embedded': {} + }, + 'Mushroom_Recipe_Burnt_Stew': { + 'hash': 30560, + 'name': 'Mushroom_Recipe_Burnt_Stew', + 'embedded': {} + }, + 'Mushroom_Recipe_Cooked_Stew': { + 'hash': 31606, + 'name': 'Mushroom_Recipe_Cooked_Stew', + 'embedded': {} + }, + 'Mushroom_Recipe_Raw_Stew': { + 'hash': 32650, + 'name': 'Mushroom_Recipe_Raw_Stew', + 'embedded': {} + }, + 'Mythril_Boulder': { + 'hash': 27368, + 'name': 'Mythril_Boulder', + 'embedded': { + 'Mythril_Boulder_29328': { + 'hash': 29328, + 'name': 'Mythril_Boulder', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Spawn_Origin_18860': { + 'hash': 18860, + 'name': 'Spawn_Origin', + 'savables': {} + } + } + }, + 'Mythril_Boulder_Parts': { + 'hash': 43522, + 'name': 'Mythril_Boulder_Parts', + 'embedded': { + 'Mythril_Boulder_Parts_59770': { + 'hash': 59770, + 'name': 'Mythril_Boulder_Parts', + 'savables': {} + }, + 'Mythril_Boulder_part_01_59808': { + 'hash': 59808, + 'name': 'Mythril_Boulder_part_01', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Mythril_Boulder_part_02_59820': { + 'hash': 59820, + 'name': 'Mythril_Boulder_part_02', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Mythril_Boulder_part_03_59816': { + 'hash': 59816, + 'name': 'Mythril_Boulder_part_03', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Mythril_Boulder_part_04_59804': { + 'hash': 59804, + 'name': 'Mythril_Boulder_part_04', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Mythril_Boulder_part_05_59812': { + 'hash': 59812, + 'name': 'Mythril_Boulder_part_05', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Mythril_Ingot': { + 'hash': 24774, + 'name': 'Mythril_Ingot', + 'embedded': { + 'Heat_Point_Collection_13294': { + 'hash': 13294, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Mythril_Ingot_24662': { + 'hash': 24662, + 'name': 'Mythril_Ingot', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Mythril_Ore': { + 'hash': 11702, + 'name': 'Mythril_Ore', + 'embedded': { + 'Mythril_Ore_15610': { + 'hash': 15610, + 'name': 'Mythril_Ore', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Naginata': { + 'hash': 41052, + 'name': 'Naginata', + 'embedded': { + 'Naginata_36330': { + 'hash': 36330, + 'name': 'Naginata', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'Enchantable': { + 'hash': 4134534481, + 'name': 'Enchantable' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Name_Proxy': { + 'hash': 15340, + 'name': 'Name_Proxy', + 'embedded': {} + }, + 'Nand': { + 'hash': 42426, + 'name': 'Nand', + 'embedded': {} + }, + 'Navigation_wheel': { + 'hash': 20416, + 'name': 'Navigation_wheel', + 'embedded': { + 'Grip_(1)_54050': { + 'hash': 54050, + 'name': 'Grip_(1)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(2)_54614': { + 'hash': 54614, + 'name': 'Grip_(2)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(3)_56370': { + 'hash': 56370, + 'name': 'Grip_(3)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(4)_53470': { + 'hash': 53470, + 'name': 'Grip_(4)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_56728': { + 'hash': 56728, + 'name': 'Grip', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Navigation_wheel_16790': { + 'hash': 16790, + 'name': 'Navigation_wheel', + 'savables': {} + } + } + }, + 'New_Tree_Grower': { + 'hash': 62444, + 'name': 'New_Tree_Grower', + 'embedded': { + 'New_Tree_Grower_52858': { + 'hash': 52858, + 'name': 'New_Tree_Grower', + 'savables': { + 'GrowerComponent': { + 'hash': 3402094521, + 'name': 'GrowerComponent' + } + } + } + } + }, + 'Non_Recipe_Burnt_Stew': { + 'hash': 48634, + 'name': 'Non_Recipe_Burnt_Stew', + 'embedded': {} + }, + 'Non_Recipe_Cooked_Stew': { + 'hash': 49314, + 'name': 'Non_Recipe_Cooked_Stew', + 'embedded': {} + }, + 'Non_Recipe_Raw_Stew': { + 'hash': 49962, + 'name': 'Non_Recipe_Raw_Stew', + 'embedded': {} + }, + 'Nor': { + 'hash': 42420, + 'name': 'Nor', + 'embedded': {} + }, + 'Not': { + 'hash': 42414, + 'name': 'Not', + 'embedded': {} + }, + 'Oak_Tree_Growth': { + 'hash': 48238, + 'name': 'Oak_Tree_Growth', + 'embedded': { + 'Oak_Tree_Growth_33458': { + 'hash': 33458, + 'name': 'Oak_Tree_Growth', + 'savables': { + 'GrowerComponent': { + 'hash': 3402094521, + 'name': 'GrowerComponent' + } + } + } + } + }, + 'Oak_Tree_Seed': { + 'hash': 17302, + 'name': 'Oak_Tree_Seed', + 'embedded': { + 'Oak_Tree_Seed_35258': { + 'hash': 35258, + 'name': 'Oak_Tree_Seed', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'RaycastCrafter': { + 'hash': 2815374842, + 'name': 'RaycastCrafter' + } + } + } + } + }, + 'Oak_Tree_Stage_1': { + 'hash': 17412, + 'name': 'Oak_Tree_Stage_1', + 'embedded': { + 'Oak_Tree_Stage_1_63514': { + 'hash': 63514, + 'name': 'Oak_Tree_Stage_1', + 'savables': {} + } + } + }, + 'Obstacle_Path': { + 'hash': 62838, + 'name': 'Obstacle_Path', + 'embedded': { + 'Obstacle_Path_30946': { + 'hash': 30946, + 'name': 'Obstacle_Path', + 'savables': { + 'PopulationPath': { + 'hash': 7704646, + 'name': 'PopulationPath' + } + } + } + } + }, + 'One_Time_Upgrade_Station_Health': { + 'hash': 46992, + 'name': 'One_Time_Upgrade_Station_Health', + 'embedded': { + 'One_Time_Upgrade_Station_Health_46540': { + 'hash': 46540, + 'name': 'One_Time_Upgrade_Station_Health', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'OneTimeUpgradeInteraction': { + 'hash': 3230087383, + 'name': 'OneTimeUpgradeInteraction' + } + } + } + } + }, + 'Onion_Full_Burnt': { + 'hash': 48718, + 'name': 'Onion_Full_Burnt', + 'embedded': { + 'Cooking_61106': { + 'hash': 61106, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Onion_Full_Burnt_48300': { + 'hash': 48300, + 'name': 'Onion_Full_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Onion_Full_Cooked': { + 'hash': 48214, + 'name': 'Onion_Full_Cooked', + 'embedded': { + 'Cooking_60678': { + 'hash': 60678, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Onion_Full_Cooked_47812': { + 'hash': 47812, + 'name': 'Onion_Full_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Onion_Full_Ripe': { + 'hash': 47730, + 'name': 'Onion_Full_Ripe', + 'embedded': { + 'Cooking_58282': { + 'hash': 58282, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Leaves_Parent_20548': { + 'hash': 20548, + 'name': 'Leaves_Parent', + 'savables': {} + }, + 'Onion_Full_Ripe_44704': { + 'hash': 44704, + 'name': 'Onion_Full_Ripe', + 'savables': { + 'BuildupPickup': { + 'hash': 3373651539, + 'name': 'BuildupPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Roots_Parent_17652': { + 'hash': 17652, + 'name': 'Roots_Parent', + 'savables': {} + } + } + }, + 'Onion_Full_Unripe': { + 'hash': 43966, + 'name': 'Onion_Full_Unripe', + 'embedded': { + 'Cooking_57758': { + 'hash': 57758, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Onion_Full_Unripe_43436': { + 'hash': 43436, + 'name': 'Onion_Full_Unripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Onion_Half_Burnt': { + 'hash': 59314, + 'name': 'Onion_Half_Burnt', + 'embedded': { + 'Cooking_33410': { + 'hash': 33410, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Onion_Half_Burnt_58976': { + 'hash': 58976, + 'name': 'Onion_Half_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Onion_Half_Cooked': { + 'hash': 58910, + 'name': 'Onion_Half_Cooked', + 'embedded': { + 'Cooking_33064': { + 'hash': 33064, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Onion_Half_Cooked_58572': { + 'hash': 58572, + 'name': 'Onion_Half_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Onion_Half_Ripe': { + 'hash': 58506, + 'name': 'Onion_Half_Ripe', + 'embedded': { + 'Cooking_32718': { + 'hash': 32718, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Onion_Half_Ripe_58168': { + 'hash': 58168, + 'name': 'Onion_Half_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Onion_Half_Unripe': { + 'hash': 58102, + 'name': 'Onion_Half_Unripe', + 'embedded': { + 'Cooking_32372': { + 'hash': 32372, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Onion_Half_Unripe_57764': { + 'hash': 57764, + 'name': 'Onion_Half_Unripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Onion_Leaves': { + 'hash': 29078, + 'name': 'Onion_Leaves', + 'embedded': { + 'Onion_Leaves_31538': { + 'hash': 31538, + 'name': 'Onion_Leaves', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'PullPickup_51602': { + 'hash': 51602, + 'name': 'PullPickup', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Onion_Roots': { + 'hash': 32068, + 'name': 'Onion_Roots', + 'embedded': { + 'Onion_Roots_47660': { + 'hash': 47660, + 'name': 'Onion_Roots', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'PullPickup_32872': { + 'hash': 32872, + 'name': 'PullPickup', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Or': { + 'hash': 42416, + 'name': 'Or', + 'embedded': {} + }, + 'Orchi_Ingot': { + 'hash': 16464, + 'name': 'Orchi_Ingot', + 'embedded': { + 'Heat_Point_Collection_13422': { + 'hash': 13422, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Orchi_Ingot_32738': { + 'hash': 32738, + 'name': 'Orchi_Ingot', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Ore_Bag': { + 'hash': 64560, + 'name': 'Ore_Bag', + 'embedded': { + 'Bag_Body_42972': { + 'hash': 42972, + 'name': 'Bag_Body', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Dock_BM_63062': { + 'hash': 63062, + 'name': 'Dock_BM', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_L_63242': { + 'hash': 63242, + 'name': 'Dock_L', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_R_63236': { + 'hash': 63236, + 'name': 'Dock_R', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_TM_63222': { + 'hash': 63222, + 'name': 'Dock_TM', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Ore_Bag_43012': { + 'hash': 43012, + 'name': 'Ore_Bag', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_Bag_Attach_30776': { + 'hash': 30776, + 'name': 'Slot_Bag_Attach', + 'savables': {} + }, + 'Slot_Bag_Attach_55164': { + 'hash': 55164, + 'name': 'Slot_Bag_Attach', + 'savables': {} + }, + 'Slot_Bag_Attach_62396': { + 'hash': 62396, + 'name': 'Slot_Bag_Attach', + 'savables': {} + }, + 'Slot_Bag_Tool_Attachment_36292': { + 'hash': 36292, + 'name': 'Slot_Bag_Tool_Attachment', + 'savables': {} + }, + 'Slot_Bag_Tool_Attachment_36386': { + 'hash': 36386, + 'name': 'Slot_Bag_Tool_Attachment', + 'savables': {} + }, + 'ore_bag_frame_01_44248': { + 'hash': 44248, + 'name': 'ore_bag_frame_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_frame_02_44244': { + 'hash': 44244, + 'name': 'ore_bag_frame_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_frame_03_44312': { + 'hash': 44312, + 'name': 'ore_bag_frame_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_frame_04_44308': { + 'hash': 44308, + 'name': 'ore_bag_frame_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_rim_bottom_44264': { + 'hash': 44264, + 'name': 'ore_bag_rim_bottom', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_rim_top_44288': { + 'hash': 44288, + 'name': 'ore_bag_rim_top', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_sack_44268': { + 'hash': 44268, + 'name': 'ore_bag_sack', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_stick_01_44328': { + 'hash': 44328, + 'name': 'ore_bag_stick_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_stick_02_44296': { + 'hash': 44296, + 'name': 'ore_bag_stick_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_stick_03_44284': { + 'hash': 44284, + 'name': 'ore_bag_stick_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_stick_04_44228': { + 'hash': 44228, + 'name': 'ore_bag_stick_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_stick_05_44224': { + 'hash': 44224, + 'name': 'ore_bag_stick_05', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_stick_06_44304': { + 'hash': 44304, + 'name': 'ore_bag_stick_06', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_stick_07_44300': { + 'hash': 44300, + 'name': 'ore_bag_stick_07', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_stick_08_44240': { + 'hash': 44240, + 'name': 'ore_bag_stick_08', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_stick_09_44236': { + 'hash': 44236, + 'name': 'ore_bag_stick_09', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_stick_10_44324': { + 'hash': 44324, + 'name': 'ore_bag_stick_10', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_stick_11_44320': { + 'hash': 44320, + 'name': 'ore_bag_stick_11', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_stick_12_44280': { + 'hash': 44280, + 'name': 'ore_bag_stick_12', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_stick_13_44232': { + 'hash': 44232, + 'name': 'ore_bag_stick_13', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_strawBind_01_44316': { + 'hash': 44316, + 'name': 'ore_bag_strawBind_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_strawBind_02_44260': { + 'hash': 44260, + 'name': 'ore_bag_strawBind_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_strawBind_03_44276': { + 'hash': 44276, + 'name': 'ore_bag_strawBind_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_strawBind_04_44272': { + 'hash': 44272, + 'name': 'ore_bag_strawBind_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_strawBind_05_44256': { + 'hash': 44256, + 'name': 'ore_bag_strawBind_05', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_strawBind_06_44252': { + 'hash': 44252, + 'name': 'ore_bag_strawBind_06', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_strawBind_07_44292': { + 'hash': 44292, + 'name': 'ore_bag_strawBind_07', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_handle_body_14308': { + 'hash': 14308, + 'name': 'standard_bag_handle_body', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_bag_handle_wraps_14304': { + 'hash': 14304, + 'name': 'standard_bag_handle_wraps', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Ore_Side_Pouch_Attachment': { + 'hash': 61020, + 'name': 'Ore_Side_Pouch_Attachment', + 'embedded': { + 'Dock_45700': { + 'hash': 45700, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62078': { + 'hash': 62078, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Insert_Bag_Attach_7796': { + 'hash': 7796, + 'name': 'Insert_Bag_Attach', + 'savables': {} + }, + 'Ore_Side_Pouch_Attachment_7868': { + 'hash': 7868, + 'name': 'Ore_Side_Pouch_Attachment', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Storage_53834': { + 'hash': 53834, + 'name': 'Storage', + 'savables': {} + }, + 'ore_bag_attachment_cloth_01_30702': { + 'hash': 30702, + 'name': 'ore_bag_attachment_cloth_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_attachment_cloth_cover_43718': { + 'hash': 43718, + 'name': 'ore_bag_attachment_cloth_cover', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_attachment_knot_01_30682': { + 'hash': 30682, + 'name': 'ore_bag_attachment_knot_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_attachment_knot_02_30678': { + 'hash': 30678, + 'name': 'ore_bag_attachment_knot_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_attachment_knot_03_30674': { + 'hash': 30674, + 'name': 'ore_bag_attachment_knot_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_attachment_knot_04_30670': { + 'hash': 30670, + 'name': 'ore_bag_attachment_knot_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_attachment_stick_01_30698': { + 'hash': 30698, + 'name': 'ore_bag_attachment_stick_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_attachment_stick_02_30694': { + 'hash': 30694, + 'name': 'ore_bag_attachment_stick_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_attachment_stick_03_30690': { + 'hash': 30690, + 'name': 'ore_bag_attachment_stick_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_attachment_stick_04_30686': { + 'hash': 30686, + 'name': 'ore_bag_attachment_stick_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_attachment_stick_05_30658': { + 'hash': 30658, + 'name': 'ore_bag_attachment_stick_05', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'ore_bag_attachment_stick_06_30654': { + 'hash': 30654, + 'name': 'ore_bag_attachment_stick_06', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Ore_Storage': { + 'hash': 65420, + 'name': 'Ore_Storage', + 'embedded': { + 'Filter_Dock_57214': { + 'hash': 57214, + 'name': 'Filter_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Interaction_Point_59032': { + 'hash': 59032, + 'name': 'Interaction_Point', + 'savables': {} + }, + 'Internal_Dock_59328': { + 'hash': 59328, + 'name': 'Internal_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Ore_Storage_65062': { + 'hash': 65062, + 'name': 'Ore_Storage', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + }, + 'CommunalStorage': { + 'hash': 3084373371, + 'name': 'CommunalStorage' + }, + 'PlayerInteractionRestrictor': { + 'hash': 2951515968, + 'name': 'PlayerInteractionRestrictor' + } + } + }, + 'Withdraw_Dock_34750': { + 'hash': 34750, + 'name': 'Withdraw_Dock', + 'savables': {} + } + } + }, + 'Ore_Training': { + 'hash': 56300, + 'name': 'Ore_Training', + 'embedded': { + 'Ore_Training_56294': { + 'hash': 56294, + 'name': 'Ore_Training', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Outdoor_Light_Fixture': { + 'hash': 4686, + 'name': 'Outdoor_Light_Fixture', + 'embedded': { + 'Fire_53718': { + 'hash': 53718, + 'name': 'Fire', + 'savables': { + 'Fire': { + 'hash': 3457519710, + 'name': 'Fire' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Outdoor_Light_Fixture_2808': { + 'hash': 2808, + 'name': 'Outdoor_Light_Fixture', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + } + } + }, + 'Outdoor_Light_Fixture_Dim': { + 'hash': 2758, + 'name': 'Outdoor_Light_Fixture_Dim', + 'embedded': { + 'Fire_34930': { + 'hash': 34930, + 'name': 'Fire', + 'savables': {} + }, + 'Outdoor_Light_Fixture_Dim_2756': { + 'hash': 2756, + 'name': 'Outdoor_Light_Fixture_Dim', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + } + } + }, + 'Padlock_Standard': { + 'hash': 3830, + 'name': 'Padlock_Standard', + 'embedded': { + 'Padlock_Standard_8924': { + 'hash': 8924, + 'name': 'Padlock_Standard', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Page': { + 'hash': 40320, + 'name': 'Page', + 'embedded': {} + }, + 'Paper': { + 'hash': 37066, + 'name': 'Paper', + 'embedded': { + 'Paper_60604': { + 'hash': 60604, + 'name': 'Paper', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PaperPageInstance': { + 'hash': 2241532968, + 'name': 'PaperPageInstance' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Phantom': { + 'hash': 17772, + 'name': 'Phantom', + 'embedded': { + 'AI_25864': { + 'hash': 25864, + 'name': 'AI', + 'savables': {} + }, + 'Phantom_01_16416': { + 'hash': 16416, + 'name': 'Phantom_01', + 'savables': {} + }, + 'Phantom_25882': { + 'hash': 25882, + 'name': 'Phantom', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Phantom_Guard': { + 'hash': 6940, + 'name': 'Phantom_Guard', + 'embedded': { + 'Heat_Point_Collection_56294': { + 'hash': 56294, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_SwordType_Craft_39368': { + 'hash': 39368, + 'name': 'Insert_SwordType_Craft', + 'savables': {} + }, + 'Phantom_Guard_51546': { + 'hash': 51546, + 'name': 'Phantom_Guard', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_Multi_39370': { + 'hash': 39370, + 'name': 'Slot_Multi', + 'savables': {} + } + } + }, + 'Phantom_Head': { + 'hash': 43960, + 'name': 'Phantom_Head', + 'embedded': { + 'AI_25864': { + 'hash': 25864, + 'name': 'AI', + 'savables': {} + }, + 'Phantom_01_16416': { + 'hash': 16416, + 'name': 'Phantom_01', + 'savables': {} + }, + 'Phantom_Head_25882': { + 'hash': 25882, + 'name': 'Phantom_Head', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Pick_Axe': { + 'hash': 61654, + 'name': 'Pick_Axe', + 'embedded': { + 'Pick_Axe_35090': { + 'hash': 35090, + 'name': 'Pick_Axe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Pickaxe_Head': { + 'hash': 35878, + 'name': 'Pickaxe_Head', + 'embedded': { + 'Heat_Point_Collection_14016': { + 'hash': 14016, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_HammerType_End_Cap_27166': { + 'hash': 27166, + 'name': 'Insert_HammerType_End_Cap', + 'savables': {} + }, + 'Pickaxe_Head_35758': { + 'hash': 35758, + 'name': 'Pickaxe_Head', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Pickaxe_Training': { + 'hash': 29706, + 'name': 'Pickaxe_Training', + 'embedded': {} + }, + 'PickupSlidingDoor': { + 'hash': 13452, + 'name': 'PickupSlidingDoor', + 'embedded': { + 'Grip_(1)_8328': { + 'hash': 8328, + 'name': 'Grip_(1)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(2)_8460': { + 'hash': 8460, + 'name': 'Grip_(2)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(3)_8292': { + 'hash': 8292, + 'name': 'Grip_(3)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(4)_8306': { + 'hash': 8306, + 'name': 'Grip_(4)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(5)_27902': { + 'hash': 27902, + 'name': 'Grip_(5)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(6)_27924': { + 'hash': 27924, + 'name': 'Grip_(6)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(7)_27886': { + 'hash': 27886, + 'name': 'Grip_(7)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(8)_27948': { + 'hash': 27948, + 'name': 'Grip_(8)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(9)_27940': { + 'hash': 27940, + 'name': 'Grip_(9)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_8438': { + 'hash': 8438, + 'name': 'Grip', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'PickupSlidingDoor_13450': { + 'hash': 13450, + 'name': 'PickupSlidingDoor', + 'savables': { + 'MovePickup': { + 'hash': 1874870249, + 'name': 'MovePickup' + } + } + } + } + }, + 'PillarBridgeRotate': { + 'hash': 47436, + 'name': 'PillarBridgeRotate', + 'embedded': { + 'PillarBridgeRotate_10812': { + 'hash': 10812, + 'name': 'PillarBridgeRotate', + 'savables': {} + }, + 'handle_01_30518': { + 'hash': 30518, + 'name': 'handle_01', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'handle_02_30398': { + 'hash': 30398, + 'name': 'handle_02', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'handle_03_30390': { + 'hash': 30390, + 'name': 'handle_03', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'handle_04_30524': { + 'hash': 30524, + 'name': 'handle_04', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'PillarRotate': { + 'hash': 25648, + 'name': 'PillarRotate', + 'embedded': { + 'PillarRotate_10812': { + 'hash': 10812, + 'name': 'PillarRotate', + 'savables': {} + }, + 'handle_01_30158': { + 'hash': 30158, + 'name': 'handle_01', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'handle_02_30102': { + 'hash': 30102, + 'name': 'handle_02', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'handle_03_30096': { + 'hash': 30096, + 'name': 'handle_03', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Pink_Crystal_cluster_02': { + 'hash': 15424, + 'name': 'Pink_Crystal_cluster_02', + 'embedded': { + 'Pink_Crystal_cluster_02_54416': { + 'hash': 54416, + 'name': 'Pink_Crystal_cluster_02', + 'savables': {} + } + } + }, + 'PlaceItemPuzzleNoDock': { + 'hash': 12962, + 'name': 'PlaceItemPuzzleNoDock', + 'embedded': { + 'PlaceItemPuzzleNoDock_26668': { + 'hash': 26668, + 'name': 'PlaceItemPuzzleNoDock', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'PlaceItemNoDockPuzzleLogic': { + 'hash': 1176706580, + 'name': 'PlaceItemNoDockPuzzleLogic' + } + } + } + } + }, + 'PlaceItemPuzzleNoDockFire': { + 'hash': 64858, + 'name': 'PlaceItemPuzzleNoDockFire', + 'embedded': { + 'PlaceItemPuzzleNoDockFire_54686': { + 'hash': 54686, + 'name': 'PlaceItemPuzzleNoDockFire', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'PlaceItemNoDockFirePuzzleLogic': { + 'hash': 2495475500, + 'name': 'PlaceItemNoDockFirePuzzleLogic' + } + } + } + } + }, + 'Placed_Table': { + 'hash': 8520, + 'name': 'Placed_Table', + 'embedded': { + 'Placed_Table_55788': { + 'hash': 55788, + 'name': 'Placed_Table', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Spawn_Object_(1)_45908': { + 'hash': 45908, + 'name': 'Spawn_Object_(1)', + 'savables': {} + }, + 'Spawn_Object_(2)_45906': { + 'hash': 45906, + 'name': 'Spawn_Object_(2)', + 'savables': {} + }, + 'Spawn_Object_(3)_45904': { + 'hash': 45904, + 'name': 'Spawn_Object_(3)', + 'savables': {} + }, + 'Spawn_Object_(4)_45902': { + 'hash': 45902, + 'name': 'Spawn_Object_(4)', + 'savables': {} + }, + 'Spawn_Object_45900': { + 'hash': 45900, + 'name': 'Spawn_Object', + 'savables': {} + }, + 'table_leg_01_48772': { + 'hash': 48772, + 'name': 'table_leg_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'table_leg_02_48776': { + 'hash': 48776, + 'name': 'table_leg_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'table_leg_03_48784': { + 'hash': 48784, + 'name': 'table_leg_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'table_leg_04_48760': { + 'hash': 48760, + 'name': 'table_leg_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'table_main_48764': { + 'hash': 48764, + 'name': 'table_main', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'table_support_long_01_48780': { + 'hash': 48780, + 'name': 'table_support_long_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'table_support_long_02_48792': { + 'hash': 48792, + 'name': 'table_support_long_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'table_support_short_01_48788': { + 'hash': 48788, + 'name': 'table_support_short_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'table_support_short_02_48768': { + 'hash': 48768, + 'name': 'table_support_short_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Placement_Crate': { + 'hash': 36614, + 'name': 'Placement_Crate', + 'embedded': { + 'Dock_1_2780': { + 'hash': 2780, + 'name': 'Dock_1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_2_31842': { + 'hash': 31842, + 'name': 'Dock_2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_3_31266': { + 'hash': 31266, + 'name': 'Dock_3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_4_30878': { + 'hash': 30878, + 'name': 'Dock_4', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Placement_Crate_14764': { + 'hash': 14764, + 'name': 'Placement_Crate', + 'savables': { + 'GeneratedLoot': { + 'hash': 3642863935, + 'name': 'GeneratedLoot' + } + } + } + } + }, + 'PlayerInAreaLogic': { + 'hash': 11982, + 'name': 'PlayerInAreaLogic', + 'embedded': { + 'PlayerInAreaLogic_9782': { + 'hash': 9782, + 'name': 'PlayerInAreaLogic', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'PlayerDetect': { + 'hash': 403040752, + 'name': 'PlayerDetect' + } + } + } + } + }, + 'Player_Template': { + 'hash': 61646, + 'name': 'Player_Template', + 'embedded': {} + }, + 'Poison_Cloud': { + 'hash': 52444, + 'name': 'Poison_Cloud', + 'embedded': { + 'Poison_Cloud_50236': { + 'hash': 50236, + 'name': 'Poison_Cloud', + 'savables': {} + } + } + }, + 'Poison_Vent': { + 'hash': 37252, + 'name': 'Poison_Vent', + 'embedded': { + 'PoisonSpawn_15766': { + 'hash': 15766, + 'name': 'PoisonSpawn', + 'savables': { + 'PlayerDetect': { + 'hash': 403040752, + 'name': 'PlayerDetect' + } + } + }, + 'Poison_Vent_46584': { + 'hash': 46584, + 'name': 'Poison_Vent', + 'savables': {} + } + } + }, + 'Pole_Hugger_Edgy': { + 'hash': 17828, + 'name': 'Pole_Hugger_Edgy', + 'embedded': { + 'Insert_Deco_112': { + 'hash': 112, + 'name': 'Insert_Deco', + 'savables': {} + }, + 'Pole_Hugger_Edgy_15532': { + 'hash': 15532, + 'name': 'Pole_Hugger_Edgy', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Pole_Hugger_Pointy_Ends': { + 'hash': 10962, + 'name': 'Pole_Hugger_Pointy_Ends', + 'embedded': { + 'Insert_Deco_112': { + 'hash': 112, + 'name': 'Insert_Deco', + 'savables': {} + }, + 'Pole_Hugger_Pointy_Ends_15532': { + 'hash': 15532, + 'name': 'Pole_Hugger_Pointy_Ends', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Pole_Hugger_Short': { + 'hash': 4920, + 'name': 'Pole_Hugger_Short', + 'embedded': { + 'Insert_Deco_112': { + 'hash': 112, + 'name': 'Insert_Deco', + 'savables': {} + }, + 'Pole_Hugger_Short_15532': { + 'hash': 15532, + 'name': 'Pole_Hugger_Short', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Pole_Hugger_Tall': { + 'hash': 62282, + 'name': 'Pole_Hugger_Tall', + 'embedded': { + 'Insert_Deco_112': { + 'hash': 112, + 'name': 'Insert_Deco', + 'savables': {} + }, + 'Pole_Hugger_Tall_15532': { + 'hash': 15532, + 'name': 'Pole_Hugger_Tall', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Pommel': { + 'hash': 15658, + 'name': 'Pommel', + 'embedded': { + 'Heat_Point_Collection_58710': { + 'hash': 58710, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_PommelType_112': { + 'hash': 112, + 'name': 'Insert_PommelType', + 'savables': {} + }, + 'Pommel_15532': { + 'hash': 15532, + 'name': 'Pommel', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Pommel_Circle': { + 'hash': 57966, + 'name': 'Pommel_Circle', + 'embedded': { + 'Heat_Point_Collection_58958': { + 'hash': 58958, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_PommelType_112': { + 'hash': 112, + 'name': 'Insert_PommelType', + 'savables': {} + }, + 'Pommel_Circle_15532': { + 'hash': 15532, + 'name': 'Pommel_Circle', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Pommel_Cone': { + 'hash': 52360, + 'name': 'Pommel_Cone', + 'embedded': { + 'Insert_Deco_112': { + 'hash': 112, + 'name': 'Insert_Deco', + 'savables': {} + }, + 'Pommel_Cone_15532': { + 'hash': 15532, + 'name': 'Pommel_Cone', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Pommel_Diamond': { + 'hash': 42764, + 'name': 'Pommel_Diamond', + 'embedded': { + 'Heat_Point_Collection_59204': { + 'hash': 59204, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_PommelType_112': { + 'hash': 112, + 'name': 'Insert_PommelType', + 'savables': {} + }, + 'Pommel_Diamond_15532': { + 'hash': 15532, + 'name': 'Pommel_Diamond', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Pommel_Large_Square': { + 'hash': 42138, + 'name': 'Pommel_Large_Square', + 'embedded': { + 'Heat_Point_Collection_59448': { + 'hash': 59448, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_PommelType_42136': { + 'hash': 42136, + 'name': 'Insert_PommelType', + 'savables': {} + }, + 'Pommel_Large_Square_42132': { + 'hash': 42132, + 'name': 'Pommel_Large_Square', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Pommel_Squashed': { + 'hash': 1736, + 'name': 'Pommel_Squashed', + 'embedded': { + 'Insert_Deco_112': { + 'hash': 112, + 'name': 'Insert_Deco', + 'savables': {} + }, + 'Pommel_Squashed_15532': { + 'hash': 15532, + 'name': 'Pommel_Squashed', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Pond_Test': { + 'hash': 58844, + 'name': 'Pond_Test', + 'embedded': { + 'Heat_Area_15578': { + 'hash': 15578, + 'name': 'Heat_Area', + 'savables': {} + }, + 'Pond_Test_21538': { + 'hash': 21538, + 'name': 'Pond_Test', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + }, + 'LiquidContainer': { + 'hash': 4179293747, + 'name': 'LiquidContainer' + } + } + } + } + }, + 'Pond_Water': { + 'hash': 23384, + 'name': 'Pond_Water', + 'embedded': { + 'Heat_Area_46624': { + 'hash': 46624, + 'name': 'Heat_Area', + 'savables': {} + }, + 'Pond_Water_21272': { + 'hash': 21272, + 'name': 'Pond_Water', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + }, + 'LiquidContainer': { + 'hash': 4179293747, + 'name': 'LiquidContainer' + } + } + } + } + }, + 'Post_Box': { + 'hash': 9562, + 'name': 'Post_Box', + 'embedded': { + 'Handle_17172': { + 'hash': 17172, + 'name': 'Handle', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Post_Box_7104': { + 'hash': 7104, + 'name': 'Post_Box', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + } + } + }, + 'Potato_Full_Burnt': { + 'hash': 1574, + 'name': 'Potato_Full_Burnt', + 'embedded': { + 'Cooking_23418': { + 'hash': 23418, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Potato_Full_Burnt_1198': { + 'hash': 1198, + 'name': 'Potato_Full_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Potato_Full_Cooked': { + 'hash': 57840, + 'name': 'Potato_Full_Cooked', + 'embedded': { + 'Cooking_9014': { + 'hash': 9014, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Potato_Full_Cooked_57464': { + 'hash': 57464, + 'name': 'Potato_Full_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Potato_Full_Ripe': { + 'hash': 54692, + 'name': 'Potato_Full_Ripe', + 'embedded': { + 'Cooking_11142': { + 'hash': 11142, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Potato_Full_Ripe_54316': { + 'hash': 54316, + 'name': 'Potato_Full_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Potato_Full_Unripe': { + 'hash': 52146, + 'name': 'Potato_Full_Unripe', + 'embedded': { + 'Cooking_31548': { + 'hash': 31548, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Potato_Full_Unripe_51770': { + 'hash': 51770, + 'name': 'Potato_Full_Unripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Potato_Growth': { + 'hash': 49408, + 'name': 'Potato_Growth', + 'embedded': { + 'Potato_Growth_33458': { + 'hash': 33458, + 'name': 'Potato_Growth', + 'savables': { + 'GrowerComponent': { + 'hash': 3402094521, + 'name': 'GrowerComponent' + } + } + } + } + }, + 'Potato_Half_Burnt': { + 'hash': 59748, + 'name': 'Potato_Half_Burnt', + 'embedded': { + 'Cooking_23418': { + 'hash': 23418, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Cooking_32800': { + 'hash': 32800, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Potato_Half_Burnt_59372': { + 'hash': 59372, + 'name': 'Potato_Half_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Potato_Half_Cooked': { + 'hash': 50612, + 'name': 'Potato_Half_Cooked', + 'embedded': { + 'Cooking_32982': { + 'hash': 32982, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Cooking_9014': { + 'hash': 9014, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Potato_Half_Cooked_50236': { + 'hash': 50236, + 'name': 'Potato_Half_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Potato_Half_Ripe': { + 'hash': 48134, + 'name': 'Potato_Half_Ripe', + 'embedded': { + 'Cooking_11142': { + 'hash': 11142, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Cooking_33006': { + 'hash': 33006, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Potato_Half_Ripe_47758': { + 'hash': 47758, + 'name': 'Potato_Half_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Potato_Half_Unripe': { + 'hash': 45822, + 'name': 'Potato_Half_Unripe', + 'embedded': { + 'Cooking_31548': { + 'hash': 31548, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Cooking_33396': { + 'hash': 33396, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Potato_Half_Unripe_45446': { + 'hash': 45446, + 'name': 'Potato_Half_Unripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'RaycastCrafter': { + 'hash': 2815374842, + 'name': 'RaycastCrafter' + } + } + } + } + }, + 'Potato_Plant_Growth': { + 'hash': 15786, + 'name': 'Potato_Plant_Growth', + 'embedded': { + 'Potato_Plant_Growth_33458': { + 'hash': 33458, + 'name': 'Potato_Plant_Growth', + 'savables': { + 'GrowerComponent': { + 'hash': 3402094521, + 'name': 'GrowerComponent' + } + } + } + } + }, + 'Potato_Plant_Stage_1': { + 'hash': 62602, + 'name': 'Potato_Plant_Stage_1', + 'embedded': { + 'Potato_Plant_Stage_1_63514': { + 'hash': 63514, + 'name': 'Potato_Plant_Stage_1', + 'savables': {} + } + } + }, + 'Potato_Plant_Stage_2': { + 'hash': 63530, + 'name': 'Potato_Plant_Stage_2', + 'embedded': { + 'Potato_Plant_Stage_2_63514': { + 'hash': 63514, + 'name': 'Potato_Plant_Stage_2', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Potato_Plant_Stage_3': { + 'hash': 54788, + 'name': 'Potato_Plant_Stage_3', + 'embedded': { + 'Potato_Plant_Stage_3_54748': { + 'hash': 54748, + 'name': 'Potato_Plant_Stage_3', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Potato_Puree_Recipe_Burnt_Stew': { + 'hash': 57936, + 'name': 'Potato_Puree_Recipe_Burnt_Stew', + 'embedded': {} + }, + 'Potato_Puree_Recipe_Cooked_Stew': { + 'hash': 57960, + 'name': 'Potato_Puree_Recipe_Cooked_Stew', + 'embedded': {} + }, + 'Potato_Puree_Recipe_Raw_Stew': { + 'hash': 57918, + 'name': 'Potato_Puree_Recipe_Raw_Stew', + 'embedded': {} + }, + 'Potato_Sapling': { + 'hash': 50692, + 'name': 'Potato_Sapling', + 'embedded': { + 'Potato_Sapling_52858': { + 'hash': 52858, + 'name': 'Potato_Sapling', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Potatoes_29060': { + 'hash': 29060, + 'name': 'Potatoes', + 'savables': { + 'GrowerGroup': { + 'hash': 2363255897, + 'name': 'GrowerGroup' + } + } + } + } + }, + 'Potion_Hoops_Side_Tool_Attachment': { + 'hash': 31418, + 'name': 'Potion_Hoops_Side_Tool_Attachment', + 'embedded': { + 'Dock_Mid_31416': { + 'hash': 31416, + 'name': 'Dock_Mid', + 'savables': { + 'AdditionalOwnedDock': { + 'hash': 2592242915, + 'name': 'AdditionalOwnedDock' + } + } + }, + 'Dock_Side_21918': { + 'hash': 21918, + 'name': 'Dock_Side', + 'savables': { + 'AdditionalOwnedDock': { + 'hash': 2592242915, + 'name': 'AdditionalOwnedDock' + } + } + }, + 'Dock_Side_22020': { + 'hash': 22020, + 'name': 'Dock_Side', + 'savables': { + 'AdditionalOwnedDock': { + 'hash': 2592242915, + 'name': 'AdditionalOwnedDock' + } + } + }, + 'Insert_Bag_Attach_7796': { + 'hash': 7796, + 'name': 'Insert_Bag_Attach', + 'savables': {} + }, + 'Potion_Hoops_Side_Tool_Attachment_7868': { + 'hash': 7868, + 'name': 'Potion_Hoops_Side_Tool_Attachment', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Storage_53262': { + 'hash': 53262, + 'name': 'Storage', + 'savables': {} + }, + 'potionHoops_sideTool_pad_01_30876': { + 'hash': 30876, + 'name': 'potionHoops_sideTool_pad_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'potionHoops_sideTool_ringHolder_29430': { + 'hash': 29430, + 'name': 'potionHoops_sideTool_ringHolder', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'potionHoops_sideTool_ringPin_01_30888': { + 'hash': 30888, + 'name': 'potionHoops_sideTool_ringPin_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'potionHoops_sideTool_ringPin_02_30884': { + 'hash': 30884, + 'name': 'potionHoops_sideTool_ringPin_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'potionHoops_sideTool_ringPin_03_30892': { + 'hash': 30892, + 'name': 'potionHoops_sideTool_ringPin_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'potionHoops_sideTool_strap_01_30880': { + 'hash': 30880, + 'name': 'potionHoops_sideTool_strap_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Potion_Medium': { + 'hash': 23644, + 'name': 'Potion_Medium', + 'embedded': { + 'CapPickup_21290': { + 'hash': 21290, + 'name': 'CapPickup', + 'savables': { + 'CapPickup': { + 'hash': 3082855726, + 'name': 'CapPickup' + } + } + }, + 'Potion_Medium_23646': { + 'hash': 23646, + 'name': 'Potion_Medium', + 'savables': { + 'LiquidContainer': { + 'hash': 4179293747, + 'name': 'LiquidContainer' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Potion_Small': { + 'hash': 62934, + 'name': 'Potion_Small', + 'embedded': {} + }, + 'Pouch': { + 'hash': 38942, + 'name': 'Pouch', + 'embedded': { + 'Pouch_36072': { + 'hash': 36072, + 'name': 'Pouch', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Storage_36080': { + 'hash': 36080, + 'name': 'Storage', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + } + } + }, + 'Pouch_Training': { + 'hash': 57348, + 'name': 'Pouch_Training', + 'embedded': { + 'Pouch_Training_36072': { + 'hash': 36072, + 'name': 'Pouch_Training', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Storage_65008': { + 'hash': 65008, + 'name': 'Storage', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + } + } + }, + 'Poultry_Onion_Mushroom_Recipe_Burnt_Stew': { + 'hash': 57780, + 'name': 'Poultry_Onion_Mushroom_Recipe_Burnt_Stew', + 'embedded': {} + }, + 'Poultry_Onion_Mushroom_Recipe_Cooked_Stew': { + 'hash': 57762, + 'name': 'Poultry_Onion_Mushroom_Recipe_Cooked_Stew', + 'embedded': {} + }, + 'Poultry_Onion_Mushroom_Recipe_Raw_Stew': { + 'hash': 57804, + 'name': 'Poultry_Onion_Mushroom_Recipe_Raw_Stew', + 'embedded': {} + }, + 'Poultry_Potato_Recipe_Burnt_Stew': { + 'hash': 57894, + 'name': 'Poultry_Potato_Recipe_Burnt_Stew', + 'embedded': {} + }, + 'Poultry_Potato_Recipe_Cooked_Stew': { + 'hash': 57852, + 'name': 'Poultry_Potato_Recipe_Cooked_Stew', + 'embedded': {} + }, + 'Poultry_Potato_Recipe_Raw_Stew': { + 'hash': 57876, + 'name': 'Poultry_Potato_Recipe_Raw_Stew', + 'embedded': {} + }, + 'Poultry_Recipe_Burnt_Stew': { + 'hash': 10830, + 'name': 'Poultry_Recipe_Burnt_Stew', + 'embedded': {} + }, + 'Poultry_Recipe_Cooked_Stew': { + 'hash': 11448, + 'name': 'Poultry_Recipe_Cooked_Stew', + 'embedded': {} + }, + 'Poultry_Recipe_Raw_Stew': { + 'hash': 12132, + 'name': 'Poultry_Recipe_Raw_Stew', + 'embedded': {} + }, + 'Power_Strike_Counter': { + 'hash': 37516, + 'name': 'Power_Strike_Counter', + 'embedded': { + 'Power_Strike_Counter_63778': { + 'hash': 63778, + 'name': 'Power_Strike_Counter', + 'savables': {} + } + } + }, + 'Practice_Gate': { + 'hash': 64704, + 'name': 'Practice_Gate', + 'embedded': {} + }, + 'Profession_Upgrade_Shrine': { + 'hash': 32200, + 'name': 'Profession_Upgrade_Shrine', + 'embedded': { + 'Hand_Touch_46540': { + 'hash': 46540, + 'name': 'Hand_Touch', + 'savables': {} + }, + 'Landscape_Finder_33664': { + 'hash': 33664, + 'name': 'Landscape_Finder', + 'savables': { + 'Landmark': { + 'hash': 2590537994, + 'name': 'Landmark' + }, + 'LandmarkDiscoverZone': { + 'hash': 4095875831, + 'name': 'LandmarkDiscoverZone' + } + } + }, + 'Profession_Upgrade_Shrine_53594': { + 'hash': 53594, + 'name': 'Profession_Upgrade_Shrine', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + }, + 'SkillShrine': { + 'hash': 2190886200, + 'name': 'SkillShrine' + } + } + }, + 'Testing_Area_29220': { + 'hash': 29220, + 'name': 'Testing_Area', + 'savables': {} + } + } + }, + 'Prongs': { + 'hash': 40460, + 'name': 'Prongs', + 'embedded': { + 'Prongs_13190': { + 'hash': 13190, + 'name': 'Prongs', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Weapon_Dock_5626': { + 'hash': 5626, + 'name': 'Weapon_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + } + } + }, + 'Proto_Greater_Got_Bramble_Wall': { + 'hash': 34050, + 'name': 'Proto_Greater_Got_Bramble_Wall', + 'embedded': { + 'Proto_Greater_Got_Bramble_Wall_34034': { + 'hash': 34034, + 'name': 'Proto_Greater_Got_Bramble_Wall', + 'savables': {} + } + } + }, + 'Pumpkin_Growth': { + 'hash': 59922, + 'name': 'Pumpkin_Growth', + 'embedded': { + 'Pumpkin_Growth_33458': { + 'hash': 33458, + 'name': 'Pumpkin_Growth', + 'savables': { + 'GrowerComponent': { + 'hash': 3402094521, + 'name': 'GrowerComponent' + } + } + } + } + }, + 'Pumpkin_Recipe_Burnt_Stew': { + 'hash': 62678, + 'name': 'Pumpkin_Recipe_Burnt_Stew', + 'embedded': {} + }, + 'Pumpkin_Recipe_Cooked_Stew': { + 'hash': 62694, + 'name': 'Pumpkin_Recipe_Cooked_Stew', + 'embedded': {} + }, + 'Pumpkin_Recipe_Raw_Stew': { + 'hash': 62724, + 'name': 'Pumpkin_Recipe_Raw_Stew', + 'embedded': {} + }, + 'Pumpkin_Tree': { + 'hash': 49086, + 'name': 'Pumpkin_Tree', + 'embedded': { + 'Pumpkin_Tree_46510': { + 'hash': 46510, + 'name': 'Pumpkin_Tree', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Pumpkin_Tree_Growth': { + 'hash': 41658, + 'name': 'Pumpkin_Tree_Growth', + 'embedded': { + 'Pumpkin_Tree_Growth_33458': { + 'hash': 33458, + 'name': 'Pumpkin_Tree_Growth', + 'savables': { + 'GrowerComponent': { + 'hash': 3402094521, + 'name': 'GrowerComponent' + } + } + } + } + }, + 'Pumpkin_Tree_Separated': { + 'hash': 23566, + 'name': 'Pumpkin_Tree_Separated', + 'embedded': {} + }, + 'Pumpkin_Tree_Stage_1': { + 'hash': 38672, + 'name': 'Pumpkin_Tree_Stage_1', + 'embedded': { + 'Pumpkin_Tree_Stage_1_63514': { + 'hash': 63514, + 'name': 'Pumpkin_Tree_Stage_1', + 'savables': {} + } + } + }, + 'Pumpkin_Tree_Stage_2': { + 'hash': 42508, + 'name': 'Pumpkin_Tree_Stage_2', + 'embedded': { + 'Pumpkin_Tree_Stage_2_46510': { + 'hash': 46510, + 'name': 'Pumpkin_Tree_Stage_2', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Pumpkin_Tree_Stage_3': { + 'hash': 63038, + 'name': 'Pumpkin_Tree_Stage_3', + 'embedded': { + 'Pumpkin_Tree_Stage_3_46510': { + 'hash': 46510, + 'name': 'Pumpkin_Tree_Stage_3', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Puzzle_Orb_1': { + 'hash': 31620, + 'name': 'Puzzle_Orb_1', + 'embedded': { + 'Puzzle_Orb_1_11514': { + 'hash': 11514, + 'name': 'Puzzle_Orb_1', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Puzzle_Orb_2': { + 'hash': 47150, + 'name': 'Puzzle_Orb_2', + 'embedded': { + 'Puzzle_Orb_2_11514': { + 'hash': 11514, + 'name': 'Puzzle_Orb_2', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Puzzle_Orb_Restrictor': { + 'hash': 29276, + 'name': 'Puzzle_Orb_Restrictor', + 'embedded': { + 'Puzzle_Orb_Restrictor_29424': { + 'hash': 29424, + 'name': 'Puzzle_Orb_Restrictor', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'PositionRestrictor': { + 'hash': 1776498660, + 'name': 'PositionRestrictor' + } + } + } + } + }, + 'Puzzle_Pillar_with_Wheel_Bridge': { + 'hash': 15908, + 'name': 'Puzzle_Pillar_with_Wheel_Bridge', + 'embedded': { + 'Elevator_20982': { + 'hash': 20982, + 'name': 'Elevator', + 'savables': { + 'WayPointPath': { + 'hash': 1063725326, + 'name': 'WayPointPath' + } + } + }, + 'Grip_(1)_54050': { + 'hash': 54050, + 'name': 'Grip_(1)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(2)_54614': { + 'hash': 54614, + 'name': 'Grip_(2)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(3)_56370': { + 'hash': 56370, + 'name': 'Grip_(3)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(4)_53470': { + 'hash': 53470, + 'name': 'Grip_(4)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(5)_19654': { + 'hash': 19654, + 'name': 'Grip_(5)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_56728': { + 'hash': 56728, + 'name': 'Grip', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Puzzle_Pillar_with_Wheel_Bridge_31136': { + 'hash': 31136, + 'name': 'Puzzle_Pillar_with_Wheel_Bridge', + 'savables': { + 'LogicFloatReceiver': { + 'hash': 3188272159, + 'name': 'LogicFloatReceiver' + } + } + }, + 'WheelBridge(Clone)_43884': { + 'hash': 43884, + 'name': 'WheelBridge(Clone)', + 'savables': { + 'LogicFloatReceiver': { + 'hash': 3188272159, + 'name': 'LogicFloatReceiver' + }, + 'LogicFloatSender': { + 'hash': 2120963769, + 'name': 'LogicFloatSender' + }, + 'RotatePickup': { + 'hash': 2498617949, + 'name': 'RotatePickup' + } + } + }, + 'wheel_origin_43868': { + 'hash': 43868, + 'name': 'wheel_origin', + 'savables': { + 'WheelGrab': { + 'hash': 320224849, + 'name': 'WheelGrab' + } + } + } + } + }, + 'Quest_Board': { + 'hash': 57298, + 'name': 'Quest_Board', + 'embedded': { + 'Quest_Board_57352': { + 'hash': 57352, + 'name': 'Quest_Board', + 'savables': {} + } + } + }, + 'Quiver': { + 'hash': 64640, + 'name': 'Quiver', + 'embedded': { + 'Dock_33558': { + 'hash': 33558, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Quiver_33568': { + 'hash': 33568, + 'name': 'Quiver', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'standard_quiver_body_49088': { + 'hash': 49088, + 'name': 'standard_quiver_body', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_quiver_body_laces_01_43824': { + 'hash': 43824, + 'name': 'standard_quiver_body_laces_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_quiver_body_lipBlock_49092': { + 'hash': 49092, + 'name': 'standard_quiver_body_lipBlock', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_quiver_metalRingBottom_49080': { + 'hash': 49080, + 'name': 'standard_quiver_metalRingBottom', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_quiver_metalRingTop_49084': { + 'hash': 49084, + 'name': 'standard_quiver_metalRingTop', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_quiver_strap_49068': { + 'hash': 49068, + 'name': 'standard_quiver_strap', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_quiver_strap_clasp_01_49072': { + 'hash': 49072, + 'name': 'standard_quiver_strap_clasp_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_quiver_strap_clasp_02_49076': { + 'hash': 49076, + 'name': 'standard_quiver_strap_clasp_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_quiver_strap_wraps_43820': { + 'hash': 43820, + 'name': 'standard_quiver_strap_wraps', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Random_Placement_Crate': { + 'hash': 8246, + 'name': 'Random_Placement_Crate', + 'embedded': { + 'Crate_place(Clone)_14764': { + 'hash': 14764, + 'name': 'Crate_place(Clone)', + 'savables': { + 'GeneratedLoot': { + 'hash': 3642863935, + 'name': 'GeneratedLoot' + } + } + }, + 'Dock_1_2780': { + 'hash': 2780, + 'name': 'Dock_1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_2_31842': { + 'hash': 31842, + 'name': 'Dock_2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_3_31266': { + 'hash': 31266, + 'name': 'Dock_3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_4_30878': { + 'hash': 30878, + 'name': 'Dock_4', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Random_Placement_Crate_14764': { + 'hash': 14764, + 'name': 'Random_Placement_Crate', + 'savables': {} + } + } + }, + 'Random_Spawn_Rectangle': { + 'hash': 24644, + 'name': 'Random_Spawn_Rectangle', + 'embedded': {} + }, + 'Rapier_Blade': { + 'hash': 11332, + 'name': 'Rapier_Blade', + 'embedded': { + 'Heat_Point_Collection_63016': { + 'hash': 63016, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_Straight_SwordType_7796': { + 'hash': 7796, + 'name': 'Insert_Straight_SwordType', + 'savables': {} + }, + 'Rapier_Blade_35392': { + 'hash': 35392, + 'name': 'Rapier_Blade', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'metal_blade_rapier_full_geo_LOD0_6834': { + 'hash': 6834, + 'name': 'metal_blade_rapier_full_geo_LOD0', + 'savables': {} + } + } + }, + 'Recycler': { + 'hash': 60684, + 'name': 'Recycler', + 'embedded': { + 'Display_Dock_6940': { + 'hash': 6940, + 'name': 'Display_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Display_Dock_6988': { + 'hash': 6988, + 'name': 'Display_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Display_Dock_6992': { + 'hash': 6992, + 'name': 'Display_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_Fuel_54958': { + 'hash': 54958, + 'name': 'Dock_Fuel', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_Output_44868': { + 'hash': 44868, + 'name': 'Dock_Output', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_Output_58172': { + 'hash': 58172, + 'name': 'Dock_Output', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_Output_61316': { + 'hash': 61316, + 'name': 'Dock_Output', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Handle_24422': { + 'hash': 24422, + 'name': 'Handle', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Handle_6394': { + 'hash': 6394, + 'name': 'Handle', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'HeatArea_37766': { + 'hash': 37766, + 'name': 'HeatArea', + 'savables': {} + }, + 'Recycler_57752': { + 'hash': 57752, + 'name': 'Recycler', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + }, + 'Recycler': { + 'hash': 2450553269, + 'name': 'Recycler' + } + } + }, + 'recycler_fuelHatch_37522': { + 'hash': 37522, + 'name': 'recycler_fuelHatch', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'smelter_bellows_arm_jnt_25672': { + 'hash': 25672, + 'name': 'smelter_bellows_arm_jnt', + 'savables': {} + } + } + }, + 'Red_Iron_Ingot': { + 'hash': 31034, + 'name': 'Red_Iron_Ingot', + 'embedded': { + 'Heat_Point_Collection_13552': { + 'hash': 13552, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Red_Iron_Ingot_32738': { + 'hash': 32738, + 'name': 'Red_Iron_Ingot', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Red_Mushroom_Recipe_Burnt_Stew': { + 'hash': 63290, + 'name': 'Red_Mushroom_Recipe_Burnt_Stew', + 'embedded': {} + }, + 'Red_Mushroom_Recipe_Cooked_Stew': { + 'hash': 62660, + 'name': 'Red_Mushroom_Recipe_Cooked_Stew', + 'embedded': {} + }, + 'Red_Mushroom_Recipe_Raw_Stew': { + 'hash': 62024, + 'name': 'Red_Mushroom_Recipe_Raw_Stew', + 'embedded': {} + }, + 'Red_Mushroom_Shield': { + 'hash': 49188, + 'name': 'Red_Mushroom_Shield', + 'embedded': { + 'Red_Mushroom_Shield_49190': { + 'hash': 49190, + 'name': 'Red_Mushroom_Shield', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Red_Sauce_Recipe_Burnt_Stew': { + 'hash': 57978, + 'name': 'Red_Sauce_Recipe_Burnt_Stew', + 'embedded': {} + }, + 'Red_Sauce_Recipe_Cooked_Stew': { + 'hash': 58026, + 'name': 'Red_Sauce_Recipe_Cooked_Stew', + 'embedded': {} + }, + 'Red_Sauce_Recipe_Raw_Stew': { + 'hash': 58002, + 'name': 'Red_Sauce_Recipe_Raw_Stew', + 'embedded': {} + }, + 'Redwood_Gotera_Core': { + 'hash': 41402, + 'name': 'Redwood_Gotera_Core', + 'embedded': { + 'Redwood_Gotera_Core_41418': { + 'hash': 41418, + 'name': 'Redwood_Gotera_Core', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Redwood_Tree_Growth': { + 'hash': 48248, + 'name': 'Redwood_Tree_Growth', + 'embedded': { + 'Redwood_Tree_Growth_33458': { + 'hash': 33458, + 'name': 'Redwood_Tree_Growth', + 'savables': { + 'GrowerComponent': { + 'hash': 3402094521, + 'name': 'GrowerComponent' + } + } + } + } + }, + 'Redwood_Tree_Seed': { + 'hash': 55054, + 'name': 'Redwood_Tree_Seed', + 'embedded': { + 'Redwood_Tree_Seed_35258': { + 'hash': 35258, + 'name': 'Redwood_Tree_Seed', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'RaycastCrafter': { + 'hash': 2815374842, + 'name': 'RaycastCrafter' + } + } + } + } + }, + 'Redwood_Tree_Stage_1': { + 'hash': 17526, + 'name': 'Redwood_Tree_Stage_1', + 'embedded': { + 'Redwood_Tree_Stage_1_63514': { + 'hash': 63514, + 'name': 'Redwood_Tree_Stage_1', + 'savables': {} + } + } + }, + 'Repair_Box': { + 'hash': 3458, + 'name': 'Repair_Box', + 'embedded': { + 'Cost_1_22852': { + 'hash': 22852, + 'name': 'Cost_1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Cost_2_22786': { + 'hash': 22786, + 'name': 'Cost_2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Cost_3_22772': { + 'hash': 22772, + 'name': 'Cost_3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_1_22642': { + 'hash': 22642, + 'name': 'Dock_1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_2_22692': { + 'hash': 22692, + 'name': 'Dock_2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_3_22698': { + 'hash': 22698, + 'name': 'Dock_3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Landmark_Finder_5660': { + 'hash': 5660, + 'name': 'Landmark_Finder', + 'savables': { + 'Landmark': { + 'hash': 2590537994, + 'name': 'Landmark' + }, + 'LandmarkDiscoverZone': { + 'hash': 4095875831, + 'name': 'LandmarkDiscoverZone' + } + } + }, + 'Quest_Marker_-_Repair_Box_51948': { + 'hash': 51948, + 'name': 'Quest_Marker_-_Repair_Box', + 'savables': { + 'ManualCondition': { + 'hash': 1268269765, + 'name': 'ManualCondition' + }, + 'RepairableObjectComparisonCondition': { + 'hash': 1558189723, + 'name': 'RepairableObjectComparisonCondition' + } + } + }, + 'RepairBox_15188': { + 'hash': 15188, + 'name': 'RepairBox', + 'savables': {} + }, + 'Repair_Box_65496': { + 'hash': 65496, + 'name': 'Repair_Box', + 'savables': { + 'RepairBox': { + 'hash': 3820454400, + 'name': 'RepairBox' + } + } + } + } + }, + 'Repair_Box_Standing_Panel': { + 'hash': 32704, + 'name': 'Repair_Box_Standing_Panel', + 'embedded': { + 'Cost_1_32664': { + 'hash': 32664, + 'name': 'Cost_1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Cost_2_32662': { + 'hash': 32662, + 'name': 'Cost_2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Cost_3_32660': { + 'hash': 32660, + 'name': 'Cost_3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_1_32654': { + 'hash': 32654, + 'name': 'Dock_1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_2_32656': { + 'hash': 32656, + 'name': 'Dock_2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_3_32658': { + 'hash': 32658, + 'name': 'Dock_3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Landmark_Finder_4224': { + 'hash': 4224, + 'name': 'Landmark_Finder', + 'savables': { + 'Landmark': { + 'hash': 2590537994, + 'name': 'Landmark' + }, + 'LandmarkDiscoverZone': { + 'hash': 4095875831, + 'name': 'LandmarkDiscoverZone' + } + } + }, + 'Quest_Marker_-_Repair_Box_51948': { + 'hash': 51948, + 'name': 'Quest_Marker_-_Repair_Box', + 'savables': { + 'ManualCondition': { + 'hash': 1268269765, + 'name': 'ManualCondition' + }, + 'RepairableObjectComparisonCondition': { + 'hash': 1558189723, + 'name': 'RepairableObjectComparisonCondition' + } + } + }, + 'RepairBox_15188': { + 'hash': 15188, + 'name': 'RepairBox', + 'savables': {} + }, + 'Repair_Box_Standing_Panel_32702': { + 'hash': 32702, + 'name': 'Repair_Box_Standing_Panel', + 'savables': { + 'RepairBox': { + 'hash': 3820454400, + 'name': 'RepairBox' + } + } + } + } + }, + 'Repair_Box_Wall_Panel': { + 'hash': 41842, + 'name': 'Repair_Box_Wall_Panel', + 'embedded': { + 'Cost_1_41802': { + 'hash': 41802, + 'name': 'Cost_1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Cost_2_41800': { + 'hash': 41800, + 'name': 'Cost_2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Cost_3_41798': { + 'hash': 41798, + 'name': 'Cost_3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_1_41792': { + 'hash': 41792, + 'name': 'Dock_1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_2_41794': { + 'hash': 41794, + 'name': 'Dock_2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_3_41796': { + 'hash': 41796, + 'name': 'Dock_3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Landmark_Finder_3504': { + 'hash': 3504, + 'name': 'Landmark_Finder', + 'savables': { + 'Landmark': { + 'hash': 2590537994, + 'name': 'Landmark' + }, + 'LandmarkDiscoverZone': { + 'hash': 4095875831, + 'name': 'LandmarkDiscoverZone' + } + } + }, + 'Quest_Marker_-_Repair_Box_51948': { + 'hash': 51948, + 'name': 'Quest_Marker_-_Repair_Box', + 'savables': { + 'ManualCondition': { + 'hash': 1268269765, + 'name': 'ManualCondition' + }, + 'RepairableObjectComparisonCondition': { + 'hash': 1558189723, + 'name': 'RepairableObjectComparisonCondition' + } + } + }, + 'RepairBox_15188': { + 'hash': 15188, + 'name': 'RepairBox', + 'savables': {} + }, + 'Repair_Box_Wall_Panel_41840': { + 'hash': 41840, + 'name': 'Repair_Box_Wall_Panel', + 'savables': { + 'RepairBox': { + 'hash': 3820454400, + 'name': 'RepairBox' + } + } + } + } + }, + 'Repeater': { + 'hash': 40046, + 'name': 'Repeater', + 'embedded': {} + }, + 'Rock_Boulder_01': { + 'hash': 63838, + 'name': 'Rock_Boulder_01', + 'embedded': {} + }, + 'Rock_Boulder_02': { + 'hash': 63828, + 'name': 'Rock_Boulder_02', + 'embedded': {} + }, + 'Rock_Boulder_03': { + 'hash': 63836, + 'name': 'Rock_Boulder_03', + 'embedded': {} + }, + 'Rock_Boulder_04': { + 'hash': 63834, + 'name': 'Rock_Boulder_04', + 'embedded': {} + }, + 'Rock_Cluster': { + 'hash': 63824, + 'name': 'Rock_Cluster', + 'embedded': { + 'Rock_Cluster_18314': { + 'hash': 18314, + 'name': 'Rock_Cluster', + 'savables': {} + } + } + }, + 'Rock_Cluster_Tutorial': { + 'hash': 25922, + 'name': 'Rock_Cluster_Tutorial', + 'embedded': { + 'Rock_Cluster_Tutorial_18314': { + 'hash': 18314, + 'name': 'Rock_Cluster_Tutorial', + 'savables': {} + } + } + }, + 'Rock_Spire_Gcore_Dynamic': { + 'hash': 40128, + 'name': 'Rock_Spire_Gcore_Dynamic', + 'embedded': { + 'Death_Fern_Spawner_32170': { + 'hash': 32170, + 'name': 'Death_Fern_Spawner', + 'savables': { + 'CylindricalBoundsSurface': { + 'hash': 34507654, + 'name': 'CylindricalBoundsSurface' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + }, + 'Health_Vine_Spawner_39788': { + 'hash': 39788, + 'name': 'Health_Vine_Spawner', + 'savables': { + 'DirectionalBoundsSurface': { + 'hash': 1962842866, + 'name': 'DirectionalBoundsSurface' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + }, + 'Rock_Spire_Gcore_Dynamic_23456': { + 'hash': 23456, + 'name': 'Rock_Spire_Gcore_Dynamic', + 'savables': {} + }, + 'Vine_Boulder_Spawner_53936': { + 'hash': 53936, + 'name': 'Vine_Boulder_Spawner', + 'savables': { + 'CylindricalBoundsSurface': { + 'hash': 34507654, + 'name': 'CylindricalBoundsSurface' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + } + } + }, + 'Rock_WallBoulder_02': { + 'hash': 63832, + 'name': 'Rock_WallBoulder_02', + 'embedded': {} + }, + 'Rod_Long': { + 'hash': 44066, + 'name': 'Rod_Long', + 'embedded': { + 'Dock_32818': { + 'hash': 32818, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Rod_Long_24200': { + 'hash': 24200, + 'name': 'Rod_Long', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_AxeType_37426': { + 'hash': 37426, + 'name': 'Slot_AxeType', + 'savables': {} + }, + 'Slot_EdgeType_Craft_31944': { + 'hash': 31944, + 'name': 'Slot_EdgeType_Craft', + 'savables': {} + }, + 'Slot_Multi_53940': { + 'hash': 53940, + 'name': 'Slot_Multi', + 'savables': {} + } + } + }, + 'Rod_Medium': { + 'hash': 44204, + 'name': 'Rod_Medium', + 'embedded': { + 'Dock_32818': { + 'hash': 32818, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Rod_Medium_44084': { + 'hash': 44084, + 'name': 'Rod_Medium', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_AxeType_15522': { + 'hash': 15522, + 'name': 'Slot_AxeType', + 'savables': {} + }, + 'Slot_Deco_37438': { + 'hash': 37438, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_EdgeType_Craft_35298': { + 'hash': 35298, + 'name': 'Slot_EdgeType_Craft', + 'savables': {} + }, + 'Slot_Multi_31156': { + 'hash': 31156, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_Multi_39008': { + 'hash': 39008, + 'name': 'Slot_Multi', + 'savables': {} + } + } + }, + 'Rod_Slim_40cm': { + 'hash': 59588, + 'name': 'Rod_Slim_40cm', + 'embedded': { + 'Rod_Slim_40cm_37330': { + 'hash': 37330, + 'name': 'Rod_Slim_40cm', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Slot_Multi_44690': { + 'hash': 44690, + 'name': 'Slot_Multi', + 'savables': {} + } + } + }, + 'Rope_Clump': { + 'hash': 43836, + 'name': 'Rope_Clump', + 'embedded': { + 'Rope_Clump_47776': { + 'hash': 47776, + 'name': 'Rope_Clump', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Rope_Pully_Puzzle': { + 'hash': 51434, + 'name': 'Rope_Pully_Puzzle', + 'embedded': { + 'Rope_Grab_57800': { + 'hash': 57800, + 'name': 'Rope_Grab', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'RopeGrab': { + 'hash': 237360636, + 'name': 'RopeGrab' + } + } + }, + 'Rope_Length_57794': { + 'hash': 57794, + 'name': 'Rope_Length', + 'savables': {} + }, + 'Rope_Pully_Puzzle_4580': { + 'hash': 4580, + 'name': 'Rope_Pully_Puzzle', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'LogicFloatReceiver': { + 'hash': 3188272159, + 'name': 'LogicFloatReceiver' + }, + 'LogicFloatSender': { + 'hash': 2120963769, + 'name': 'LogicFloatSender' + } + } + } + } + }, + 'Ruins_Elevator_Puzzle_Square': { + 'hash': 27582, + 'name': 'Ruins_Elevator_Puzzle_Square', + 'embedded': { + 'Ruins_Elevator_Puzzle_Square_31136': { + 'hash': 31136, + 'name': 'Ruins_Elevator_Puzzle_Square', + 'savables': {} + } + } + }, + 'Ruins_Elevator_Puzzle_Square_Crystal_Pillar': { + 'hash': 3512, + 'name': 'Ruins_Elevator_Puzzle_Square_Crystal_Pillar', + 'embedded': { + 'Crystal_Blue(Clone)_(1)_40232': { + 'hash': 40232, + 'name': 'Crystal_Blue(Clone)_(1)', + 'savables': {} + }, + 'Elevator_20982': { + 'hash': 20982, + 'name': 'Elevator', + 'savables': { + 'WayPointPath': { + 'hash': 1063725326, + 'name': 'WayPointPath' + } + } + }, + 'Ruins_Elevator_Puzzle_Square_Crystal_Pillar_31136': { + 'hash': 31136, + 'name': 'Ruins_Elevator_Puzzle_Square_Crystal_Pillar', + 'savables': { + 'LogicFloatReceiver': { + 'hash': 3188272159, + 'name': 'LogicFloatReceiver' + } + } + } + } + }, + 'Ruins_Elevator_Puzzle_Square_Large_Variant': { + 'hash': 4192, + 'name': 'Ruins_Elevator_Puzzle_Square_Large_Variant', + 'embedded': { + 'Ruins_Elevator_Puzzle_Square_Large_Variant_16752': { + 'hash': 16752, + 'name': 'Ruins_Elevator_Puzzle_Square_Large_Variant', + 'savables': {} + } + } + }, + 'Ruins_Elevator_Puzzle_Square_Pillar_Variant': { + 'hash': 22284, + 'name': 'Ruins_Elevator_Puzzle_Square_Pillar_Variant', + 'embedded': { + 'Ruins_Elevator_Puzzle_Square_Pillar_Variant_31136': { + 'hash': 31136, + 'name': 'Ruins_Elevator_Puzzle_Square_Pillar_Variant', + 'savables': {} + } + } + }, + 'Ruins_Hand_Touch_Activator': { + 'hash': 1002, + 'name': 'Ruins_Hand_Touch_Activator', + 'embedded': { + 'Ruins_Hand_Touch_Activator_46540': { + 'hash': 46540, + 'name': 'Ruins_Hand_Touch_Activator', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + } + } + } + } + }, + 'Ruins_Pillar_Crystal': { + 'hash': 58240, + 'name': 'Ruins_Pillar_Crystal', + 'embedded': { + 'Crystal_Blue(Clone)_(1)_40232': { + 'hash': 40232, + 'name': 'Crystal_Blue(Clone)_(1)', + 'savables': {} + }, + 'Ruins_Pillar_Crystal_58176': { + 'hash': 58176, + 'name': 'Ruins_Pillar_Crystal', + 'savables': {} + } + } + }, + 'Ruins_Sliding_Wall_Puzzle_Square': { + 'hash': 42494, + 'name': 'Ruins_Sliding_Wall_Puzzle_Square', + 'embedded': { + 'Ruins_Sliding_Wall_Puzzle_Square_42408': { + 'hash': 42408, + 'name': 'Ruins_Sliding_Wall_Puzzle_Square', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'SlidingDoor': { + 'hash': 3583462804, + 'name': 'SlidingDoor' + } + } + } + } + }, + 'Rusty_Axe': { + 'hash': 4412, + 'name': 'Rusty_Axe', + 'embedded': { + 'Rusty_Axe_62196': { + 'hash': 62196, + 'name': 'Rusty_Axe', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Rusty_Chisel': { + 'hash': 40366, + 'name': 'Rusty_Chisel', + 'embedded': { + 'Rusty_Chisel_40156': { + 'hash': 40156, + 'name': 'Rusty_Chisel', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Rusty_Greataxe': { + 'hash': 29296, + 'name': 'Rusty_Greataxe', + 'embedded': { + 'Rusty_Greataxe_28996': { + 'hash': 28996, + 'name': 'Rusty_Greataxe', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Rusty_Greatsword': { + 'hash': 63156, + 'name': 'Rusty_Greatsword', + 'embedded': { + 'Rusty_Greatsword_62946': { + 'hash': 62946, + 'name': 'Rusty_Greatsword', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Rusty_Hammer': { + 'hash': 36126, + 'name': 'Rusty_Hammer', + 'embedded': { + 'Rusty_Hammer_58538': { + 'hash': 58538, + 'name': 'Rusty_Hammer', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Rusty_Pickaxe': { + 'hash': 46874, + 'name': 'Rusty_Pickaxe', + 'embedded': { + 'Rusty_Pickaxe_46574': { + 'hash': 46574, + 'name': 'Rusty_Pickaxe', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Rusty_Pitchfork': { + 'hash': 59586, + 'name': 'Rusty_Pitchfork', + 'embedded': { + 'Rusty_Pitchfork_58914': { + 'hash': 58914, + 'name': 'Rusty_Pitchfork', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Rusty_Shield': { + 'hash': 20684, + 'name': 'Rusty_Shield', + 'embedded': { + 'Insert_Shield_64244': { + 'hash': 64244, + 'name': 'Insert_Shield', + 'savables': {} + }, + 'Rusty_Shield_20260': { + 'hash': 20260, + 'name': 'Rusty_Shield', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Rusty_Short_Sword': { + 'hash': 44824, + 'name': 'Rusty_Short_Sword', + 'embedded': { + 'Rusty_Short_Sword_52378': { + 'hash': 52378, + 'name': 'Rusty_Short_Sword', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Rusty_Spade': { + 'hash': 33230, + 'name': 'Rusty_Spade', + 'embedded': { + 'Fake_Pickup_6096': { + 'hash': 6096, + 'name': 'Fake_Pickup', + 'savables': {} + }, + 'Rusty_Spade_60654': { + 'hash': 60654, + 'name': 'Rusty_Spade', + 'savables': { + 'DiggingImpactor': { + 'hash': 3445325106, + 'name': 'DiggingImpactor' + }, + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Safe_Point': { + 'hash': 33004, + 'name': 'Safe_Point', + 'embedded': { + 'Hand_Touch_46540': { + 'hash': 46540, + 'name': 'Hand_Touch', + 'savables': {} + }, + 'Safe_Point_9078': { + 'hash': 9078, + 'name': 'Safe_Point', + 'savables': { + 'CheckPoint': { + 'hash': 3704379512, + 'name': 'CheckPoint' + }, + 'SafePositionSetter': { + 'hash': 70871065, + 'name': 'SafePositionSetter' + } + } + } + } + }, + 'Sai': { + 'hash': 27038, + 'name': 'Sai', + 'embedded': { + 'Sai_36330': { + 'hash': 36330, + 'name': 'Sai', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Salt': { + 'hash': 49578, + 'name': 'Salt', + 'embedded': { + 'Salt_30920': { + 'hash': 30920, + 'name': 'Salt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Sandstone_Boulder_01': { + 'hash': 34168, + 'name': 'Sandstone_Boulder_01', + 'embedded': { + 'Sandstone_Boulder_01_13178': { + 'hash': 13178, + 'name': 'Sandstone_Boulder_01', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Sandstone_Boulder_02': { + 'hash': 8006, + 'name': 'Sandstone_Boulder_02', + 'embedded': { + 'Sandstone_Boulder_02_13178': { + 'hash': 13178, + 'name': 'Sandstone_Boulder_02', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Sandstone_Boulder_03': { + 'hash': 5050, + 'name': 'Sandstone_Boulder_03', + 'embedded': { + 'Sandstone_Boulder_03_13178': { + 'hash': 13178, + 'name': 'Sandstone_Boulder_03', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Sandstone_Cluster': { + 'hash': 41676, + 'name': 'Sandstone_Cluster', + 'embedded': { + 'Sandstone_Cluster_41674': { + 'hash': 41674, + 'name': 'Sandstone_Cluster', + 'savables': {} + } + } + }, + 'Sandstone_Stone': { + 'hash': 55930, + 'name': 'Sandstone_Stone', + 'embedded': { + 'Sandstone_Stone_30920': { + 'hash': 30920, + 'name': 'Sandstone_Stone', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Sapling': { + 'hash': 25994, + 'name': 'Sapling', + 'embedded': { + 'Sapling_52900': { + 'hash': 52900, + 'name': 'Sapling', + 'savables': {} + } + } + }, + 'Sapling_Freshly_Planted': { + 'hash': 25992, + 'name': 'Sapling_Freshly_Planted', + 'embedded': { + 'Sapling_Freshly_Planted_44026': { + 'hash': 44026, + 'name': 'Sapling_Freshly_Planted', + 'savables': {} + } + } + }, + 'ScaleTemp': { + 'hash': 64402, + 'name': 'ScaleTemp', + 'embedded': {} + }, + 'Schmeechee_Glowing': { + 'hash': 53576, + 'name': 'Schmeechee_Glowing', + 'embedded': { + 'Schmeechee_53578': { + 'hash': 53578, + 'name': 'Schmeechee', + 'savables': {} + }, + 'Schmeechee_AI_58356': { + 'hash': 58356, + 'name': 'Schmeechee_AI', + 'savables': {} + }, + 'Schmeechee_Glowing_53582': { + 'hash': 53582, + 'name': 'Schmeechee_Glowing', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Schmeechee_Orange': { + 'hash': 63728, + 'name': 'Schmeechee_Orange', + 'embedded': { + 'Schmeechee_21916': { + 'hash': 21916, + 'name': 'Schmeechee', + 'savables': {} + }, + 'Schmeechee_AI_58356': { + 'hash': 58356, + 'name': 'Schmeechee_AI', + 'savables': {} + }, + 'Schmeechee_Orange_58792': { + 'hash': 58792, + 'name': 'Schmeechee_Orange', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Schmeechee_Poisonous': { + 'hash': 31646, + 'name': 'Schmeechee_Poisonous', + 'embedded': { + 'Schmeechee_31648': { + 'hash': 31648, + 'name': 'Schmeechee', + 'savables': {} + }, + 'Schmeechee_AI_58356': { + 'hash': 58356, + 'name': 'Schmeechee_AI', + 'savables': {} + }, + 'Schmeechee_Poisonous_31652': { + 'hash': 31652, + 'name': 'Schmeechee_Poisonous', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Schmeechee_Red': { + 'hash': 3532, + 'name': 'Schmeechee_Red', + 'embedded': { + 'Schmeechee_3534': { + 'hash': 3534, + 'name': 'Schmeechee', + 'savables': {} + }, + 'Schmeechee_AI_58356': { + 'hash': 58356, + 'name': 'Schmeechee_AI', + 'savables': {} + }, + 'Schmeechee_Red_3538': { + 'hash': 3538, + 'name': 'Schmeechee_Red', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Scythe_Blade': { + 'hash': 26788, + 'name': 'Scythe_Blade', + 'embedded': { + 'Insert_AxeType_7796': { + 'hash': 7796, + 'name': 'Insert_AxeType', + 'savables': {} + }, + 'Scythe_Blade_29280': { + 'hash': 29280, + 'name': 'Scythe_Blade', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'joint_blade_scythe_01_55756': { + 'hash': 55756, + 'name': 'joint_blade_scythe_01', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'joint_blade_scythe_02_55752': { + 'hash': 55752, + 'name': 'joint_blade_scythe_02', + 'savables': {} + }, + 'joint_blade_scythe_03_55776': { + 'hash': 55776, + 'name': 'joint_blade_scythe_03', + 'savables': {} + }, + 'joint_blade_scythe_04_55760': { + 'hash': 55760, + 'name': 'joint_blade_scythe_04', + 'savables': {} + }, + 'joint_blade_scythe_05_55772': { + 'hash': 55772, + 'name': 'joint_blade_scythe_05', + 'savables': {} + }, + 'joint_blade_scythe_06_55768': { + 'hash': 55768, + 'name': 'joint_blade_scythe_06', + 'savables': {} + }, + 'joint_blade_scythe_07_55764': { + 'hash': 55764, + 'name': 'joint_blade_scythe_07', + 'savables': {} + }, + 'metal_blade_scythe_full_geo_LOD0_2552': { + 'hash': 2552, + 'name': 'metal_blade_scythe_full_geo_LOD0', + 'savables': {} + } + } + }, + 'Select_Server_Orb': { + 'hash': 55760, + 'name': 'Select_Server_Orb', + 'embedded': {} + }, + 'Send_Post': { + 'hash': 53190, + 'name': 'Send_Post', + 'embedded': { + 'Grab_31026': { + 'hash': 31026, + 'name': 'Grab', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Handle_5088': { + 'hash': 5088, + 'name': 'Handle', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Scroller_Touch_Mode_41098': { + 'hash': 41098, + 'name': 'Scroller_Touch_Mode', + 'savables': {} + }, + 'Send_Post_53122': { + 'hash': 53122, + 'name': 'Send_Post', + 'savables': {} + } + } + }, + 'Set_Piece': { + 'hash': 62334, + 'name': 'Set_Piece', + 'embedded': {} + }, + 'Shelf': { + 'hash': 23630, + 'name': 'Shelf', + 'embedded': { + 'Dock_2780': { + 'hash': 2780, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60210': { + 'hash': 60210, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60212': { + 'hash': 60212, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60214': { + 'hash': 60214, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60216': { + 'hash': 60216, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60218': { + 'hash': 60218, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60220': { + 'hash': 60220, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60222': { + 'hash': 60222, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60224': { + 'hash': 60224, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60226': { + 'hash': 60226, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60228': { + 'hash': 60228, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60230': { + 'hash': 60230, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60232': { + 'hash': 60232, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60234': { + 'hash': 60234, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60236': { + 'hash': 60236, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60238': { + 'hash': 60238, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60240': { + 'hash': 60240, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60242': { + 'hash': 60242, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60244': { + 'hash': 60244, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60246': { + 'hash': 60246, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Shelf_5060': { + 'hash': 5060, + 'name': 'Shelf', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + } + } + }, + 'Shelf_Short': { + 'hash': 20452, + 'name': 'Shelf_Short', + 'embedded': { + 'Dock_2780': { + 'hash': 2780, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_58082': { + 'hash': 58082, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_58084': { + 'hash': 58084, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_58086': { + 'hash': 58086, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_58088': { + 'hash': 58088, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_58090': { + 'hash': 58090, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_58092': { + 'hash': 58092, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_58094': { + 'hash': 58094, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_58096': { + 'hash': 58096, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_58098': { + 'hash': 58098, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Shelf_Short_60158': { + 'hash': 60158, + 'name': 'Shelf_Short', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + } + } + }, + 'Shield': { + 'hash': 61656, + 'name': 'Shield', + 'embedded': { + 'Shield_32452': { + 'hash': 32452, + 'name': 'Shield', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Shield_Core_Bent_Middle': { + 'hash': 7232, + 'name': 'Shield_Core_Bent_Middle', + 'embedded': { + 'Insert_Shield_Handle_112': { + 'hash': 112, + 'name': 'Insert_Shield_Handle', + 'savables': {} + }, + 'Shield_Core_Bent_Middle_10382': { + 'hash': 10382, + 'name': 'Shield_Core_Bent_Middle', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Slot_Shield_Part_47874': { + 'hash': 47874, + 'name': 'Slot_Shield_Part', + 'savables': {} + }, + 'Slot_Shield_Part_8898': { + 'hash': 8898, + 'name': 'Slot_Shield_Part', + 'savables': {} + } + } + }, + 'Shield_Core_Circle_Middle': { + 'hash': 52756, + 'name': 'Shield_Core_Circle_Middle', + 'embedded': { + 'Insert_Shield_Handle_112': { + 'hash': 112, + 'name': 'Insert_Shield_Handle', + 'savables': {} + }, + 'Shield_Core_Circle_Middle_52754': { + 'hash': 52754, + 'name': 'Shield_Core_Circle_Middle', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Slot_Shield_Part_47874': { + 'hash': 47874, + 'name': 'Slot_Shield_Part', + 'savables': {} + }, + 'Slot_Shield_Part_8898': { + 'hash': 8898, + 'name': 'Slot_Shield_Part', + 'savables': {} + } + } + }, + 'Shield_Core_Handle': { + 'hash': 4530, + 'name': 'Shield_Core_Handle', + 'embedded': { + 'Shield_Core_Handle_4528': { + 'hash': 4528, + 'name': 'Shield_Core_Handle', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Slot_Shield_Handle_47874': { + 'hash': 47874, + 'name': 'Slot_Shield_Handle', + 'savables': {} + } + } + }, + 'Shield_Core_Holed_Middle': { + 'hash': 50602, + 'name': 'Shield_Core_Holed_Middle', + 'embedded': { + 'Insert_Shield_Handle_112': { + 'hash': 112, + 'name': 'Insert_Shield_Handle', + 'savables': {} + }, + 'Shield_Core_Holed_Middle_50604': { + 'hash': 50604, + 'name': 'Shield_Core_Holed_Middle', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Slot_Shield_Part_47874': { + 'hash': 47874, + 'name': 'Slot_Shield_Part', + 'savables': {} + }, + 'Slot_Shield_Part_8898': { + 'hash': 8898, + 'name': 'Slot_Shield_Part', + 'savables': {} + } + } + }, + 'Shield_Part_Half_Circle': { + 'hash': 50888, + 'name': 'Shield_Part_Half_Circle', + 'embedded': { + 'Insert_Shield_Part_112': { + 'hash': 112, + 'name': 'Insert_Shield_Part', + 'savables': {} + }, + 'Shield_Part_Half_Circle_50886': { + 'hash': 50886, + 'name': 'Shield_Part_Half_Circle', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Slot_Deco_25868': { + 'hash': 25868, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_25870': { + 'hash': 25870, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_51506': { + 'hash': 51506, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_51508': { + 'hash': 51508, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_52564': { + 'hash': 52564, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_52566': { + 'hash': 52566, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_53718': { + 'hash': 53718, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_53720': { + 'hash': 53720, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_55242': { + 'hash': 55242, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_55244': { + 'hash': 55244, + 'name': 'Slot_Deco', + 'savables': {} + } + } + }, + 'Shield_Part_Half_Circle_Hole': { + 'hash': 44704, + 'name': 'Shield_Part_Half_Circle_Hole', + 'embedded': { + 'Insert_Shield_Part_112': { + 'hash': 112, + 'name': 'Insert_Shield_Part', + 'savables': {} + }, + 'Shield_Part_Half_Circle_Hole_44702': { + 'hash': 44702, + 'name': 'Shield_Part_Half_Circle_Hole', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Slot_Deco_25868': { + 'hash': 25868, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_25870': { + 'hash': 25870, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_51506': { + 'hash': 51506, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_51508': { + 'hash': 51508, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_52564': { + 'hash': 52564, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_52566': { + 'hash': 52566, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_55242': { + 'hash': 55242, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_55244': { + 'hash': 55244, + 'name': 'Slot_Deco', + 'savables': {} + } + } + }, + 'Shield_Part_Half_Hole': { + 'hash': 12416, + 'name': 'Shield_Part_Half_Hole', + 'embedded': { + 'Insert_Shield_Part_112': { + 'hash': 112, + 'name': 'Insert_Shield_Part', + 'savables': {} + }, + 'Shield_Part_Half_Hole_12414': { + 'hash': 12414, + 'name': 'Shield_Part_Half_Hole', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Slot_Deco_20018': { + 'hash': 20018, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_46580': { + 'hash': 46580, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_52138': { + 'hash': 52138, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_56752': { + 'hash': 56752, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_63256': { + 'hash': 63256, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_854': { + 'hash': 854, + 'name': 'Slot_Deco', + 'savables': {} + } + } + }, + 'Shield_Part_Half_Point_01': { + 'hash': 59936, + 'name': 'Shield_Part_Half_Point_01', + 'embedded': { + 'Insert_Shield_Part_112': { + 'hash': 112, + 'name': 'Insert_Shield_Part', + 'savables': {} + }, + 'Shield_Part_Half_Point_01_56662': { + 'hash': 56662, + 'name': 'Shield_Part_Half_Point_01', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Slot_Deco_20420': { + 'hash': 20420, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_26340': { + 'hash': 26340, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_26366': { + 'hash': 26366, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_26368': { + 'hash': 26368, + 'name': 'Slot_Deco', + 'savables': {} + }, + 'Slot_Deco_26396': { + 'hash': 26396, + 'name': 'Slot_Deco', + 'savables': {} + } + } + }, + 'Short_Sword': { + 'hash': 38566, + 'name': 'Short_Sword', + 'embedded': { + 'Short_Sword_36330': { + 'hash': 36330, + 'name': 'Short_Sword', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Short_Sword_Blade': { + 'hash': 55310, + 'name': 'Short_Sword_Blade', + 'embedded': { + 'Heat_Point_Collection_63534': { + 'hash': 63534, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_Straight_SwordType_7796': { + 'hash': 7796, + 'name': 'Insert_Straight_SwordType', + 'savables': {} + }, + 'Short_Sword_Blade_36330': { + 'hash': 36330, + 'name': 'Short_Sword_Blade', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'metal_blade_shortSword_full_geo_LOD0_4044': { + 'hash': 4044, + 'name': 'metal_blade_shortSword_full_geo_LOD0', + 'savables': {} + } + } + }, + 'Short_Sword_Training': { + 'hash': 1150, + 'name': 'Short_Sword_Training', + 'embedded': { + 'Short_Sword_Training_1152': { + 'hash': 1152, + 'name': 'Short_Sword_Training', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Shotel_Blade': { + 'hash': 36438, + 'name': 'Shotel_Blade', + 'embedded': { + 'Heat_Point_Collection_2136': { + 'hash': 2136, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_SwordType_7796': { + 'hash': 7796, + 'name': 'Insert_SwordType', + 'savables': {} + }, + 'Shotel_Blade_36346': { + 'hash': 36346, + 'name': 'Shotel_Blade', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'metal_blade_shotel_full_geo_LOD0_22394': { + 'hash': 22394, + 'name': 'metal_blade_shotel_full_geo_LOD0', + 'savables': {} + } + } + }, + 'Silver_Boulder': { + 'hash': 9144, + 'name': 'Silver_Boulder', + 'embedded': { + 'Silver_Boulder_11186': { + 'hash': 11186, + 'name': 'Silver_Boulder', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Spawn_Origin_50402': { + 'hash': 50402, + 'name': 'Spawn_Origin', + 'savables': {} + } + } + }, + 'Silver_Boulder_Parts': { + 'hash': 17120, + 'name': 'Silver_Boulder_Parts', + 'embedded': { + 'Silver_Boulder_Parts_56732': { + 'hash': 56732, + 'name': 'Silver_Boulder_Parts', + 'savables': {} + }, + 'Silver_Boulder_part_01_56744': { + 'hash': 56744, + 'name': 'Silver_Boulder_part_01', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Silver_Boulder_part_02_56752': { + 'hash': 56752, + 'name': 'Silver_Boulder_part_02', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Silver_Boulder_part_03_56748': { + 'hash': 56748, + 'name': 'Silver_Boulder_part_03', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Silver_Ingot': { + 'hash': 23528, + 'name': 'Silver_Ingot', + 'embedded': { + 'Heat_Point_Collection_13678': { + 'hash': 13678, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Silver_Ingot_23416': { + 'hash': 23416, + 'name': 'Silver_Ingot', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Silver_Ore': { + 'hash': 9586, + 'name': 'Silver_Ore', + 'embedded': { + 'Silver_Ore_28602': { + 'hash': 28602, + 'name': 'Silver_Ore', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Skill_Orb': { + 'hash': 17270, + 'name': 'Skill_Orb', + 'embedded': { + 'Skill_Orb_35828': { + 'hash': 35828, + 'name': 'Skill_Orb', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Skill_Orb_Replacer': { + 'hash': 23526, + 'name': 'Skill_Orb_Replacer', + 'embedded': { + 'Skill_Orb_Replacer_35828': { + 'hash': 35828, + 'name': 'Skill_Orb_Replacer', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'SlidingBlockTestLayoutINCOMPLETE': { + 'hash': 8280, + 'name': 'SlidingBlockTestLayoutINCOMPLETE', + 'embedded': {} + }, + 'Sliding_Door': { + 'hash': 33420, + 'name': 'Sliding_Door', + 'embedded': {} + }, + 'Slingshot': { + 'hash': 13142, + 'name': 'Slingshot', + 'embedded': { + 'Projectile_Dock_40686': { + 'hash': 40686, + 'name': 'Projectile_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Slingshot_15402': { + 'hash': 15402, + 'name': 'Slingshot', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'String_40688': { + 'hash': 40688, + 'name': 'String', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Slow_Grass': { + 'hash': 59062, + 'name': 'Slow_Grass', + 'embedded': { + 'Slow_Grass_7970': { + 'hash': 7970, + 'name': 'Slow_Grass', + 'savables': {} + } + } + }, + 'Small_Bone_Spike': { + 'hash': 61488, + 'name': 'Small_Bone_Spike', + 'embedded': { + 'Insert_Deco_112': { + 'hash': 112, + 'name': 'Insert_Deco', + 'savables': {} + }, + 'Small_Bone_Spike_15532': { + 'hash': 15532, + 'name': 'Small_Bone_Spike', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Small_Cave_Mushroom_01': { + 'hash': 33796, + 'name': 'Small_Cave_Mushroom_01', + 'embedded': { + 'Small_Cave_Mushroom_01_33544': { + 'hash': 33544, + 'name': 'Small_Cave_Mushroom_01', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Spawner_3488': { + 'hash': 3488, + 'name': 'Spawner', + 'savables': {} + }, + 'cave_mushroom_small_spineTop_jnt_38718': { + 'hash': 38718, + 'name': 'cave_mushroom_small_spineTop_jnt', + 'savables': {} + }, + 'cave_mushroom_small_spine_jnt_46098': { + 'hash': 46098, + 'name': 'cave_mushroom_small_spine_jnt', + 'savables': {} + } + } + }, + 'Small_Cave_Mushroom_Cluster': { + 'hash': 56444, + 'name': 'Small_Cave_Mushroom_Cluster', + 'embedded': { + 'Small_Cave_Mushroom_Cluster_61380': { + 'hash': 61380, + 'name': 'Small_Cave_Mushroom_Cluster', + 'savables': {} + } + } + }, + 'Small_Shield': { + 'hash': 63498, + 'name': 'Small_Shield', + 'embedded': { + 'Insert_Shield_64244': { + 'hash': 64244, + 'name': 'Insert_Shield', + 'savables': {} + }, + 'Small_Shield_32452': { + 'hash': 32452, + 'name': 'Small_Shield', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Small_Shield_Training': { + 'hash': 21312, + 'name': 'Small_Shield_Training', + 'embedded': { + 'Small_Shield_Training_21302': { + 'hash': 21302, + 'name': 'Small_Shield_Training', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Smelter': { + 'hash': 44646, + 'name': 'Smelter', + 'embedded': { + 'Dock_37092': { + 'hash': 37092, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_37150': { + 'hash': 37150, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_37236': { + 'hash': 37236, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_Fuel_54958': { + 'hash': 54958, + 'name': 'Dock_Fuel', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_Ore_(B)_42990': { + 'hash': 42990, + 'name': 'Dock_Ore_(B)', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_Ore_(T)_54962': { + 'hash': 54962, + 'name': 'Dock_Ore_(T)', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_Ore_Dispenser_L_54940': { + 'hash': 54940, + 'name': 'Dock_Ore_Dispenser_L', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_Ore_Dispenser_M_54938': { + 'hash': 54938, + 'name': 'Dock_Ore_Dispenser_M', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_Ore_Dispenser_R_54936': { + 'hash': 54936, + 'name': 'Dock_Ore_Dispenser_R', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_Output_54928': { + 'hash': 54928, + 'name': 'Dock_Output', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_Output_54930': { + 'hash': 54930, + 'name': 'Dock_Output', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Fire_54948': { + 'hash': 54948, + 'name': 'Fire', + 'savables': { + 'Fire': { + 'hash': 3457519710, + 'name': 'Fire' + } + } + }, + 'Handle_24422': { + 'hash': 24422, + 'name': 'Handle', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Handle_38408': { + 'hash': 38408, + 'name': 'Handle', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Handle_5088': { + 'hash': 5088, + 'name': 'Handle', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Mould_Dock_54960': { + 'hash': 54960, + 'name': 'Mould_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Smelter_19322': { + 'hash': 19322, + 'name': 'Smelter', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + }, + 'Smelter': { + 'hash': 902024186, + 'name': 'Smelter' + } + } + }, + 'UnlockDocks_10172': { + 'hash': 10172, + 'name': 'UnlockDocks', + 'savables': { + 'PositionRestrictor': { + 'hash': 1776498660, + 'name': 'PositionRestrictor' + } + } + }, + 'smelter_bellows_arm_jnt_25672': { + 'hash': 25672, + 'name': 'smelter_bellows_arm_jnt', + 'savables': {} + }, + 'smelter_dispenser_lever_Handle_5912': { + 'hash': 5912, + 'name': 'smelter_dispenser_lever_Handle', + 'savables': { + 'Lever': { + 'hash': 1594932294, + 'name': 'Lever' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'smelter_fuelGate_handle_59832': { + 'hash': 59832, + 'name': 'smelter_fuelGate_handle', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'smelter_fuelGate_pivot_10060': { + 'hash': 10060, + 'name': 'smelter_fuelGate_pivot', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Smelter_Gem_1': { + 'hash': 34986, + 'name': 'Smelter_Gem_1', + 'embedded': { + 'Smelter_Gem_1_11514': { + 'hash': 11514, + 'name': 'Smelter_Gem_1', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Smelter_Gem_2': { + 'hash': 41638, + 'name': 'Smelter_Gem_2', + 'embedded': { + 'Smelter_Gem_2_11514': { + 'hash': 11514, + 'name': 'Smelter_Gem_2', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Smelter_Gem_3': { + 'hash': 46508, + 'name': 'Smelter_Gem_3', + 'embedded': { + 'Smelter_Gem_3_11514': { + 'hash': 11514, + 'name': 'Smelter_Gem_3', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Smelter_gem_2_item_pedestal': { + 'hash': 56098, + 'name': 'Smelter_gem_2_item_pedestal', + 'embedded': { + 'Pedestal_Dock_27002': { + 'hash': 27002, + 'name': 'Pedestal_Dock', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'PickupDockPedestalSpawn': { + 'hash': 2592242915, + 'name': 'PickupDockPedestalSpawn' + } + } + }, + 'Smelter_gem_2_item_pedestal_27194': { + 'hash': 27194, + 'name': 'Smelter_gem_2_item_pedestal', + 'savables': {} + } + } + }, + 'Smelter_gem_3_item_pedestal': { + 'hash': 63036, + 'name': 'Smelter_gem_3_item_pedestal', + 'embedded': { + 'Pedestal_Dock_27002': { + 'hash': 27002, + 'name': 'Pedestal_Dock', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'PickupDockPedestalSpawn': { + 'hash': 2592242915, + 'name': 'PickupDockPedestalSpawn' + } + } + }, + 'Smelter_gem_3_item_pedestal_27194': { + 'hash': 27194, + 'name': 'Smelter_gem_3_item_pedestal', + 'savables': {} + } + } + }, + 'SnowballMoundSpawner': { + 'hash': 30542, + 'name': 'SnowballMoundSpawner', + 'embedded': { + 'SnowballMoundSpawner_24412': { + 'hash': 24412, + 'name': 'SnowballMoundSpawner', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'SnowballSpawner': { + 'hash': 22418, + 'name': 'SnowballSpawner', + 'embedded': { + 'SnowballSpawner_52610': { + 'hash': 52610, + 'name': 'SnowballSpawner', + 'savables': {} + }, + 'Spawner_528': { + 'hash': 528, + 'name': 'Spawner', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'SpawnInCircle': { + 'hash': 1714180166, + 'name': 'SpawnInCircle' + } + } + } + } + }, + 'Snowball_network_Prefab': { + 'hash': 52090, + 'name': 'Snowball_network_Prefab', + 'embedded': { + 'Snowball_network_Prefab_36924': { + 'hash': 36924, + 'name': 'Snowball_network_Prefab', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Snowman_Network_Prefab_1': { + 'hash': 57830, + 'name': 'Snowman_Network_Prefab_1', + 'embedded': { + 'Dock_2780': { + 'hash': 2780, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Snowman_Network_Prefab_1_25600': { + 'hash': 25600, + 'name': 'Snowman_Network_Prefab_1', + 'savables': {} + } + } + }, + 'Snowman_Network_Prefab_2': { + 'hash': 16878, + 'name': 'Snowman_Network_Prefab_2', + 'embedded': { + 'Dock_2780': { + 'hash': 2780, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Snowman_Network_Prefab_2_25600': { + 'hash': 25600, + 'name': 'Snowman_Network_Prefab_2', + 'savables': {} + } + } + }, + 'Snowman_Network_Prefab_3': { + 'hash': 17612, + 'name': 'Snowman_Network_Prefab_3', + 'embedded': { + 'Dock_2780': { + 'hash': 2780, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Snowman_Network_Prefab_3_25600': { + 'hash': 25600, + 'name': 'Snowman_Network_Prefab_3', + 'savables': {} + } + } + }, + 'Snowman_Network_Prefab_test': { + 'hash': 25690, + 'name': 'Snowman_Network_Prefab_test', + 'embedded': { + 'Dock_2780': { + 'hash': 2780, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Snowman_Network_Prefab_test_25600': { + 'hash': 25600, + 'name': 'Snowman_Network_Prefab_test', + 'savables': {} + } + } + }, + 'Soft_Fabric_Large_Roll': { + 'hash': 23206, + 'name': 'Soft_Fabric_Large_Roll', + 'embedded': { + 'Soft_Fabric_Large_Roll_47776': { + 'hash': 47776, + 'name': 'Soft_Fabric_Large_Roll', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Spawner_43650': { + 'hash': 43650, + 'name': 'Spawner', + 'savables': {} + } + } + }, + 'Soft_Fabric_Medium_Roll': { + 'hash': 47760, + 'name': 'Soft_Fabric_Medium_Roll', + 'embedded': { + 'Soft_Fabric_Medium_Roll_47776': { + 'hash': 47776, + 'name': 'Soft_Fabric_Medium_Roll', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Spawner_43650': { + 'hash': 43650, + 'name': 'Spawner', + 'savables': {} + } + } + }, + 'Soft_Fabric_Medium_Strips': { + 'hash': 63204, + 'name': 'Soft_Fabric_Medium_Strips', + 'embedded': { + 'Soft_Fabric_Medium_Strips_63188': { + 'hash': 63188, + 'name': 'Soft_Fabric_Medium_Strips', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Spade_Head': { + 'hash': 50548, + 'name': 'Spade_Head', + 'embedded': { + 'Fake_Pickup_6096': { + 'hash': 6096, + 'name': 'Fake_Pickup', + 'savables': {} + }, + 'Insert_AxeType_7796': { + 'hash': 7796, + 'name': 'Insert_AxeType', + 'savables': {} + }, + 'Spade_Head_60654': { + 'hash': 60654, + 'name': 'Spade_Head', + 'savables': { + 'DiggingImpactor': { + 'hash': 3445325106, + 'name': 'DiggingImpactor' + }, + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'spade_head_LOD0_45520': { + 'hash': 45520, + 'name': 'spade_head_LOD0', + 'savables': {} + } + } + }, + 'Spawn_Point': { + 'hash': 63844, + 'name': 'Spawn_Point', + 'embedded': { + 'Spawn_Point_4036': { + 'hash': 4036, + 'name': 'Spawn_Point', + 'savables': {} + } + } + }, + 'Spawner_Test': { + 'hash': 51070, + 'name': 'Spawner_Test', + 'embedded': {} + }, + 'Spear_Head_Pyramid': { + 'hash': 13554, + 'name': 'Spear_Head_Pyramid', + 'embedded': {} + }, + 'Spear_Head_Spiky': { + 'hash': 13680, + 'name': 'Spear_Head_Spiky', + 'embedded': {} + }, + 'Spear_Head_Standard': { + 'hash': 13816, + 'name': 'Spear_Head_Standard', + 'embedded': {} + }, + 'Spectral_Ghost': { + 'hash': 57494, + 'name': 'Spectral_Ghost', + 'embedded': {} + }, + 'Spherical_Encounter': { + 'hash': 1222, + 'name': 'Spherical_Encounter', + 'embedded': { + /** @todo Verify entities and their components. */ + 'Spherical_Encounter_43896': { + 'hash': 43896, + 'name': 'Spherical_Encounter', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + } + } + }, + 'Spike_Fancy': { + 'hash': 12492, + 'name': 'Spike_Fancy', + 'embedded': { + 'Heat_Point_Collection_3584': { + 'hash': 3584, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_Deco_112': { + 'hash': 112, + 'name': 'Insert_Deco', + 'savables': {} + }, + 'Spike_Fancy_15532': { + 'hash': 15532, + 'name': 'Spike_Fancy', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Spike_Short': { + 'hash': 6934, + 'name': 'Spike_Short', + 'embedded': { + 'Insert_Deco_112': { + 'hash': 112, + 'name': 'Insert_Deco', + 'savables': {} + }, + 'Spike_Short_15532': { + 'hash': 15532, + 'name': 'Spike_Short', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Spike_Tall': { + 'hash': 3558, + 'name': 'Spike_Tall', + 'embedded': { + 'Insert_Deco_112': { + 'hash': 112, + 'name': 'Insert_Deco', + 'savables': {} + }, + 'Spike_Tall_15532': { + 'hash': 15532, + 'name': 'Spike_Tall', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Spire_Gcore_Dynamic': { + 'hash': 23472, + 'name': 'Spire_Gcore_Dynamic', + 'embedded': { + 'Directional_Encounter_33516': { + 'hash': 33516, + 'name': 'Directional_Encounter', + 'savables': { + 'DirectionalBoundsSurface': { + 'hash': 1962842866, + 'name': 'DirectionalBoundsSurface' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + }, + 'Spire_Gcore_Dynamic_23456': { + 'hash': 23456, + 'name': 'Spire_Gcore_Dynamic', + 'savables': {} + } + } + }, + 'Spread_Spawner_Dynamic': { + 'hash': 18426, + 'name': 'Spread_Spawner_Dynamic', + 'embedded': { + 'Directional_Encounter_(1)_45120': { + 'hash': 45120, + 'name': 'Directional_Encounter_(1)', + 'savables': { + 'DirectionalBoundsSurface': { + 'hash': 1962842866, + 'name': 'DirectionalBoundsSurface' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + }, + 'Directional_Encounter_45108': { + 'hash': 45108, + 'name': 'Directional_Encounter', + 'savables': { + 'DirectionalBoundsSurface': { + 'hash': 1962842866, + 'name': 'DirectionalBoundsSurface' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + }, + 'Spread_Spawner_Dynamic_18410': { + 'hash': 18410, + 'name': 'Spread_Spawner_Dynamic', + 'savables': {} + } + } + }, + 'Spriggull': { + 'hash': 62050, + 'name': 'Spriggull', + 'embedded': { + 'Body_60576': { + 'hash': 60576, + 'name': 'Body', + 'savables': {} + }, + 'Heat_42194': { + 'hash': 42194, + 'name': 'Heat', + 'savables': { + 'Fire': { + 'hash': 3457519710, + 'name': 'Fire' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Interactor_2642': { + 'hash': 2642, + 'name': 'Interactor', + 'savables': {} + }, + 'Spriggull_62666': { + 'hash': 62666, + 'name': 'Spriggull', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Spriggull_AI_58356': { + 'hash': 58356, + 'name': 'Spriggull_AI', + 'savables': {} + }, + 'skin_jaw_jnt_48650': { + 'hash': 48650, + 'name': 'skin_jaw_jnt', + 'savables': {} + } + } + }, + 'SpriggullDrumstick_Bone': { + 'hash': 24406, + 'name': 'SpriggullDrumstick_Bone', + 'embedded': { + 'SpriggullDrumstick_Bone_26390': { + 'hash': 26390, + 'name': 'SpriggullDrumstick_Bone', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'SpriggullDrumstick_Full_Burnt': { + 'hash': 20570, + 'name': 'SpriggullDrumstick_Full_Burnt', + 'embedded': { + 'Bone_Spawner_16064': { + 'hash': 16064, + 'name': 'Bone_Spawner', + 'savables': {} + }, + 'Cooking_35958': { + 'hash': 35958, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'SpriggullDrumstick_Full_Burnt_36708': { + 'hash': 36708, + 'name': 'SpriggullDrumstick_Full_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'SpriggullDrumstick_Full_Cooked': { + 'hash': 33190, + 'name': 'SpriggullDrumstick_Full_Cooked', + 'embedded': { + 'Bone_Spawner_16556': { + 'hash': 16556, + 'name': 'Bone_Spawner', + 'savables': {} + }, + 'Cooking_29822': { + 'hash': 29822, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'SpriggullDrumstick_Full_Cooked_30572': { + 'hash': 30572, + 'name': 'SpriggullDrumstick_Full_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'SpriggullDrumstick_Full_Ripe': { + 'hash': 43430, + 'name': 'SpriggullDrumstick_Full_Ripe', + 'embedded': { + 'Bone_Spawner_38786': { + 'hash': 38786, + 'name': 'Bone_Spawner', + 'savables': {} + }, + 'Cooking_24500': { + 'hash': 24500, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'SpriggullDrumstick_Full_Ripe_25250': { + 'hash': 25250, + 'name': 'SpriggullDrumstick_Full_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'SpriggullDrumstick_Half_Burnt': { + 'hash': 10908, + 'name': 'SpriggullDrumstick_Half_Burnt', + 'embedded': { + 'Cooking_19872': { + 'hash': 19872, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'SpriggullDrumstick_Half_Burnt_19928': { + 'hash': 19928, + 'name': 'SpriggullDrumstick_Half_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'SpriggullDrumstick_Half_Cooked': { + 'hash': 8440, + 'name': 'SpriggullDrumstick_Half_Cooked', + 'embedded': { + 'Cooking_18026': { + 'hash': 18026, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'SpriggullDrumstick_Half_Cooked_18082': { + 'hash': 18082, + 'name': 'SpriggullDrumstick_Half_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'SpriggullDrumstick_Half_Ripe': { + 'hash': 5972, + 'name': 'SpriggullDrumstick_Half_Ripe', + 'embedded': { + 'Cooking_16182': { + 'hash': 16182, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'SpriggullDrumstick_Half_Ripe_16238': { + 'hash': 16238, + 'name': 'SpriggullDrumstick_Half_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Spriggull_Egg': { + 'hash': 7014, + 'name': 'Spriggull_Egg', + 'embedded': { + 'Spriggull_Egg_5216': { + 'hash': 5216, + 'name': 'Spriggull_Egg', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Spriggull_Feather_Blue': { + 'hash': 7918, + 'name': 'Spriggull_Feather_Blue', + 'embedded': { + 'Spriggull_Feather_Blue_61684': { + 'hash': 61684, + 'name': 'Spriggull_Feather_Blue', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Spriggull_Feather_Green': { + 'hash': 25446, + 'name': 'Spriggull_Feather_Green', + 'embedded': { + 'Insert_Feather_112': { + 'hash': 112, + 'name': 'Insert_Feather', + 'savables': {} + }, + 'Spriggull_Feather_Green_25450': { + 'hash': 25450, + 'name': 'Spriggull_Feather_Green', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Spriggull_Feather_Purple': { + 'hash': 36248, + 'name': 'Spriggull_Feather_Purple', + 'embedded': { + 'Insert_Feather_112': { + 'hash': 112, + 'name': 'Insert_Feather', + 'savables': {} + }, + 'Spriggull_Feather_Purple_36244': { + 'hash': 36244, + 'name': 'Spriggull_Feather_Purple', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Spriggull_Feather_Red': { + 'hash': 18734, + 'name': 'Spriggull_Feather_Red', + 'embedded': { + 'Spriggull_Feather_Red_18738': { + 'hash': 18738, + 'name': 'Spriggull_Feather_Red', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Spriggull_Fletching_Blue': { + 'hash': 50608, + 'name': 'Spriggull_Fletching_Blue', + 'embedded': { + 'Insert_Feather_51282': { + 'hash': 51282, + 'name': 'Insert_Feather', + 'savables': {} + }, + 'Spriggull_Fletching_Blue_51284': { + 'hash': 51284, + 'name': 'Spriggull_Fletching_Blue', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Spriggull_Fletching_Red': { + 'hash': 24072, + 'name': 'Spriggull_Fletching_Red', + 'embedded': { + 'Insert_Feather_112': { + 'hash': 112, + 'name': 'Insert_Feather', + 'savables': {} + }, + 'Spriggull_Fletching_Red_18738': { + 'hash': 18738, + 'name': 'Spriggull_Fletching_Red', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Spriggull_Nest': { + 'hash': 16680, + 'name': 'Spriggull_Nest', + 'embedded': { + 'Spriggull_Nest_16166': { + 'hash': 16166, + 'name': 'Spriggull_Nest', + 'savables': {} + } + } + }, + 'SpyGlass': { + 'hash': 5170, + 'name': 'SpyGlass', + 'embedded': { + 'SpyGlass_7714': { + 'hash': 7714, + 'name': 'SpyGlass', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'spyglass_body_01_57858': { + 'hash': 57858, + 'name': 'spyglass_body_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'spyglass_body_02_57854': { + 'hash': 57854, + 'name': 'spyglass_body_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'spyglass_wraps_57850': { + 'hash': 57850, + 'name': 'spyglass_wraps', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'SpyGlass_Long': { + 'hash': 64848, + 'name': 'SpyGlass_Long', + 'embedded': { + 'SpyGlass_Long_7714': { + 'hash': 7714, + 'name': 'SpyGlass_Long', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Stalactite_pillar': { + 'hash': 3944, + 'name': 'Stalactite_pillar', + 'embedded': { + 'Explosion_17130': { + 'hash': 17130, + 'name': 'Explosion', + 'savables': {} + }, + 'Explosion_17244': { + 'hash': 17244, + 'name': 'Explosion', + 'savables': {} + }, + 'Explosion_17358': { + 'hash': 17358, + 'name': 'Explosion', + 'savables': {} + }, + 'Explosion_17472': { + 'hash': 17472, + 'name': 'Explosion', + 'savables': {} + }, + 'Explosion_17586': { + 'hash': 17586, + 'name': 'Explosion', + 'savables': {} + }, + 'Explosion_17700': { + 'hash': 17700, + 'name': 'Explosion', + 'savables': {} + }, + 'Explosion_21698': { + 'hash': 21698, + 'name': 'Explosion', + 'savables': {} + }, + 'Explosive_Spike_Stalactite(NoNetworkPrefab)_17234': { + 'hash': 17234, + 'name': 'Explosive_Spike_Stalactite(NoNetworkPrefab)', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Explosive_Spike_Stalactite(NoNetworkPrefab)_17348': { + 'hash': 17348, + 'name': 'Explosive_Spike_Stalactite(NoNetworkPrefab)', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Explosive_Spike_Stalactite(NoNetworkPrefab)_17462': { + 'hash': 17462, + 'name': 'Explosive_Spike_Stalactite(NoNetworkPrefab)', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Explosive_Spike_Stalactite(NoNetworkPrefab)_17576': { + 'hash': 17576, + 'name': 'Explosive_Spike_Stalactite(NoNetworkPrefab)', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Explosive_Spike_Stalactite(NoNetworkPrefab)_17690': { + 'hash': 17690, + 'name': 'Explosive_Spike_Stalactite(NoNetworkPrefab)', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Explosive_Spike_Stalactite(NoNetworkPrefab)_17804': { + 'hash': 17804, + 'name': 'Explosive_Spike_Stalactite(NoNetworkPrefab)', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Explosive_Spike_Stalactite(NoNetworkPrefab)_21742': { + 'hash': 21742, + 'name': 'Explosive_Spike_Stalactite(NoNetworkPrefab)', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'Hit_Detection_44554': { + 'hash': 44554, + 'name': 'Hit_Detection', + 'savables': { + 'ImpactDetectionLogic': { + 'hash': 1435171891, + 'name': 'ImpactDetectionLogic' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Stalactite_pillar_50810': { + 'hash': 50810, + 'name': 'Stalactite_pillar', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + } + } + } + } + }, + 'Standard_Crafted_Mould': { + 'hash': 38578, + 'name': 'Standard_Crafted_Mould', + 'embedded': { + 'Flat_Mould_Emblem_9986': { + 'hash': 9986, + 'name': 'Flat_Mould_Emblem', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'Standard_Crafted_Mould_14710': { + 'hash': 14710, + 'name': 'Standard_Crafted_Mould', + 'savables': { + 'Mould': { + 'hash': 391977879, + 'name': 'Mould' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'mould_standard_ingotGraphic_60818': { + 'hash': 60818, + 'name': 'mould_standard_ingotGraphic', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'mould_standard_outerFrame_01_60826': { + 'hash': 60826, + 'name': 'mould_standard_outerFrame_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'mould_standard_railSlot_01_60830': { + 'hash': 60830, + 'name': 'mould_standard_railSlot_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'mould_standard_railSlot_02_60814': { + 'hash': 60814, + 'name': 'mould_standard_railSlot_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'mould_standard_railSlot_03_60822': { + 'hash': 60822, + 'name': 'mould_standard_railSlot_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'mould_standard_railSlot_04_60806': { + 'hash': 60806, + 'name': 'mould_standard_railSlot_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'mould_standard_timesGraphic_60810': { + 'hash': 60810, + 'name': 'mould_standard_timesGraphic', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Standard_Side_Pouch_Attachment': { + 'hash': 7852, + 'name': 'Standard_Side_Pouch_Attachment', + 'embedded': { + 'Dock_45700': { + 'hash': 45700, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62078': { + 'hash': 62078, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Insert_Bag_Attach_7796': { + 'hash': 7796, + 'name': 'Insert_Bag_Attach', + 'savables': {} + }, + 'Standard_Side_Pouch_Attachment_7868': { + 'hash': 7868, + 'name': 'Standard_Side_Pouch_Attachment', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Storage_52822': { + 'hash': 52822, + 'name': 'Storage', + 'savables': {} + }, + 'standard_sidePouch_backPin_L1_7968': { + 'hash': 7968, + 'name': 'standard_sidePouch_backPin_L1', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_sidePouch_body_7972': { + 'hash': 7972, + 'name': 'standard_sidePouch_body', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_sidePouch_body_flap_7980': { + 'hash': 7980, + 'name': 'standard_sidePouch_body_flap', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_sidePouch_flap_7976': { + 'hash': 7976, + 'name': 'standard_sidePouch_flap', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Standard_Side_Tool_Attachment': { + 'hash': 59468, + 'name': 'Standard_Side_Tool_Attachment', + 'embedded': { + 'Dock_62078': { + 'hash': 62078, + 'name': 'Dock', + 'savables': { + 'AdditionalOwnedDock': { + 'hash': 2592242915, + 'name': 'AdditionalOwnedDock' + } + } + }, + 'Insert_Bag_Attach_7796': { + 'hash': 7796, + 'name': 'Insert_Bag_Attach', + 'savables': {} + }, + 'Standard_Side_Tool_Attachment_7868': { + 'hash': 7868, + 'name': 'Standard_Side_Tool_Attachment', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Storage_52526': { + 'hash': 52526, + 'name': 'Storage', + 'savables': {} + }, + 'standard_sideTool_slot_loop_33788': { + 'hash': 33788, + 'name': 'standard_sideTool_slot_loop', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_sideTool_slot_pad_01_33784': { + 'hash': 33784, + 'name': 'standard_sideTool_slot_pad_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_sideTool_slot_pad_02_33780': { + 'hash': 33780, + 'name': 'standard_sideTool_slot_pad_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'standard_sideTool_slot_strap_01_33776': { + 'hash': 33776, + 'name': 'standard_sideTool_slot_strap_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Standard_Stages': { + 'hash': 31152, + 'name': 'Standard_Stages', + 'embedded': { + 'Standard_Stages_53224': { + 'hash': 53224, + 'name': 'Standard_Stages', + 'savables': { + 'StageBasedPrefab': { + 'hash': 1390862571, + 'name': 'StageBasedPrefab' + } + } + } + } + }, + 'Steam_Spray': { + 'hash': 53376, + 'name': 'Steam_Spray', + 'embedded': { + 'Hurting_Bit_26178': { + 'hash': 26178, + 'name': 'Hurting_Bit', + 'savables': {} + }, + 'Start_event_44764': { + 'hash': 44764, + 'name': 'Start_event', + 'savables': {} + }, + 'Steam_Spray_61896': { + 'hash': 61896, + 'name': 'Steam_Spray', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + } + } + }, + 'Stop_event_45050': { + 'hash': 45050, + 'name': 'Stop_event', + 'savables': {} + } + } + }, + 'Steel_Alloy_Ingot': { + 'hash': 22222, + 'name': 'Steel_Alloy_Ingot', + 'embedded': {} + }, + 'Stick': { + 'hash': 61674, + 'name': 'Stick', + 'embedded': { + 'Slot_Multi_64914': { + 'hash': 64914, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Slot_Primitive_SwordType_30294': { + 'hash': 30294, + 'name': 'Slot_Primitive_SwordType', + 'savables': {} + }, + 'Stick_31654': { + 'hash': 31654, + 'name': 'Stick', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Stick_Charred': { + 'hash': 20564, + 'name': 'Stick_Charred', + 'embedded': { + 'Stick_Charred_31654': { + 'hash': 31654, + 'name': 'Stick_Charred', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Stick_Storage': { + 'hash': 46252, + 'name': 'Stick_Storage', + 'embedded': { + 'Filter_Dock_57214': { + 'hash': 57214, + 'name': 'Filter_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Interaction_Point_59032': { + 'hash': 59032, + 'name': 'Interaction_Point', + 'savables': {} + }, + 'Internal_Dock_59328': { + 'hash': 59328, + 'name': 'Internal_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Stick_Storage_59042': { + 'hash': 59042, + 'name': 'Stick_Storage', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + }, + 'CommunalStorage': { + 'hash': 3084373371, + 'name': 'CommunalStorage' + }, + 'PlayerInteractionRestrictor': { + 'hash': 2951515968, + 'name': 'PlayerInteractionRestrictor' + } + } + }, + 'Withdraw_Dock_34750': { + 'hash': 34750, + 'name': 'Withdraw_Dock', + 'savables': {} + } + } + }, + 'Stick_Training': { + 'hash': 61414, + 'name': 'Stick_Training', + 'embedded': { + 'Stick_Training_61396': { + 'hash': 61396, + 'name': 'Stick_Training', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Stone': { + 'hash': 61670, + 'name': 'Stone', + 'embedded': { + 'Insert_Primitive_SwordType_7796': { + 'hash': 7796, + 'name': 'Insert_Primitive_SwordType', + 'savables': {} + }, + 'Stone_30920': { + 'hash': 30920, + 'name': 'Stone', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Stone_Boulder_01': { + 'hash': 33376, + 'name': 'Stone_Boulder_01', + 'embedded': { + 'Stone_Boulder_01_33370': { + 'hash': 33370, + 'name': 'Stone_Boulder_01', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Stone_Boulder_02': { + 'hash': 17686, + 'name': 'Stone_Boulder_02', + 'embedded': { + 'Stone_Boulder_02_17680': { + 'hash': 17680, + 'name': 'Stone_Boulder_02', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Stone_Boulder_03': { + 'hash': 12450, + 'name': 'Stone_Boulder_03', + 'embedded': { + 'Stone_Boulder_03_12444': { + 'hash': 12444, + 'name': 'Stone_Boulder_03', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Stone_Boulder_Cluster': { + 'hash': 8948, + 'name': 'Stone_Boulder_Cluster', + 'embedded': { + 'Stone_Boulder_Cluster_8942': { + 'hash': 8942, + 'name': 'Stone_Boulder_Cluster', + 'savables': {} + } + } + }, + 'Stone_Training': { + 'hash': 19490, + 'name': 'Stone_Training', + 'embedded': { + 'Stone_Training_19480': { + 'hash': 19480, + 'name': 'Stone_Training', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Storage_Chest': { + 'hash': 63826, + 'name': 'Storage_Chest', + 'embedded': { + 'Bottom_Dock_1_2780': { + 'hash': 2780, + 'name': 'Bottom_Dock_1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_2_2778': { + 'hash': 2778, + 'name': 'Bottom_Dock_2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_3_2776': { + 'hash': 2776, + 'name': 'Bottom_Dock_3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_4_2770': { + 'hash': 2770, + 'name': 'Bottom_Dock_4', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_5_2772': { + 'hash': 2772, + 'name': 'Bottom_Dock_5', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_6_2774': { + 'hash': 2774, + 'name': 'Bottom_Dock_6', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Handle_Left_23970': { + 'hash': 23970, + 'name': 'Handle_Left', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Handle_Right_23964': { + 'hash': 23964, + 'name': 'Handle_Right', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Lid_2768': { + 'hash': 2768, + 'name': 'Lid', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Storage_Chest_2788': { + 'hash': 2788, + 'name': 'Storage_Chest', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + }, + 'Chest': { + 'hash': 3598052397, + 'name': 'Chest' + } + } + }, + 'Top_Dock_1_2766': { + 'hash': 2766, + 'name': 'Top_Dock_1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_2_2764': { + 'hash': 2764, + 'name': 'Top_Dock_2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_3_2762': { + 'hash': 2762, + 'name': 'Top_Dock_3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_4_2756': { + 'hash': 2756, + 'name': 'Top_Dock_4', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_5_2758': { + 'hash': 2758, + 'name': 'Top_Dock_5', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_6_2760': { + 'hash': 2760, + 'name': 'Top_Dock_6', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + } + } + }, + 'Storage_Crate_Parts': { + 'hash': 16574, + 'name': 'Storage_Crate_Parts', + 'embedded': { + 'Storage_Crate_Parts_23406': { + 'hash': 23406, + 'name': 'Storage_Crate_Parts', + 'savables': {} + } + } + }, + 'Storage_Crate_Redwood_Closed': { + 'hash': 59594, + 'name': 'Storage_Crate_Redwood_Closed', + 'embedded': { + 'Spawn_Content_29300': { + 'hash': 29300, + 'name': 'Spawn_Content', + 'savables': {} + }, + 'Storage_Crate_Redwood_Closed_64282': { + 'hash': 64282, + 'name': 'Storage_Crate_Redwood_Closed', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Storage_Crate_Redwood_Open': { + 'hash': 32788, + 'name': 'Storage_Crate_Redwood_Open', + 'embedded': { + 'Random_Spawn_Rectangle_22462': { + 'hash': 22462, + 'name': 'Random_Spawn_Rectangle', + 'savables': { + 'RandomSpawnRectangle': { + 'hash': 3101665521, + 'name': 'RandomSpawnRectangle' + } + } + }, + 'Spawn_Content_3812': { + 'hash': 3812, + 'name': 'Spawn_Content', + 'savables': {} + }, + 'Storage_Crate_Redwood_Open_50750': { + 'hash': 50750, + 'name': 'Storage_Crate_Redwood_Open', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Street_Post': { + 'hash': 57248, + 'name': 'Street_Post', + 'embedded': { + 'Sign_Body_17004': { + 'hash': 17004, + 'name': 'Sign_Body', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Street_Post_54666': { + 'hash': 54666, + 'name': 'Street_Post', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + }, + 'Visual_1_28010': { + 'hash': 28010, + 'name': 'Visual_1', + 'savables': { + 'MeshPlacement': { + 'hash': 2169673426, + 'name': 'MeshPlacement' + } + } + }, + 'Visual_2_57532': { + 'hash': 57532, + 'name': 'Visual_2', + 'savables': { + 'MeshPlacement': { + 'hash': 2169673426, + 'name': 'MeshPlacement' + } + } + }, + 'Visual_3_15494': { + 'hash': 15494, + 'name': 'Visual_3', + 'savables': { + 'MeshPlacement': { + 'hash': 2169673426, + 'name': 'MeshPlacement' + } + } + }, + 'Visual_4_9368': { + 'hash': 9368, + 'name': 'Visual_4', + 'savables': { + 'MeshPlacement': { + 'hash': 2169673426, + 'name': 'MeshPlacement' + } + } + } + } + }, + 'Structure_Chest': { + 'hash': 35280, + 'name': 'Structure_Chest', + 'embedded': { + 'Bottom_Dock_1_2780': { + 'hash': 2780, + 'name': 'Bottom_Dock_1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_2_2778': { + 'hash': 2778, + 'name': 'Bottom_Dock_2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_3_2776': { + 'hash': 2776, + 'name': 'Bottom_Dock_3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_4_2770': { + 'hash': 2770, + 'name': 'Bottom_Dock_4', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_5_2772': { + 'hash': 2772, + 'name': 'Bottom_Dock_5', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Bottom_Dock_6_2774': { + 'hash': 2774, + 'name': 'Bottom_Dock_6', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Handle_Left_23970': { + 'hash': 23970, + 'name': 'Handle_Left', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Handle_Right_23964': { + 'hash': 23964, + 'name': 'Handle_Right', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Lid_2768': { + 'hash': 2768, + 'name': 'Lid', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Storage_Chest_(1)_2788': { + 'hash': 2788, + 'name': 'Storage_Chest_(1)', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + }, + 'Chest': { + 'hash': 3598052397, + 'name': 'Chest' + } + } + }, + 'Structure_Chest_21454': { + 'hash': 21454, + 'name': 'Structure_Chest', + 'savables': { + 'GeneratedLoot': { + 'hash': 3642863935, + 'name': 'GeneratedLoot' + } + } + }, + 'Top_Dock_1_2766': { + 'hash': 2766, + 'name': 'Top_Dock_1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_2_2764': { + 'hash': 2764, + 'name': 'Top_Dock_2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_3_2762': { + 'hash': 2762, + 'name': 'Top_Dock_3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_4_2756': { + 'hash': 2756, + 'name': 'Top_Dock_4', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_5_2758': { + 'hash': 2758, + 'name': 'Top_Dock_5', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Top_Dock_6_2760': { + 'hash': 2760, + 'name': 'Top_Dock_6', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + } + } + }, + 'TEMP_Hebios_Camp_Spawner_Barren': { + 'hash': 33858, + 'name': 'TEMP_Hebios_Camp_Spawner_Barren', + 'embedded': {} + }, + 'TEMP_Hebios_Camp_Spawner_Valley': { + 'hash': 33880, + 'name': 'TEMP_Hebios_Camp_Spawner_Valley', + 'embedded': {} + }, + 'TEMP_Watch_Tower_Spawner': { + 'hash': 44032, + 'name': 'TEMP_Watch_Tower_Spawner', + 'embedded': {} + }, + 'Tab_Lever': { + 'hash': 3354, + 'name': 'Tab_Lever', + 'embedded': {} + }, + 'Table_Placer': { + 'hash': 25418, + 'name': 'Table_Placer', + 'embedded': { + 'Table_Placer_29584': { + 'hash': 29584, + 'name': 'Table_Placer', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'RaycastCrafter': { + 'hash': 2815374842, + 'name': 'RaycastCrafter' + } + } + } + } + }, + 'Tall_Support': { + 'hash': 46506, + 'name': 'Tall_Support', + 'embedded': { + 'Tall_Support_5348': { + 'hash': 5348, + 'name': 'Tall_Support', + 'savables': {} + } + } + }, + 'Tall_Support_Beams': { + 'hash': 5682, + 'name': 'Tall_Support_Beams', + 'embedded': { + 'Tall_Support_Beams_5680': { + 'hash': 5680, + 'name': 'Tall_Support_Beams', + 'savables': {} + } + } + }, + 'Targeted_Geyser': { + 'hash': 60812, + 'name': 'Targeted_Geyser', + 'embedded': { + 'Erupt_Area_19858': { + 'hash': 19858, + 'name': 'Erupt_Area', + 'savables': {} + }, + 'Geyser_AI_29794': { + 'hash': 29794, + 'name': 'Geyser_AI', + 'savables': {} + }, + 'Targeted_Geyser_37626': { + 'hash': 37626, + 'name': 'Targeted_Geyser', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'TeleportOnTrueLogic': { + 'hash': 18260, + 'name': 'TeleportOnTrueLogic', + 'embedded': { + 'TeleportOnTrueLogic_11330': { + 'hash': 11330, + 'name': 'TeleportOnTrueLogic', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'TeleportationPoint': { + 'hash': 3146178080, + 'name': 'TeleportationPoint' + } + } + } + } + }, + 'Teleport_Point': { + 'hash': 33542, + 'name': 'Teleport_Point', + 'embedded': {} + }, + 'Teleporter_Puzzle': { + 'hash': 19164, + 'name': 'Teleporter_Puzzle', + 'embedded': { + 'Customization_Teleporter_2940': { + 'hash': 2940, + 'name': 'Customization_Teleporter', + 'savables': {} + }, + 'Teleporter_Puzzle_7710': { + 'hash': 7710, + 'name': 'Teleporter_Puzzle', + 'savables': { + 'LogicVector3Receiver': { + 'hash': 1228539097, + 'name': 'LogicVector3Receiver' + }, + 'LogicVector3Sender': { + 'hash': 2026743731, + 'name': 'LogicVector3Sender' + }, + 'PositionProvider': { + 'hash': 3538443740, + 'name': 'PositionProvider' + }, + 'TeleportationPoint': { + 'hash': 3146178080, + 'name': 'TeleportationPoint' + } + } + } + } + }, + 'Teleporter_To_Customization': { + 'hash': 60372, + 'name': 'Teleporter_To_Customization', + 'embedded': { + 'Customization_Teleporter_27658': { + 'hash': 27658, + 'name': 'Customization_Teleporter', + 'savables': {} + }, + 'Teleporter_To_Customization_60294': { + 'hash': 60294, + 'name': 'Teleporter_To_Customization', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + } + } + }, + 'Temp_Dynamic_Wall': { + 'hash': 31628, + 'name': 'Temp_Dynamic_Wall', + 'embedded': { + 'Temp_Dynamic_Wall_8038': { + 'hash': 8038, + 'name': 'Temp_Dynamic_Wall', + 'savables': {} + } + } + }, + 'Test_Fire': { + 'hash': 31268, + 'name': 'Test_Fire', + 'embedded': { + 'Fire_30100': { + 'hash': 30100, + 'name': 'Fire', + 'savables': { + 'Fire': { + 'hash': 3457519710, + 'name': 'Fire' + } + } + }, + 'Forge_Area_19102': { + 'hash': 19102, + 'name': 'Forge_Area', + 'savables': {} + }, + 'Test_Fire_61848': { + 'hash': 61848, + 'name': 'Test_Fire', + 'savables': {} + } + } + }, + 'Test_Serializable_Large': { + 'hash': 57330, + 'name': 'Test_Serializable_Large', + 'embedded': {} + }, + 'Test_Serializable_Small': { + 'hash': 51498, + 'name': 'Test_Serializable_Small', + 'embedded': {} + }, + 'Thick_Great_Sword_Blade': { + 'hash': 25802, + 'name': 'Thick_Great_Sword_Blade', + 'embedded': { + 'Heat_Point_Collection_64052': { + 'hash': 64052, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_Large_SwordType_7796': { + 'hash': 7796, + 'name': 'Insert_Large_SwordType', + 'savables': {} + }, + 'Thick_Great_Sword_Blade_84': { + 'hash': 84, + 'name': 'Thick_Great_Sword_Blade', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'metal_thickGreatsword_blade_full_geo_LOD0_2564': { + 'hash': 2564, + 'name': 'metal_thickGreatsword_blade_full_geo_LOD0', + 'savables': {} + } + } + }, + 'Thin_Cloth_Medium_Square': { + 'hash': 34570, + 'name': 'Thin_Cloth_Medium_Square', + 'embedded': { + 'Thin_Cloth_Medium_Square_14710': { + 'hash': 14710, + 'name': 'Thin_Cloth_Medium_Square', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Timber_Bag': { + 'hash': 25122, + 'name': 'Timber_Bag', + 'embedded': { + 'Bag_Body_42972': { + 'hash': 42972, + 'name': 'Bag_Body', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Dock_TL_42990': { + 'hash': 42990, + 'name': 'Dock_TL', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Interaction_Point_59032': { + 'hash': 59032, + 'name': 'Interaction_Point', + 'savables': {} + }, + 'Slot_Bag_Attach_30776': { + 'hash': 30776, + 'name': 'Slot_Bag_Attach', + 'savables': {} + }, + 'Slot_Bag_Attach_55164': { + 'hash': 55164, + 'name': 'Slot_Bag_Attach', + 'savables': {} + }, + 'Timber_Bag_43012': { + 'hash': 43012, + 'name': 'Timber_Bag', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'basket_bag_handle_wraps_56574': { + 'hash': 56574, + 'name': 'basket_bag_handle_wraps', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'basket_handle_56602': { + 'hash': 56602, + 'name': 'basket_handle', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_leather_pad_14826': { + 'hash': 14826, + 'name': 'timber_bag_leather_pad', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_plank_01_14822': { + 'hash': 14822, + 'name': 'timber_bag_plank_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_plank_02_14818': { + 'hash': 14818, + 'name': 'timber_bag_plank_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_plank_03_14814': { + 'hash': 14814, + 'name': 'timber_bag_plank_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_ropeKnot_01_14810': { + 'hash': 14810, + 'name': 'timber_bag_ropeKnot_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_ropeKnot_02_14806': { + 'hash': 14806, + 'name': 'timber_bag_ropeKnot_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_ropeKnot_03_14802': { + 'hash': 14802, + 'name': 'timber_bag_ropeKnot_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_ropeKnot_04_14798': { + 'hash': 14798, + 'name': 'timber_bag_ropeKnot_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_ropeKnot_05_14794': { + 'hash': 14794, + 'name': 'timber_bag_ropeKnot_05', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_ropeKnot_07_14890': { + 'hash': 14890, + 'name': 'timber_bag_ropeKnot_07', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_ropeKnot_08_14886': { + 'hash': 14886, + 'name': 'timber_bag_ropeKnot_08', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_ropeNotch_01_14882': { + 'hash': 14882, + 'name': 'timber_bag_ropeNotch_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_ropeNotch_02_14878': { + 'hash': 14878, + 'name': 'timber_bag_ropeNotch_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_ropeNotch_03_14874': { + 'hash': 14874, + 'name': 'timber_bag_ropeNotch_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_ropeNotch_04_14870': { + 'hash': 14870, + 'name': 'timber_bag_ropeNotch_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_ropeNotch_05_14866': { + 'hash': 14866, + 'name': 'timber_bag_ropeNotch_05', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_ropeNotch_06_14862': { + 'hash': 14862, + 'name': 'timber_bag_ropeNotch_06', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_ropeNotch_07_14858': { + 'hash': 14858, + 'name': 'timber_bag_ropeNotch_07', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_ropeNotch_08_14854': { + 'hash': 14854, + 'name': 'timber_bag_ropeNotch_08', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_stick_010_14846': { + 'hash': 14846, + 'name': 'timber_bag_stick_010', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_stick_011_14842': { + 'hash': 14842, + 'name': 'timber_bag_stick_011', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_stick_01_14850': { + 'hash': 14850, + 'name': 'timber_bag_stick_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_stick_02_14838': { + 'hash': 14838, + 'name': 'timber_bag_stick_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_stick_03_14834': { + 'hash': 14834, + 'name': 'timber_bag_stick_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_stick_04_14830': { + 'hash': 14830, + 'name': 'timber_bag_stick_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_stick_05_14790': { + 'hash': 14790, + 'name': 'timber_bag_stick_05', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_stick_06_14786': { + 'hash': 14786, + 'name': 'timber_bag_stick_06', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_stick_07_14782': { + 'hash': 14782, + 'name': 'timber_bag_stick_07', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_stick_08_14778': { + 'hash': 14778, + 'name': 'timber_bag_stick_08', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_stick_09_14774': { + 'hash': 14774, + 'name': 'timber_bag_stick_09', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Timber_Side_Pouch_Attachment': { + 'hash': 7102, + 'name': 'Timber_Side_Pouch_Attachment', + 'embedded': { + 'Dock_45700': { + 'hash': 45700, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62078': { + 'hash': 62078, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Insert_Bag_Attach_7796': { + 'hash': 7796, + 'name': 'Insert_Bag_Attach', + 'savables': {} + }, + 'Storage_52232': { + 'hash': 52232, + 'name': 'Storage', + 'savables': {} + }, + 'Timber_Side_Pouch_Attachment_7868': { + 'hash': 7868, + 'name': 'Timber_Side_Pouch_Attachment', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'timber_bag_attachment_plank_01_358': { + 'hash': 358, + 'name': 'timber_bag_attachment_plank_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_attachment_ropeKnot_01_406': { + 'hash': 406, + 'name': 'timber_bag_attachment_ropeKnot_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_attachment_ropeKnot_02_402': { + 'hash': 402, + 'name': 'timber_bag_attachment_ropeKnot_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_attachment_ropeNotch_01_390': { + 'hash': 390, + 'name': 'timber_bag_attachment_ropeNotch_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_attachment_stick_01_386': { + 'hash': 386, + 'name': 'timber_bag_attachment_stick_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_attachment_stick_02_382': { + 'hash': 382, + 'name': 'timber_bag_attachment_stick_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_attachment_stick_03_378': { + 'hash': 378, + 'name': 'timber_bag_attachment_stick_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_attachment_stick_04_374': { + 'hash': 374, + 'name': 'timber_bag_attachment_stick_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_attachment_stick_05_370': { + 'hash': 370, + 'name': 'timber_bag_attachment_stick_05', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'timber_bag_attachment_stick_06_366': { + 'hash': 366, + 'name': 'timber_bag_attachment_stick_06', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Timed_Respawner': { + 'hash': 32620, + 'name': 'Timed_Respawner', + 'embedded': { + 'Timed_Respawner_32662': { + 'hash': 32662, + 'name': 'Timed_Respawner', + 'savables': { + 'RespawnOnDestroy': { + 'hash': 830106687, + 'name': 'RespawnOnDestroy' + } + } + } + } + }, + 'TimerLogic': { + 'hash': 18490, + 'name': 'TimerLogic', + 'embedded': { + 'TimerLogic_63978': { + 'hash': 63978, + 'name': 'TimerLogic', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'TimerLogic': { + 'hash': 3109677933, + 'name': 'TimerLogic' + } + } + } + } + }, + 'Tinder': { + 'hash': 34122, + 'name': 'Tinder', + 'embedded': { + 'Fire_8488': { + 'hash': 8488, + 'name': 'Fire', + 'savables': { + 'Fire': { + 'hash': 3457519710, + 'name': 'Fire' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Spawner_49628': { + 'hash': 49628, + 'name': 'Spawner', + 'savables': {} + }, + 'Tinder_24372': { + 'hash': 24372, + 'name': 'Tinder', + 'savables': { + 'BasicDecay': { + 'hash': 3801256786, + 'name': 'BasicDecay' + } + } + } + } + }, + 'Tomato_Flower_Bloom': { + 'hash': 13022, + 'name': 'Tomato_Flower_Bloom', + 'embedded': { + 'Tomato_Flower_Bloom_49826': { + 'hash': 49826, + 'name': 'Tomato_Flower_Bloom', + 'savables': {} + } + } + }, + 'Tomato_Flower_Bud': { + 'hash': 13024, + 'name': 'Tomato_Flower_Bud', + 'embedded': { + 'Tomato_Flower_Bud_49898': { + 'hash': 49898, + 'name': 'Tomato_Flower_Bud', + 'savables': {} + } + } + }, + 'Tomato_Full_Burnt': { + 'hash': 38742, + 'name': 'Tomato_Full_Burnt', + 'embedded': { + 'Cooking_57238': { + 'hash': 57238, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Tomato_Full_Burnt_38212': { + 'hash': 38212, + 'name': 'Tomato_Full_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Tomato_Full_Cooked': { + 'hash': 38098, + 'name': 'Tomato_Full_Cooked', + 'embedded': { + 'Cooking_56718': { + 'hash': 56718, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Tomato_Full_Cooked_37568': { + 'hash': 37568, + 'name': 'Tomato_Full_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Tomato_Full_Ripe': { + 'hash': 37454, + 'name': 'Tomato_Full_Ripe', + 'embedded': { + 'Cooking_56198': { + 'hash': 56198, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Tomato_Full_Ripe_36924': { + 'hash': 36924, + 'name': 'Tomato_Full_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Tomato_Full_Unripe': { + 'hash': 36810, + 'name': 'Tomato_Full_Unripe', + 'embedded': { + 'Cooking_55678': { + 'hash': 55678, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Tomato_Full_Unripe_36280': { + 'hash': 36280, + 'name': 'Tomato_Full_Unripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Tomato_Growth': { + 'hash': 19280, + 'name': 'Tomato_Growth', + 'embedded': { + 'Tomato_Growth_33458': { + 'hash': 33458, + 'name': 'Tomato_Growth', + 'savables': { + 'GrowerComponent': { + 'hash': 3402094521, + 'name': 'GrowerComponent' + } + } + } + } + }, + 'Tomato_Half_Burnt': { + 'hash': 57698, + 'name': 'Tomato_Half_Burnt', + 'embedded': { + 'Cooking_30630': { + 'hash': 30630, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Tomato_Half_Burnt_57360': { + 'hash': 57360, + 'name': 'Tomato_Half_Burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Tomato_Half_Cooked': { + 'hash': 57294, + 'name': 'Tomato_Half_Cooked', + 'embedded': { + 'Cooking_30288': { + 'hash': 30288, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Tomato_Half_Cooked_56956': { + 'hash': 56956, + 'name': 'Tomato_Half_Cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Tomato_Half_Ripe': { + 'hash': 56890, + 'name': 'Tomato_Half_Ripe', + 'embedded': { + 'Cooking_29946': { + 'hash': 29946, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Tomato_Half_Ripe_56552': { + 'hash': 56552, + 'name': 'Tomato_Half_Ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Tomato_Half_Unripe': { + 'hash': 56486, + 'name': 'Tomato_Half_Unripe', + 'embedded': { + 'Cooking_29604': { + 'hash': 29604, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Tomato_Half_Unripe_56148': { + 'hash': 56148, + 'name': 'Tomato_Half_Unripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'RaycastCrafter': { + 'hash': 2815374842, + 'name': 'RaycastCrafter' + } + } + } + } + }, + 'Tomato_Tree': { + 'hash': 56492, + 'name': 'Tomato_Tree', + 'embedded': { + 'Tomato_Tree_54408': { + 'hash': 54408, + 'name': 'Tomato_Tree', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Tomato_Tree_Growth': { + 'hash': 16358, + 'name': 'Tomato_Tree_Growth', + 'embedded': { + 'Tomato_Tree_Growth_33458': { + 'hash': 33458, + 'name': 'Tomato_Tree_Growth', + 'savables': { + 'GrowerComponent': { + 'hash': 3402094521, + 'name': 'GrowerComponent' + } + } + } + } + }, + 'Tomato_Tree_Separated': { + 'hash': 21548, + 'name': 'Tomato_Tree_Separated', + 'embedded': {} + }, + 'Tomato_Tree_Stage_1': { + 'hash': 2384, + 'name': 'Tomato_Tree_Stage_1', + 'embedded': { + 'Tomato_Tree_Stage_1_63514': { + 'hash': 63514, + 'name': 'Tomato_Tree_Stage_1', + 'savables': {} + } + } + }, + 'Tomato_Tree_Stage_2': { + 'hash': 2542, + 'name': 'Tomato_Tree_Stage_2', + 'embedded': { + 'Tomato_Tree_Stage_2_52164': { + 'hash': 52164, + 'name': 'Tomato_Tree_Stage_2', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Tomato_Tree_Stage_3': { + 'hash': 2892, + 'name': 'Tomato_Tree_Stage_3', + 'embedded': { + 'Tomato_Tree_Stage_3_23378': { + 'hash': 23378, + 'name': 'Tomato_Tree_Stage_3', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Torch': { + 'hash': 56698, + 'name': 'Torch', + 'embedded': { + 'Fire_30100': { + 'hash': 30100, + 'name': 'Fire', + 'savables': { + 'Fire': { + 'hash': 3457519710, + 'name': 'Fire' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Torch_30110': { + 'hash': 30110, + 'name': 'Torch', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Township_Bridge_Broken': { + 'hash': 8620, + 'name': 'Township_Bridge_Broken', + 'embedded': { + 'Township_Bridge_Broken_13660': { + 'hash': 13660, + 'name': 'Township_Bridge_Broken', + 'savables': {} + } + } + }, + 'Township_Bridge_Fixed': { + 'hash': 33334, + 'name': 'Township_Bridge_Fixed', + 'embedded': { + 'Township_Bridge_Fixed_13518': { + 'hash': 13518, + 'name': 'Township_Bridge_Fixed', + 'savables': {} + } + } + }, + 'Township_Bridge_Repair_Box': { + 'hash': 60674, + 'name': 'Township_Bridge_Repair_Box', + 'embedded': { + 'Cost_1_22852': { + 'hash': 22852, + 'name': 'Cost 1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Cost_2_22786': { + 'hash': 22786, + 'name': 'Cost 2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Cost_3_22772': { + 'hash': 22772, + 'name': 'Cost 3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_1_22642': { + 'hash': 22642, + 'name': 'Dock 1', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_2_22692': { + 'hash': 22692, + 'name': 'Dock 2', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_3_22698': { + 'hash': 22698, + 'name': 'Dock 3', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Township_Bridge_Broken_60312': { + 'hash': 60312, + 'name': 'Township Bridge Broken', + 'savables': {} + }, + 'Township_Bridge_Repair_Box_60672': { + 'hash': 60672, + 'name': 'Township Bridge Repair Box', + 'savables': { + 'RepairBox': { + 'hash': 3820454400, + 'name': 'RepairBox' + } + } + } + } + }, + 'Trade_Deck': { + 'hash': 30016, + 'name': 'Trade_Deck', + 'embedded': { + 'BuyCoinDisplay_3686': { + 'hash': 3686, + 'name': 'BuyCoinDisplay', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'BuyItemDisplay_3684': { + 'hash': 3684, + 'name': 'BuyItemDisplay', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'CoinTradeCounter_63408': { + 'hash': 63408, + 'name': 'CoinTradeCounter', + 'savables': { + 'ButtonCounter': { + 'hash': 3901697682, + 'name': 'ButtonCounter' + } + } + }, + 'Grab_14560': { + 'hash': 14560, + 'name': 'Grab', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grab_22452': { + 'hash': 22452, + 'name': 'Grab', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Handle_65280': { + 'hash': 65280, + 'name': 'Handle', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'ItemTradeCounters_404': { + 'hash': 404, + 'name': 'ItemTradeCounters', + 'savables': { + 'ButtonCounter': { + 'hash': 3901697682, + 'name': 'ButtonCounter' + } + } + }, + 'ProfitDock_52720': { + 'hash': 52720, + 'name': 'ProfitDock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'SellCoinDisplay_3680': { + 'hash': 3680, + 'name': 'SellCoinDisplay', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'SellItemDisplay_34750': { + 'hash': 34750, + 'name': 'SellItemDisplay', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'StockDock_50586': { + 'hash': 50586, + 'name': 'StockDock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'TaxDock_54312': { + 'hash': 54312, + 'name': 'TaxDock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'TaxLever_48782': { + 'hash': 48782, + 'name': 'TaxLever', + 'savables': { + 'Lever': { + 'hash': 1594932294, + 'name': 'Lever' + } + } + }, + 'TemporaryCoinDock_28320': { + 'hash': 28320, + 'name': 'TemporaryCoinDock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Trade_Deck_31038': { + 'hash': 31038, + 'name': 'Trade_Deck', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + }, + 'TaxManager': { + 'hash': 43510150, + 'name': 'TaxManager' + }, + 'TradeVendor': { + 'hash': 1645673210, + 'name': 'TradeVendor' + } + } + } + } + }, + 'TraderPrototype': { + 'hash': 28820, + 'name': 'TraderPrototype', + 'embedded': {} + }, + 'Training_Short_Sword_Blade_COLD': { + 'hash': 1850, + 'name': 'Training_Short_Sword_Blade_COLD', + 'embedded': { + 'Forged_Model_4044': { + 'hash': 4044, + 'name': 'Forged_Model', + 'savables': {} + }, + 'Heat_Point_Collection_11428': { + 'hash': 11428, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Training_Short_Sword_Blade_COLD_36330': { + 'hash': 36330, + 'name': 'Training_Short_Sword_Blade_COLD', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Training_Short_Sword_Blade_HOT': { + 'hash': 13220, + 'name': 'Training_Short_Sword_Blade_HOT', + 'embedded': { + 'Forged_Model_4044': { + 'hash': 4044, + 'name': 'Forged_Model', + 'savables': {} + }, + 'Heat_Point_Collection_11814': { + 'hash': 11814, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Training_Short_Sword_Blade_HOT_36330': { + 'hash': 36330, + 'name': 'Training_Short_Sword_Blade_HOT', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'ForgedPointCollection': { + 'hash': 2272630171, + 'name': 'ForgedPointCollection' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Tree': { + 'hash': 8860, + 'name': 'Tree', + 'embedded': { + 'Tree_54994': { + 'hash': 54994, + 'name': 'Tree', + 'savables': { + 'GrowthStageComponent': { + 'hash': 751359624, + 'name': 'GrowthStageComponent' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + }, + 'TreeDecay': { + 'hash': 2042199192, + 'name': 'TreeDecay' + }, + 'WoodcutTree': { + 'hash': 1098050191, + 'name': 'WoodcutTree' + } + } + } + } + }, + 'Tree_Button_Spawner': { + 'hash': 3934, + 'name': 'Tree_Button_Spawner', + 'embedded': {} + }, + 'Tree_Grower': { + 'hash': 25934, + 'name': 'Tree_Grower', + 'embedded': { + 'Tree_Grower_33458': { + 'hash': 33458, + 'name': 'Tree_Grower', + 'savables': { + 'TimeBasedStagedPrefab': { + 'hash': 1085701614, + 'name': 'TimeBasedStagedPrefab' + } + } + } + } + }, + 'Tree_Grown': { + 'hash': 30572, + 'name': 'Tree_Grown', + 'embedded': { + 'Tree_Grown_53296': { + 'hash': 53296, + 'name': 'Tree_Grown', + 'savables': {} + } + } + }, + 'Tree_Spawner_-_Any_Ash': { + 'hash': 50794, + 'name': 'Tree_Spawner_-_Any_Ash', + 'embedded': { + 'Tree_Spawner_-_Any_Ash_50788': { + 'hash': 50788, + 'name': 'Tree_Spawner_-_Any_Ash', + 'savables': { + 'TreeSpawner': { + 'hash': 3638500874, + 'name': 'TreeSpawner' + } + } + } + } + }, + 'Tree_Spawner_-_Any_Birch': { + 'hash': 570, + 'name': 'Tree_Spawner_-_Any_Birch', + 'embedded': { + 'Tree_Spawner_-_Any_Birch_21194': { + 'hash': 21194, + 'name': 'Tree_Spawner_-_Any_Birch', + 'savables': { + 'TreeSpawner': { + 'hash': 3638500874, + 'name': 'TreeSpawner' + } + } + } + } + }, + 'Tree_Spawner_-_Any_Oak': { + 'hash': 48358, + 'name': 'Tree_Spawner_-_Any_Oak', + 'embedded': { + 'Tree_Spawner_-_Any_Oak_21194': { + 'hash': 21194, + 'name': 'Tree_Spawner_-_Any_Oak', + 'savables': { + 'TreeSpawner': { + 'hash': 3638500874, + 'name': 'TreeSpawner' + } + } + } + } + }, + 'Tree_Spawner_-_Any_Redwood': { + 'hash': 546, + 'name': 'Tree_Spawner_-_Any_Redwood', + 'embedded': { + 'Tree_Spawner_-_Any_Redwood_21194': { + 'hash': 21194, + 'name': 'Tree_Spawner_-_Any_Redwood', + 'savables': { + 'TreeSpawner': { + 'hash': 3638500874, + 'name': 'TreeSpawner' + } + } + } + } + }, + 'Tree_Spawner_-_Any_Standard': { + 'hash': 15738, + 'name': 'Tree_Spawner_-_Any_Standard', + 'embedded': { + 'Tree_Spawner_-_Any_Standard_21194': { + 'hash': 21194, + 'name': 'Tree_Spawner_-_Any_Standard', + 'savables': { + 'TreeSpawner': { + 'hash': 3638500874, + 'name': 'TreeSpawner' + } + } + } + } + }, + 'Tree_Spawner_-_Any_TEMP_TEST': { + 'hash': 58970, + 'name': 'Tree_Spawner_-_Any_TEMP_TEST', + 'embedded': {} + }, + 'Tree_Spawner_-_Any_Walnut': { + 'hash': 34710, + 'name': 'Tree_Spawner_-_Any_Walnut', + 'embedded': { + 'Tree_Spawner_-_Any_Walnut_21194': { + 'hash': 21194, + 'name': 'Tree_Spawner_-_Any_Walnut', + 'savables': { + 'TreeSpawner': { + 'hash': 3638500874, + 'name': 'TreeSpawner' + } + } + } + } + }, + 'Tree_Spawner_-_Small_Standard': { + 'hash': 57286, + 'name': 'Tree_Spawner_-_Small_Standard', + 'embedded': { + 'Tree_Spawner_-_Small_Standard_21194': { + 'hash': 21194, + 'name': 'Tree_Spawner_-_Small_Standard', + 'savables': { + 'TreeSpawner': { + 'hash': 3638500874, + 'name': 'TreeSpawner' + } + } + } + } + }, + 'Tree_Young': { + 'hash': 30570, + 'name': 'Tree_Young', + 'embedded': { + 'Tree_Young_53362': { + 'hash': 53362, + 'name': 'Tree_Young', + 'savables': {} + } + } + }, + 'Trial_Spawner_MD-T1': { + 'hash': 62144, + 'name': 'Trial_Spawner_MD-T1', + 'embedded': { + 'Trial_Spawner_MD-T1_37438': { + 'hash': 37438, + 'name': 'Trial_Spawner_MD-T1', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + } + } + }, + 'Trial_Spawner_MD-T2': { + 'hash': 60910, + 'name': 'Trial_Spawner_MD-T2', + 'embedded': { + 'Trial_Spawner_MD-T2_37438': { + 'hash': 37438, + 'name': 'Trial_Spawner_MD-T2', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + } + } + }, + 'Trial_Spawner_MD-T3': { + 'hash': 52988, + 'name': 'Trial_Spawner_MD-T3', + 'embedded': { + 'Trial_Spawner_MD-T3_37438': { + 'hash': 37438, + 'name': 'Trial_Spawner_MD-T3', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + } + } + }, + 'Trial_Spawner_MD-W1': { + 'hash': 32210, + 'name': 'Trial_Spawner_MD-W1', + 'embedded': { + 'Trial_Spawner_MD-W1_52626': { + 'hash': 52626, + 'name': 'Trial_Spawner_MD-W1', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + } + } + }, + 'Trial_Spawner_MD-W2': { + 'hash': 50818, + 'name': 'Trial_Spawner_MD-W2', + 'embedded': { + 'Trial_Spawner_MD-W2_52626': { + 'hash': 52626, + 'name': 'Trial_Spawner_MD-W2', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + } + } + }, + 'Trial_Spawner_T-1': { + 'hash': 7744, + 'name': 'Trial_Spawner_T-1', + 'embedded': { + 'Trial_Spawner_T-1_37438': { + 'hash': 37438, + 'name': 'Trial_Spawner_T-1', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + } + } + }, + 'Trial_Spawner_T-2': { + 'hash': 40198, + 'name': 'Trial_Spawner_T-2', + 'embedded': { + 'Trial_Spawner_T-2_9898': { + 'hash': 9898, + 'name': 'Trial_Spawner_T-2', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + } + } + }, + 'Trial_Spawner_T-3': { + 'hash': 45096, + 'name': 'Trial_Spawner_T-3', + 'embedded': { + 'Trial_Spawner_T-3_37438': { + 'hash': 37438, + 'name': 'Trial_Spawner_T-3', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + } + } + }, + 'Trial_Spawner_T-3-Myth': { + 'hash': 49994, + 'name': 'Trial_Spawner_T-3-Myth', + 'embedded': { + 'Trial_Spawner_T-3-Myth_37438': { + 'hash': 37438, + 'name': 'Trial_Spawner_T-3-Myth', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + } + } + }, + 'Trial_Spawner_W-1': { + 'hash': 33084, + 'name': 'Trial_Spawner_W-1', + 'embedded': { + 'Trial_Spawner_W-1_52626': { + 'hash': 52626, + 'name': 'Trial_Spawner_W-1', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + } + } + }, + 'Trial_Spawner_W-2': { + 'hash': 18696, + 'name': 'Trial_Spawner_W-2', + 'embedded': { + 'Trial_Spawner_W-2_52626': { + 'hash': 52626, + 'name': 'Trial_Spawner_W-2', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + } + } + }, + 'Trial_Spawner_W-2-Crys': { + 'hash': 58286, + 'name': 'Trial_Spawner_W-2-Crys', + 'embedded': { + 'Trial_Spawner_W-2-Crys_52626': { + 'hash': 52626, + 'name': 'Trial_Spawner_W-2-Crys', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + } + } + }, + 'Trial_Spawner_W-3': { + 'hash': 42624, + 'name': 'Trial_Spawner_W-3', + 'embedded': { + 'Trial_Spawner_W-3_52626': { + 'hash': 52626, + 'name': 'Trial_Spawner_W-3', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + } + } + }, + 'Turabada': { + 'hash': 13804, + 'name': 'Turabada', + 'embedded': { + 'Arm_Collision_L_40528': { + 'hash': 40528, + 'name': 'Arm_Collision_L', + 'savables': {} + }, + 'Arm_Collision_R_42784': { + 'hash': 42784, + 'name': 'Arm_Collision_R', + 'savables': {} + }, + 'Explosion_58370': { + 'hash': 58370, + 'name': 'Explosion', + 'savables': {} + }, + 'Killed_Drops_63174': { + 'hash': 63174, + 'name': 'Killed_Drops', + 'savables': {} + }, + 'Target_Collector_10522': { + 'hash': 10522, + 'name': 'Target_Collector', + 'savables': {} + }, + 'Turabada_01_2540': { + 'hash': 2540, + 'name': 'Turabada_01', + 'savables': {} + }, + 'Turabada_13756': { + 'hash': 13756, + 'name': 'Turabada', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Turabada_AI_10656': { + 'hash': 10656, + 'name': 'Turabada_AI', + 'savables': { + 'LevelStatModifier': { + 'hash': 788405183, + 'name': 'LevelStatModifier' + } + } + } + } + }, + 'Turabada_Arm': { + 'hash': 15584, + 'name': 'Turabada_Arm', + 'embedded': { + 'Insert_HammerType_End_Cap_52192': { + 'hash': 52192, + 'name': 'Insert_HammerType_End_Cap', + 'savables': {} + }, + 'Turabada_Arm_15540': { + 'hash': 15540, + 'name': 'Turabada_Arm', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Turabada_Copper_Destroy_Variant': { + 'hash': 34850, + 'name': 'Turabada_Copper_Destroy_Variant', + 'embedded': { + 'Turabada_Copper_Destroy_Variant_37492': { + 'hash': 37492, + 'name': 'Turabada_Copper_Destroy_Variant', + 'savables': {} + } + } + }, + 'Turabada_Copper_Trial_Variant': { + 'hash': 14248, + 'name': 'Turabada_Copper_Trial_Variant', + 'embedded': { + 'Arm_Collision_L_40528': { + 'hash': 40528, + 'name': 'Arm_Collision_L', + 'savables': {} + }, + 'Arm_Collision_R_42784': { + 'hash': 42784, + 'name': 'Arm_Collision_R', + 'savables': {} + }, + 'Explosion_58370': { + 'hash': 58370, + 'name': 'Explosion', + 'savables': {} + }, + 'Killed_Drops_63174': { + 'hash': 63174, + 'name': 'Killed_Drops', + 'savables': {} + }, + 'Target_Collector_10522': { + 'hash': 10522, + 'name': 'Target_Collector', + 'savables': {} + }, + 'Turabada_01_2540': { + 'hash': 2540, + 'name': 'Turabada_01', + 'savables': {} + }, + 'Turabada_AI_10656': { + 'hash': 10656, + 'name': 'Turabada_AI', + 'savables': { + 'LevelStatModifier': { + 'hash': 788405183, + 'name': 'LevelStatModifier' + } + } + }, + 'Turabada_Copper_Trial_Variant_13756': { + 'hash': 13756, + 'name': 'Turabada_Copper_Trial_Variant', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Turabada_Copper_Variant': { + 'hash': 39056, + 'name': 'Turabada_Copper_Variant', + 'embedded': { + 'Arm_Collision_L_40528': { + 'hash': 40528, + 'name': 'Arm_Collision_L', + 'savables': {} + }, + 'Arm_Collision_R_42784': { + 'hash': 42784, + 'name': 'Arm_Collision_R', + 'savables': {} + }, + 'Explosion_58370': { + 'hash': 58370, + 'name': 'Explosion', + 'savables': {} + }, + 'Killed_Drops_63174': { + 'hash': 63174, + 'name': 'Killed_Drops', + 'savables': {} + }, + 'Target_Collector_10522': { + 'hash': 10522, + 'name': 'Target_Collector', + 'savables': {} + }, + 'Turabada_01_2540': { + 'hash': 2540, + 'name': 'Turabada_01', + 'savables': {} + }, + 'Turabada_AI_10656': { + 'hash': 10656, + 'name': 'Turabada_AI', + 'savables': { + 'LevelStatModifier': { + 'hash': 788405183, + 'name': 'LevelStatModifier' + } + } + }, + 'Turabada_Copper_Variant_13756': { + 'hash': 13756, + 'name': 'Turabada_Copper_Variant', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Turabada_Destroy': { + 'hash': 37508, + 'name': 'Turabada_Destroy', + 'embedded': { + 'Turabada_Destroy_37492': { + 'hash': 37492, + 'name': 'Turabada_Destroy', + 'savables': {} + } + } + }, + 'Turabada_Gold_Destroy_Variant': { + 'hash': 15310, + 'name': 'Turabada_Gold_Destroy_Variant', + 'embedded': { + 'Turabada_Gold_Destroy_Variant_37492': { + 'hash': 37492, + 'name': 'Turabada_Gold_Destroy_Variant', + 'savables': {} + } + } + }, + 'Turabada_Gold_Trial_Variant': { + 'hash': 15506, + 'name': 'Turabada_Gold_Trial_Variant', + 'embedded': { + 'Arm_Collision_L_40528': { + 'hash': 40528, + 'name': 'Arm_Collision_L', + 'savables': {} + }, + 'Arm_Collision_R_42784': { + 'hash': 42784, + 'name': 'Arm_Collision_R', + 'savables': {} + }, + 'Explosion_58370': { + 'hash': 58370, + 'name': 'Explosion', + 'savables': {} + }, + 'Killed_Drops_63174': { + 'hash': 63174, + 'name': 'Killed_Drops', + 'savables': {} + }, + 'Target_Collector_10522': { + 'hash': 10522, + 'name': 'Target_Collector', + 'savables': {} + }, + 'Turabada_01_2540': { + 'hash': 2540, + 'name': 'Turabada_01', + 'savables': {} + }, + 'Turabada_AI_10656': { + 'hash': 10656, + 'name': 'Turabada_AI', + 'savables': { + 'LevelStatModifier': { + 'hash': 788405183, + 'name': 'LevelStatModifier' + } + } + }, + 'Turabada_Gold_Trial_Variant_13756': { + 'hash': 13756, + 'name': 'Turabada_Gold_Trial_Variant', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Turabada_Gold_Variant': { + 'hash': 37176, + 'name': 'Turabada_Gold_Variant', + 'embedded': { + 'Arm_Collision_L_40528': { + 'hash': 40528, + 'name': 'Arm_Collision_L', + 'savables': {} + }, + 'Arm_Collision_R_42784': { + 'hash': 42784, + 'name': 'Arm_Collision_R', + 'savables': {} + }, + 'Explosion_58370': { + 'hash': 58370, + 'name': 'Explosion', + 'savables': {} + }, + 'Killed_Drops_63174': { + 'hash': 63174, + 'name': 'Killed_Drops', + 'savables': {} + }, + 'Target_Collector_10522': { + 'hash': 10522, + 'name': 'Target_Collector', + 'savables': {} + }, + 'Turabada_01_2540': { + 'hash': 2540, + 'name': 'Turabada_01', + 'savables': {} + }, + 'Turabada_AI_10656': { + 'hash': 10656, + 'name': 'Turabada_AI', + 'savables': { + 'LevelStatModifier': { + 'hash': 788405183, + 'name': 'LevelStatModifier' + } + } + }, + 'Turabada_Gold_Variant_13756': { + 'hash': 13756, + 'name': 'Turabada_Gold_Variant', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Turabada_Hub_Dynamic': { + 'hash': 48478, + 'name': 'Turabada_Hub_Dynamic', + 'embedded': { + 'Core_Spawn_16554': { + 'hash': 16554, + 'name': 'Core_Spawn', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + }, + 'Door_Blockage_Spawn_47616': { + 'hash': 47616, + 'name': 'Door_Blockage_Spawn', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + }, + 'Enemy_Spawn_30256': { + 'hash': 30256, + 'name': 'Enemy_Spawn', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + }, + 'Turabada_Hub_Dynamic_53304': { + 'hash': 53304, + 'name': 'Turabada_Hub_Dynamic', + 'savables': {} + } + } + }, + 'Turabada_Iron_Destroy_Variant': { + 'hash': 42690, + 'name': 'Turabada_Iron_Destroy_Variant', + 'embedded': { + 'Turabada_Iron_Destroy_Variant_37492': { + 'hash': 37492, + 'name': 'Turabada_Iron_Destroy_Variant', + 'savables': {} + } + } + }, + 'Turabada_Iron_Trial_Variant': { + 'hash': 16684, + 'name': 'Turabada_Iron_Trial_Variant', + 'embedded': { + 'Arm_Collision_L_40528': { + 'hash': 40528, + 'name': 'Arm_Collision_L', + 'savables': {} + }, + 'Arm_Collision_R_42784': { + 'hash': 42784, + 'name': 'Arm_Collision_R', + 'savables': {} + }, + 'Explosion_58370': { + 'hash': 58370, + 'name': 'Explosion', + 'savables': {} + }, + 'Killed_Drops_63174': { + 'hash': 63174, + 'name': 'Killed_Drops', + 'savables': {} + }, + 'Target_Collector_10522': { + 'hash': 10522, + 'name': 'Target_Collector', + 'savables': {} + }, + 'Turabada_01_2540': { + 'hash': 2540, + 'name': 'Turabada_01', + 'savables': {} + }, + 'Turabada_AI_10656': { + 'hash': 10656, + 'name': 'Turabada_AI', + 'savables': { + 'LevelStatModifier': { + 'hash': 788405183, + 'name': 'LevelStatModifier' + } + } + }, + 'Turabada_Iron_Trial_Variant_13756': { + 'hash': 13756, + 'name': 'Turabada_Iron_Trial_Variant', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Turabada_Iron_Variant': { + 'hash': 8298, + 'name': 'Turabada_Iron_Variant', + 'embedded': { + 'Arm_Collision_L_40528': { + 'hash': 40528, + 'name': 'Arm_Collision_L', + 'savables': {} + }, + 'Arm_Collision_R_42784': { + 'hash': 42784, + 'name': 'Arm_Collision_R', + 'savables': {} + }, + 'Explosion_58370': { + 'hash': 58370, + 'name': 'Explosion', + 'savables': {} + }, + 'Killed_Drops_63174': { + 'hash': 63174, + 'name': 'Killed_Drops', + 'savables': {} + }, + 'Target_Collector_10522': { + 'hash': 10522, + 'name': 'Target_Collector', + 'savables': {} + }, + 'Turabada_01_2540': { + 'hash': 2540, + 'name': 'Turabada_01', + 'savables': {} + }, + 'Turabada_AI_10656': { + 'hash': 10656, + 'name': 'Turabada_AI', + 'savables': { + 'LevelStatModifier': { + 'hash': 788405183, + 'name': 'LevelStatModifier' + } + } + }, + 'Turabada_Iron_Variant_13756': { + 'hash': 13756, + 'name': 'Turabada_Iron_Variant', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Turabada_Large_Destroy_Variant': { + 'hash': 63178, + 'name': 'Turabada_Large_Destroy_Variant', + 'embedded': { + 'Turabada_Large_Destroy_Variant_37492': { + 'hash': 37492, + 'name': 'Turabada_Large_Destroy_Variant', + 'savables': {} + } + } + }, + 'Turabada_Large_Trial_Variant': { + 'hash': 17814, + 'name': 'Turabada_Large_Trial_Variant', + 'embedded': { + 'Arm_Collision_L_40528': { + 'hash': 40528, + 'name': 'Arm_Collision_L', + 'savables': {} + }, + 'Arm_Collision_R_42784': { + 'hash': 42784, + 'name': 'Arm_Collision_R', + 'savables': {} + }, + 'Explosion_58370': { + 'hash': 58370, + 'name': 'Explosion', + 'savables': {} + }, + 'Killed_Drops_63174': { + 'hash': 63174, + 'name': 'Killed_Drops', + 'savables': {} + }, + 'Target_Collector_10522': { + 'hash': 10522, + 'name': 'Target_Collector', + 'savables': {} + }, + 'Turabada_01_2540': { + 'hash': 2540, + 'name': 'Turabada_01', + 'savables': {} + }, + 'Turabada_AI_10656': { + 'hash': 10656, + 'name': 'Turabada_AI', + 'savables': { + 'LevelStatModifier': { + 'hash': 788405183, + 'name': 'LevelStatModifier' + } + } + }, + 'Turabada_Large_Trial_Variant_13756': { + 'hash': 13756, + 'name': 'Turabada_Large_Trial_Variant', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Turabada_Large_Variant': { + 'hash': 41172, + 'name': 'Turabada_Large_Variant', + 'embedded': { + 'Arm_Collision_L_40528': { + 'hash': 40528, + 'name': 'Arm_Collision_L', + 'savables': {} + }, + 'Arm_Collision_R_42784': { + 'hash': 42784, + 'name': 'Arm_Collision_R', + 'savables': {} + }, + 'Explosion_58370': { + 'hash': 58370, + 'name': 'Explosion', + 'savables': {} + }, + 'Killed_Drops_63174': { + 'hash': 63174, + 'name': 'Killed_Drops', + 'savables': {} + }, + 'Target_Collector_10522': { + 'hash': 10522, + 'name': 'Target_Collector', + 'savables': {} + }, + 'Turabada_01_2540': { + 'hash': 2540, + 'name': 'Turabada_01', + 'savables': {} + }, + 'Turabada_AI_10656': { + 'hash': 10656, + 'name': 'Turabada_AI', + 'savables': { + 'LevelStatModifier': { + 'hash': 788405183, + 'name': 'LevelStatModifier' + } + } + }, + 'Turabada_Large_Variant_13756': { + 'hash': 13756, + 'name': 'Turabada_Large_Variant', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Turabada_Mythril_Destroy_Variant': { + 'hash': 45488, + 'name': 'Turabada_Mythril_Destroy_Variant', + 'embedded': { + 'Turabada_Mythril_Destroy_Variant_37492': { + 'hash': 37492, + 'name': 'Turabada_Mythril_Destroy_Variant', + 'savables': {} + } + } + }, + 'Turabada_Mythril_Trial_Variant': { + 'hash': 18722, + 'name': 'Turabada_Mythril_Trial_Variant', + 'embedded': { + 'Arm_Collision_L_40528': { + 'hash': 40528, + 'name': 'Arm_Collision_L', + 'savables': {} + }, + 'Arm_Collision_R_42784': { + 'hash': 42784, + 'name': 'Arm_Collision_R', + 'savables': {} + }, + 'Explosion_58370': { + 'hash': 58370, + 'name': 'Explosion', + 'savables': {} + }, + 'Killed_Drops_63174': { + 'hash': 63174, + 'name': 'Killed_Drops', + 'savables': {} + }, + 'Target_Collector_10522': { + 'hash': 10522, + 'name': 'Target_Collector', + 'savables': {} + }, + 'Turabada_01_2540': { + 'hash': 2540, + 'name': 'Turabada_01', + 'savables': {} + }, + 'Turabada_AI_10656': { + 'hash': 10656, + 'name': 'Turabada_AI', + 'savables': { + 'LevelStatModifier': { + 'hash': 788405183, + 'name': 'LevelStatModifier' + } + } + }, + 'Turabada_Mythril_Trial_Variant_13756': { + 'hash': 13756, + 'name': 'Turabada_Mythril_Trial_Variant', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Turabada_Mythril_Variant': { + 'hash': 62968, + 'name': 'Turabada_Mythril_Variant', + 'embedded': { + 'Arm_Collision_L_40528': { + 'hash': 40528, + 'name': 'Arm_Collision_L', + 'savables': {} + }, + 'Arm_Collision_R_42784': { + 'hash': 42784, + 'name': 'Arm_Collision_R', + 'savables': {} + }, + 'Explosion_58370': { + 'hash': 58370, + 'name': 'Explosion', + 'savables': {} + }, + 'Killed_Drops_63174': { + 'hash': 63174, + 'name': 'Killed_Drops', + 'savables': {} + }, + 'Target_Collector_10522': { + 'hash': 10522, + 'name': 'Target_Collector', + 'savables': {} + }, + 'Turabada_01_2540': { + 'hash': 2540, + 'name': 'Turabada_01', + 'savables': {} + }, + 'Turabada_AI_10656': { + 'hash': 10656, + 'name': 'Turabada_AI', + 'savables': { + 'LevelStatModifier': { + 'hash': 788405183, + 'name': 'LevelStatModifier' + } + } + }, + 'Turabada_Mythril_Variant_13756': { + 'hash': 13756, + 'name': 'Turabada_Mythril_Variant', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Turabada_Preview': { + 'hash': 49464, + 'name': 'Turabada_Preview', + 'embedded': {} + }, + 'Turabada_Shard_Core': { + 'hash': 7900, + 'name': 'Turabada_Shard_Core', + 'embedded': { + 'Chisel_Piece_58818': { + 'hash': 58818, + 'name': 'Chisel_Piece', + 'savables': {} + }, + 'Chisel_Piece_58820': { + 'hash': 58820, + 'name': 'Chisel_Piece', + 'savables': {} + }, + 'Chisel_Piece_58822': { + 'hash': 58822, + 'name': 'Chisel_Piece', + 'savables': {} + }, + 'Chisel_Piece_58824': { + 'hash': 58824, + 'name': 'Chisel_Piece', + 'savables': {} + }, + 'Chisel_Piece_58826': { + 'hash': 58826, + 'name': 'Chisel_Piece', + 'savables': {} + }, + 'Chisel_Piece_58828': { + 'hash': 58828, + 'name': 'Chisel_Piece', + 'savables': {} + }, + 'Chisel_Piece_58830': { + 'hash': 58830, + 'name': 'Chisel_Piece', + 'savables': {} + }, + 'Chisel_Piece_58832': { + 'hash': 58832, + 'name': 'Chisel_Piece', + 'savables': {} + }, + 'Chisel_Piece_58834': { + 'hash': 58834, + 'name': 'Chisel_Piece', + 'savables': {} + }, + 'Chisel_Piece_58836': { + 'hash': 58836, + 'name': 'Chisel_Piece', + 'savables': {} + }, + 'Chisel_Piece_58838': { + 'hash': 58838, + 'name': 'Chisel_Piece', + 'savables': {} + }, + 'Chisel_Piece_58840': { + 'hash': 58840, + 'name': 'Chisel_Piece', + 'savables': {} + }, + 'Chisel_Piece_58842': { + 'hash': 58842, + 'name': 'Chisel_Piece', + 'savables': {} + }, + 'Explosion_44800': { + 'hash': 44800, + 'name': 'Explosion', + 'savables': {} + }, + 'Turabada_Shard_Core_7884': { + 'hash': 7884, + 'name': 'Turabada_Shard_Core', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Turabada_Short_Destroy_Variant': { + 'hash': 48002, + 'name': 'Turabada_Short_Destroy_Variant', + 'embedded': { + 'Turabada_Short_Destroy_Variant_37492': { + 'hash': 37492, + 'name': 'Turabada_Short_Destroy_Variant', + 'savables': {} + } + } + }, + 'Turabada_Short_Trial_Variant': { + 'hash': 19936, + 'name': 'Turabada_Short_Trial_Variant', + 'embedded': { + 'Arm_Collision_L_40528': { + 'hash': 40528, + 'name': 'Arm_Collision_L', + 'savables': {} + }, + 'Arm_Collision_R_42784': { + 'hash': 42784, + 'name': 'Arm_Collision_R', + 'savables': {} + }, + 'Explosion_58370': { + 'hash': 58370, + 'name': 'Explosion', + 'savables': {} + }, + 'Killed_Drops_63174': { + 'hash': 63174, + 'name': 'Killed_Drops', + 'savables': {} + }, + 'Target_Collector_10522': { + 'hash': 10522, + 'name': 'Target_Collector', + 'savables': {} + }, + 'Turabada_01_2540': { + 'hash': 2540, + 'name': 'Turabada_01', + 'savables': {} + }, + 'Turabada_AI_10656': { + 'hash': 10656, + 'name': 'Turabada_AI', + 'savables': { + 'LevelStatModifier': { + 'hash': 788405183, + 'name': 'LevelStatModifier' + } + } + }, + 'Turabada_Short_Trial_Variant_13756': { + 'hash': 13756, + 'name': 'Turabada_Short_Trial_Variant', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Turabada_Short_Variant': { + 'hash': 63878, + 'name': 'Turabada_Short_Variant', + 'embedded': { + 'Arm_Collision_L_40528': { + 'hash': 40528, + 'name': 'Arm_Collision_L', + 'savables': {} + }, + 'Arm_Collision_R_42784': { + 'hash': 42784, + 'name': 'Arm_Collision_R', + 'savables': {} + }, + 'Explosion_58370': { + 'hash': 58370, + 'name': 'Explosion', + 'savables': {} + }, + 'Killed_Drops_63174': { + 'hash': 63174, + 'name': 'Killed_Drops', + 'savables': {} + }, + 'Target_Collector_10522': { + 'hash': 10522, + 'name': 'Target_Collector', + 'savables': {} + }, + 'Turabada_01_2540': { + 'hash': 2540, + 'name': 'Turabada_01', + 'savables': {} + }, + 'Turabada_AI_10656': { + 'hash': 10656, + 'name': 'Turabada_AI', + 'savables': { + 'LevelStatModifier': { + 'hash': 788405183, + 'name': 'LevelStatModifier' + } + } + }, + 'Turabada_Short_Variant_13756': { + 'hash': 13756, + 'name': 'Turabada_Short_Variant', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Turabada_Silver_Destroy_Variant': { + 'hash': 1960, + 'name': 'Turabada_Silver_Destroy_Variant', + 'embedded': { + 'Turabada_Silver_Destroy_Variant_37492': { + 'hash': 37492, + 'name': 'Turabada_Silver_Destroy_Variant', + 'savables': {} + } + } + }, + 'Turabada_Silver_Trial_Variant': { + 'hash': 20844, + 'name': 'Turabada_Silver_Trial_Variant', + 'embedded': { + 'Arm_Collision_L_40528': { + 'hash': 40528, + 'name': 'Arm_Collision_L', + 'savables': {} + }, + 'Arm_Collision_R_42784': { + 'hash': 42784, + 'name': 'Arm_Collision_R', + 'savables': {} + }, + 'Explosion_58370': { + 'hash': 58370, + 'name': 'Explosion', + 'savables': {} + }, + 'Killed_Drops_63174': { + 'hash': 63174, + 'name': 'Killed_Drops', + 'savables': {} + }, + 'Target_Collector_10522': { + 'hash': 10522, + 'name': 'Target_Collector', + 'savables': {} + }, + 'Turabada_01_2540': { + 'hash': 2540, + 'name': 'Turabada_01', + 'savables': {} + }, + 'Turabada_AI_10656': { + 'hash': 10656, + 'name': 'Turabada_AI', + 'savables': { + 'LevelStatModifier': { + 'hash': 788405183, + 'name': 'LevelStatModifier' + } + } + }, + 'Turabada_Silver_Trial_Variant_13756': { + 'hash': 13756, + 'name': 'Turabada_Silver_Trial_Variant', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Turabada_Silver_Variant': { + 'hash': 45716, + 'name': 'Turabada_Silver_Variant', + 'embedded': { + 'Arm_Collision_L_40528': { + 'hash': 40528, + 'name': 'Arm_Collision_L', + 'savables': {} + }, + 'Arm_Collision_R_42784': { + 'hash': 42784, + 'name': 'Arm_Collision_R', + 'savables': {} + }, + 'Explosion_58370': { + 'hash': 58370, + 'name': 'Explosion', + 'savables': {} + }, + 'Killed_Drops_63174': { + 'hash': 63174, + 'name': 'Killed_Drops', + 'savables': {} + }, + 'Target_Collector_10522': { + 'hash': 10522, + 'name': 'Target_Collector', + 'savables': {} + }, + 'Turabada_01_2540': { + 'hash': 2540, + 'name': 'Turabada_01', + 'savables': {} + }, + 'Turabada_AI_10656': { + 'hash': 10656, + 'name': 'Turabada_AI', + 'savables': { + 'LevelStatModifier': { + 'hash': 788405183, + 'name': 'LevelStatModifier' + } + } + }, + 'Turabada_Silver_Variant_13756': { + 'hash': 13756, + 'name': 'Turabada_Silver_Variant', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Turabada_Spawner_Automatic': { + 'hash': 51652, + 'name': 'Turabada_Spawner_Automatic', + 'embedded': { + 'Turabada_Spawner_Automatic_26726': { + 'hash': 26726, + 'name': 'Turabada_Spawner_Automatic', + 'savables': {} + }, + 'caveRock_34072': { + 'hash': 34072, + 'name': 'caveRock', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Turabada_Spawner_Reactive': { + 'hash': 27188, + 'name': 'Turabada_Spawner_Reactive', + 'embedded': { + 'Reactive_AI_17314': { + 'hash': 17314, + 'name': 'Reactive_AI', + 'savables': {} + }, + 'Turabada_Spawner_Reactive_26726': { + 'hash': 26726, + 'name': 'Turabada_Spawner_Reactive', + 'savables': {} + }, + 'caveRock_34072': { + 'hash': 34072, + 'name': 'caveRock', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Turabada_Trial_Variant': { + 'hash': 21882, + 'name': 'Turabada_Trial_Variant', + 'embedded': { + 'Arm_Collision_L_40528': { + 'hash': 40528, + 'name': 'Arm_Collision_L', + 'savables': {} + }, + 'Arm_Collision_R_42784': { + 'hash': 42784, + 'name': 'Arm_Collision_R', + 'savables': {} + }, + 'Explosion_58370': { + 'hash': 58370, + 'name': 'Explosion', + 'savables': {} + }, + 'Killed_Drops_63174': { + 'hash': 63174, + 'name': 'Killed_Drops', + 'savables': {} + }, + 'Target_Collector_10522': { + 'hash': 10522, + 'name': 'Target_Collector', + 'savables': {} + }, + 'Turabada_01_2540': { + 'hash': 2540, + 'name': 'Turabada_01', + 'savables': {} + }, + 'Turabada_AI_10656': { + 'hash': 10656, + 'name': 'Turabada_AI', + 'savables': { + 'LevelStatModifier': { + 'hash': 788405183, + 'name': 'LevelStatModifier' + } + } + }, + 'Turabada_Trial_Variant_13756': { + 'hash': 13756, + 'name': 'Turabada_Trial_Variant', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'UnplacedMetalWallHook': { + 'hash': 18972, + 'name': 'UnplacedMetalWallHook', + 'embedded': { + 'Heat_Point_Collection_11020': { + 'hash': 11020, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'UnplacedMetalWallHook_26498': { + 'hash': 26498, + 'name': 'UnplacedMetalWallHook', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'RaycastCrafter': { + 'hash': 2815374842, + 'name': 'RaycastCrafter' + } + } + } + } + }, + 'VR_Player_Character_New': { + 'hash': 49582, + 'name': 'VR_Player_Character_New', + 'embedded': {} + }, + 'Vacuum': { + 'hash': 8586, + 'name': 'Vacuum', + 'embedded': { + 'Dock_42390': { + 'hash': 42390, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Vacuum_7480': { + 'hash': 7480, + 'name': 'Vacuum', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Vegetable_Ragu_Recipe_Burnt_Stew': { + 'hash': 58092, + 'name': 'Vegetable_Ragu_Recipe_Burnt_Stew', + 'embedded': {} + }, + 'Vegetable_Ragu_Recipe_Cooked_Stew': { + 'hash': 58074, + 'name': 'Vegetable_Ragu_Recipe_Cooked_Stew', + 'embedded': {} + }, + 'Vegetable_Ragu_Recipe_Raw_Stew': { + 'hash': 58050, + 'name': 'Vegetable_Ragu_Recipe_Raw_Stew', + 'embedded': {} + }, + 'Vine_Attack_Fern': { + 'hash': 24402, + 'name': 'Vine_Attack_Fern', + 'embedded': { + 'Death_Fern_AI_29794': { + 'hash': 29794, + 'name': 'Death_Fern_AI', + 'savables': {} + }, + 'Emit_Gas_Spawner_16984': { + 'hash': 16984, + 'name': 'Emit_Gas_Spawner', + 'savables': {} + }, + 'Erupt_Area_19858': { + 'hash': 19858, + 'name': 'Erupt_Area', + 'savables': {} + }, + 'Impactor_63610': { + 'hash': 63610, + 'name': 'Impactor', + 'savables': {} + }, + 'Impactor_65072': { + 'hash': 65072, + 'name': 'Impactor', + 'savables': {} + }, + 'Impactor_65078': { + 'hash': 65078, + 'name': 'Impactor', + 'savables': {} + }, + 'Mesh_15308': { + 'hash': 15308, + 'name': 'Mesh', + 'savables': {} + }, + 'Vine_Attack_Fern_37626': { + 'hash': 37626, + 'name': 'Vine_Attack_Fern', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Vine_Boulder_01': { + 'hash': 31088, + 'name': 'Vine_Boulder_01', + 'embedded': { + 'Directional_Encounter_63404': { + 'hash': 63404, + 'name': 'Directional_Encounter', + 'savables': { + 'DirectionalBoundsSurface': { + 'hash': 1962842866, + 'name': 'DirectionalBoundsSurface' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + }, + 'Vine_Boulder_01_62528': { + 'hash': 62528, + 'name': 'Vine_Boulder_01', + 'savables': {} + } + } + }, + 'Vision_Recipe_Burnt_Stew': { + 'hash': 58138, + 'name': 'Vision_Recipe_Burnt_Stew', + 'embedded': {} + }, + 'Vision_Recipe_Cooked_Stew': { + 'hash': 58120, + 'name': 'Vision_Recipe_Cooked_Stew', + 'embedded': {} + }, + 'Vision_Recipe_Raw_Stew': { + 'hash': 58162, + 'name': 'Vision_Recipe_Raw_Stew', + 'embedded': {} + }, + 'Wakizashi': { + 'hash': 29856, + 'name': 'Wakizashi', + 'embedded': { + 'Wakizashi_36330': { + 'hash': 36330, + 'name': 'Wakizashi', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'Enchantable': { + 'hash': 4134534481, + 'name': 'Enchantable' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Walk_Air': { + 'hash': 50936, + 'name': 'Walk_Air', + 'embedded': {} + }, + 'Wall_Shelf': { + 'hash': 15548, + 'name': 'Wall_Shelf', + 'embedded': { + 'Dock_62060': { + 'hash': 62060, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62062': { + 'hash': 62062, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62064': { + 'hash': 62064, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_62066': { + 'hash': 62066, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Wall_Shelf_62464': { + 'hash': 62464, + 'name': 'Wall_Shelf', + 'savables': {} + } + } + }, + 'Wall_Street_Post': { + 'hash': 50078, + 'name': 'Wall_Street_Post', + 'embedded': { + 'Sign_Body_13458': { + 'hash': 13458, + 'name': 'Sign_Body', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Visual_1_44280': { + 'hash': 44280, + 'name': 'Visual_1', + 'savables': { + 'MeshPlacement': { + 'hash': 2169673426, + 'name': 'MeshPlacement' + } + } + }, + 'Visual_2_38710': { + 'hash': 38710, + 'name': 'Visual_2', + 'savables': { + 'MeshPlacement': { + 'hash': 2169673426, + 'name': 'MeshPlacement' + } + } + }, + 'Visual_3_23608': { + 'hash': 23608, + 'name': 'Visual_3', + 'savables': { + 'MeshPlacement': { + 'hash': 2169673426, + 'name': 'MeshPlacement' + } + } + }, + 'Visual_4_16452': { + 'hash': 16452, + 'name': 'Visual_4', + 'savables': { + 'MeshPlacement': { + 'hash': 2169673426, + 'name': 'MeshPlacement' + } + } + }, + 'Wall_Street_Post_16266': { + 'hash': 16266, + 'name': 'Wall_Street_Post', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + } + } + }, + 'Wall_Torch_Holder': { + 'hash': 3786, + 'name': 'Wall_Torch_Holder', + 'embedded': { + 'Torch_Dock_5626': { + 'hash': 5626, + 'name': 'Torch_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Wall_Torch_Holder_54416': { + 'hash': 54416, + 'name': 'Wall_Torch_Holder', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + } + } + }, + 'Wall_Torch_Holder_Puzzle': { + 'hash': 30196, + 'name': 'Wall_Torch_Holder_Puzzle', + 'embedded': { + 'Extra_Logic_1_49636': { + 'hash': 49636, + 'name': 'Extra_Logic_1', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + } + } + }, + 'Torch_Dock_5626': { + 'hash': 5626, + 'name': 'Torch_Dock', + 'savables': { + 'LogicIntSender': { + 'hash': 2880587164, + 'name': 'LogicIntSender' + }, + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + }, + 'PlaceItemPuzzleLogic': { + 'hash': 1001395212, + 'name': 'PlaceItemPuzzleLogic' + } + } + }, + 'Wall_Torch_Holder_Puzzle_30194': { + 'hash': 30194, + 'name': 'Wall_Torch_Holder_Puzzle', + 'savables': {} + } + } + }, + 'Walnut_Gotera_Bomb_Dart': { + 'hash': 39716, + 'name': 'Walnut_Gotera_Bomb_Dart', + 'embedded': { + 'Dart_62940': { + 'hash': 62940, + 'name': 'Dart', + 'savables': {} + }, + 'Walnut_Gotera_Bomb_Dart_3092': { + 'hash': 3092, + 'name': 'Walnut_Gotera_Bomb_Dart', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Walnut_Tree_Growth': { + 'hash': 48268, + 'name': 'Walnut_Tree_Growth', + 'embedded': { + 'Walnut_Tree_Growth_33458': { + 'hash': 33458, + 'name': 'Walnut_Tree_Growth', + 'savables': { + 'GrowerComponent': { + 'hash': 3402094521, + 'name': 'GrowerComponent' + } + } + } + } + }, + 'Walnut_Tree_Seed': { + 'hash': 44172, + 'name': 'Walnut_Tree_Seed', + 'embedded': { + 'Walnut_Tree_Seed_35258': { + 'hash': 35258, + 'name': 'Walnut_Tree_Seed', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'RaycastCrafter': { + 'hash': 2815374842, + 'name': 'RaycastCrafter' + } + } + } + } + }, + 'Walnut_Tree_Stage_1': { + 'hash': 26568, + 'name': 'Walnut_Tree_Stage_1', + 'embedded': { + 'Walnut_Tree_Stage_1_63514': { + 'hash': 63514, + 'name': 'Walnut_Tree_Stage_1', + 'savables': {} + } + } + }, + 'WarHammer': { + 'hash': 9630, + 'name': 'WarHammer', + 'embedded': { + 'Heat_Point_Collection_1720': { + 'hash': 1720, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Insert_HammerType_End_Cap_52192': { + 'hash': 52192, + 'name': 'Insert_HammerType_End_Cap', + 'savables': {} + }, + 'WarHammer_42978': { + 'hash': 42978, + 'name': 'WarHammer', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Water_Well_Dynamic': { + 'hash': 14364, + 'name': 'Water_Well_Dynamic', + 'embedded': {} + }, + 'Water_Well_Tunnel_Dynamic': { + 'hash': 12356, + 'name': 'Water_Well_Tunnel_Dynamic', + 'embedded': { + 'Dock_2780': { + 'hash': 2780, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60224': { + 'hash': 60224, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60226': { + 'hash': 60226, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60228': { + 'hash': 60228, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60234': { + 'hash': 60234, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60236': { + 'hash': 60236, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60238': { + 'hash': 60238, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60244': { + 'hash': 60244, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_60246': { + 'hash': 60246, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Water_Well_Tunnel_Dynamic_14816': { + 'hash': 14816, + 'name': 'Water_Well_Tunnel_Dynamic', + 'savables': {} + } + } + }, + 'Weapon_Rack_Wall': { + 'hash': 13062, + 'name': 'Weapon_Rack_Wall', + 'embedded': { + 'ToolDock_(1)_26316': { + 'hash': 26316, + 'name': 'ToolDock_(1)', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'ToolDock_(2)_26308': { + 'hash': 26308, + 'name': 'ToolDock_(2)', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'ToolDock_(3)_26304': { + 'hash': 26304, + 'name': 'ToolDock_(3)', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'ToolDock_5626': { + 'hash': 5626, + 'name': 'ToolDock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Weapon_Rack_Wall_9260': { + 'hash': 9260, + 'name': 'Weapon_Rack_Wall', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + } + } + }, + 'Wedge_Training': { + 'hash': 53570, + 'name': 'Wedge_Training', + 'embedded': { + 'Wedge_Training_53566': { + 'hash': 53566, + 'name': 'Wedge_Training', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + } + } + }, + 'Weight_Gauge': { + 'hash': 48306, + 'name': 'Weight_Gauge', + 'embedded': { + 'Weight_Gauge_48288': { + 'hash': 48288, + 'name': 'Weight_Gauge', + 'savables': {} + } + } + }, + 'WheelBridge': { + 'hash': 7252, + 'name': 'WheelBridge', + 'embedded': { + 'Grip_(1)_54050': { + 'hash': 54050, + 'name': 'Grip_(1)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(2)_54614': { + 'hash': 54614, + 'name': 'Grip_(2)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(3)_56370': { + 'hash': 56370, + 'name': 'Grip_(3)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(4)_53470': { + 'hash': 53470, + 'name': 'Grip_(4)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(5)_19654': { + 'hash': 19654, + 'name': 'Grip_(5)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_56728': { + 'hash': 56728, + 'name': 'Grip', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'WheelBridge_43884': { + 'hash': 43884, + 'name': 'WheelBridge', + 'savables': { + 'LogicFloatReceiver': { + 'hash': 3188272159, + 'name': 'LogicFloatReceiver' + }, + 'LogicFloatSender': { + 'hash': 2120963769, + 'name': 'LogicFloatSender' + }, + 'RotatePickup': { + 'hash': 2498617949, + 'name': 'RotatePickup' + } + } + }, + 'wheel_origin_43868': { + 'hash': 43868, + 'name': 'wheel_origin', + 'savables': { + 'WheelGrab': { + 'hash': 320224849, + 'name': 'WheelGrab' + } + } + } + } + }, + 'WheelPuzzle': { + 'hash': 52364, + 'name': 'WheelPuzzle', + 'embedded': { + 'Grip_(1)_54050': { + 'hash': 54050, + 'name': 'Grip_(1)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(2)_54614': { + 'hash': 54614, + 'name': 'Grip_(2)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(3)_56370': { + 'hash': 56370, + 'name': 'Grip_(3)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(4)_53470': { + 'hash': 53470, + 'name': 'Grip_(4)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_(5)_19654': { + 'hash': 19654, + 'name': 'Grip_(5)', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Grip_56728': { + 'hash': 56728, + 'name': 'Grip', + 'savables': { + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'WheelPuzzle_43884': { + 'hash': 43884, + 'name': 'WheelPuzzle', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'LogicFloatReceiver': { + 'hash': 3188272159, + 'name': 'LogicFloatReceiver' + }, + 'LogicFloatSender': { + 'hash': 2120963769, + 'name': 'LogicFloatSender' + }, + 'RotatePickup': { + 'hash': 2498617949, + 'name': 'RotatePickup' + } + } + }, + 'wheel_origin_43868': { + 'hash': 43868, + 'name': 'wheel_origin', + 'savables': { + 'WheelGrab': { + 'hash': 320224849, + 'name': 'WheelGrab' + } + } + } + } + }, + 'WheelPuzzleOLD': { + 'hash': 61964, + 'name': 'WheelPuzzleOLD', + 'embedded': {} + }, + 'White_Gold_Ingot': { + 'hash': 13158, + 'name': 'White_Gold_Ingot', + 'embedded': { + 'Heat_Point_Collection_13798': { + 'hash': 13798, + 'name': 'Heat_Point_Collection', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'White_Gold_Ingot_32738': { + 'hash': 32738, + 'name': 'White_Gold_Ingot', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Woodcut_Ash_LeafClump_Base': { + 'hash': 28312, + 'name': 'Woodcut_Ash_LeafClump_Base', + 'embedded': { + 'Woodcut_Ash_LeafClump_Base_28328': { + 'hash': 28328, + 'name': 'Woodcut_Ash_LeafClump_Base', + 'savables': {} + } + } + }, + 'Woodcut_Ash_LeafClump_C1C1': { + 'hash': 44892, + 'name': 'Woodcut_Ash_LeafClump_C1C1', + 'embedded': { + 'Woodcut_Ash_LeafClump_C1C1_44890': { + 'hash': 44890, + 'name': 'Woodcut_Ash_LeafClump_C1C1', + 'savables': {} + } + } + }, + 'Woodcut_Ash_LeafClump_C1C2': { + 'hash': 34638, + 'name': 'Woodcut_Ash_LeafClump_C1C2', + 'embedded': { + 'Woodcut_Ash_LeafClump_C1C2_34636': { + 'hash': 34636, + 'name': 'Woodcut_Ash_LeafClump_C1C2', + 'savables': {} + } + } + }, + 'Woodcut_Ash_LeafClump_C1C2_E': { + 'hash': 47502, + 'name': 'Woodcut_Ash_LeafClump_C1C2_E', + 'embedded': { + 'Woodcut_Ash_LeafClump_C1C2_E_47500': { + 'hash': 47500, + 'name': 'Woodcut_Ash_LeafClump_C1C2_E', + 'savables': {} + } + } + }, + 'Woodcut_Ash_LeafClump_C1_E': { + 'hash': 47458, + 'name': 'Woodcut_Ash_LeafClump_C1_E', + 'embedded': { + 'Woodcut_Ash_LeafClump_C1_E_47456': { + 'hash': 47456, + 'name': 'Woodcut_Ash_LeafClump_C1_E', + 'savables': {} + } + } + }, + 'Woodcut_Ash_LeafClump_C1_E_1': { + 'hash': 14074, + 'name': 'Woodcut_Ash_LeafClump_C1_E_1', + 'embedded': { + 'Woodcut_Ash_LeafClump_C1_E_1_14072': { + 'hash': 14072, + 'name': 'Woodcut_Ash_LeafClump_C1_E_1', + 'savables': {} + } + } + }, + 'Woodcut_Ash_LeafClump_C1_E_2': { + 'hash': 40722, + 'name': 'Woodcut_Ash_LeafClump_C1_E_2', + 'embedded': { + 'Woodcut_Ash_LeafClump_C1_E_2_40720': { + 'hash': 40720, + 'name': 'Woodcut_Ash_LeafClump_C1_E_2', + 'savables': {} + } + } + }, + 'Woodcut_Ash_LeafClump_C2C2': { + 'hash': 44908, + 'name': 'Woodcut_Ash_LeafClump_C2C2', + 'embedded': { + 'Woodcut_Ash_LeafClump_C2C2_44906': { + 'hash': 44906, + 'name': 'Woodcut_Ash_LeafClump_C2C2', + 'savables': {} + } + } + }, + 'Woodcut_Ash_LeafClump_C2C3': { + 'hash': 9426, + 'name': 'Woodcut_Ash_LeafClump_C2C3', + 'embedded': { + 'Woodcut_Ash_LeafClump_C2C3_9424': { + 'hash': 9424, + 'name': 'Woodcut_Ash_LeafClump_C2C3', + 'savables': {} + } + } + }, + 'Woodcut_Ash_LeafClump_C2C3_E': { + 'hash': 57802, + 'name': 'Woodcut_Ash_LeafClump_C2C3_E', + 'embedded': { + 'Woodcut_Ash_LeafClump_C2C3_E_57800': { + 'hash': 57800, + 'name': 'Woodcut_Ash_LeafClump_C2C3_E', + 'savables': {} + } + } + }, + 'Woodcut_Ash_LeafClump_C2_E': { + 'hash': 29976, + 'name': 'Woodcut_Ash_LeafClump_C2_E', + 'embedded': { + 'Woodcut_Ash_LeafClump_C2_E_29974': { + 'hash': 29974, + 'name': 'Woodcut_Ash_LeafClump_C2_E', + 'savables': {} + } + } + }, + 'Woodcut_Ash_LeafClump_C2_E_1': { + 'hash': 24422, + 'name': 'Woodcut_Ash_LeafClump_C2_E_1', + 'embedded': { + 'Woodcut_Ash_LeafClump_C2_E_1_24420': { + 'hash': 24420, + 'name': 'Woodcut_Ash_LeafClump_C2_E_1', + 'savables': {} + } + } + }, + 'Woodcut_Ash_LeafClump_C3C3': { + 'hash': 10682, + 'name': 'Woodcut_Ash_LeafClump_C3C3', + 'embedded': { + 'Woodcut_Ash_LeafClump_C3C3_10680': { + 'hash': 10680, + 'name': 'Woodcut_Ash_LeafClump_C3C3', + 'savables': {} + } + } + }, + 'Woodcut_Ash_LeafClump_C3_E': { + 'hash': 57250, + 'name': 'Woodcut_Ash_LeafClump_C3_E', + 'embedded': { + 'Woodcut_Ash_LeafClump_C3_E_57248': { + 'hash': 57248, + 'name': 'Woodcut_Ash_LeafClump_C3_E', + 'savables': {} + } + } + }, + 'Woodcut_Ash_Seed_Spawner_Attachment': { + 'hash': 16054, + 'name': 'Woodcut_Ash_Seed_Spawner_Attachment', + 'embedded': { + 'Woodcut_Ash_Seed_Spawner_Attachment_36402': { + 'hash': 36402, + 'name': 'Woodcut_Ash_Seed_Spawner_Attachment', + 'savables': {} + } + } + }, + 'Woodcut_B0_B0': { + 'hash': 11470, + 'name': 'Woodcut_B0_B0', + 'embedded': { + 'Top_8056': { + 'hash': 8056, + 'name': 'Top_8056', + 'savables': {} + } + } + }, + 'Woodcut_B0_B0_S-30': { + 'hash': 19224, + 'name': 'Woodcut_B0_B0_S-30', + 'embedded': { + 'Stick_53710': { + 'hash': 53710, + 'name': 'Stick', + 'savables': {} + }, + 'Top_53706': { + 'hash': 53706, + 'name': 'Top', + 'savables': {} + }, + 'Woodcut_B0_B0_S-30_35608': { + 'hash': 35608, + 'name': 'Woodcut_B0_B0_S-30', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_B0_B0_S15': { + 'hash': 35014, + 'name': 'Woodcut_B0_B0_S15', + 'embedded': { + 'Top_53706': { + 'hash': 53706, + 'name': 'Top_53706', + 'savables': {} + }, + 'Stick_53710': { + 'hash': 53710, + 'name': 'Stick_53710', + 'savables': {} + } + } + }, + 'Woodcut_B0_B0_S30': { + 'hash': 36844, + 'name': 'Woodcut_B0_B0_S30', + 'embedded': { + 'Stick_53710': { + 'hash': 53710, + 'name': 'Stick', + 'savables': {} + }, + 'Top_53706': { + 'hash': 53706, + 'name': 'Top', + 'savables': {} + }, + 'Woodcut_B0_B0_S30_35608': { + 'hash': 35608, + 'name': 'Woodcut_B0_B0_S30', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_B0_B0_S30_S30': { + 'hash': 6224, + 'name': 'Woodcut_B0_B0_S30_S30', + 'embedded': { + 'Branch_1_20342': { + 'hash': 20342, + 'name': 'Branch_1', + 'savables': {} + }, + 'Stick_1_20338': { + 'hash': 20338, + 'name': 'Stick_1', + 'savables': {} + }, + 'Stick_2_55820': { + 'hash': 55820, + 'name': 'Stick_2', + 'savables': {} + }, + 'Woodcut_B0_B0_S30_S30_6218': { + 'hash': 6218, + 'name': 'Woodcut_B0_B0_S30_S30', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_B0_B15_B30': { + 'hash': 35020, + 'name': 'Woodcut_B0_B15_B30', + 'embedded': { + 'Branch_1_20342': { + 'hash': 20342, + 'name': 'Branch_1_20342', + 'savables': {} + }, + 'Branch_2_20338': { + 'hash': 20338, + 'name': 'Branch_2_20338', + 'savables': {} + } + } + }, + 'Woodcut_B0_B30_S30': { + 'hash': 51486, + 'name': 'Woodcut_B0_B30_S30', + 'embedded': { + 'Stick_51478': { + 'hash': 51478, + 'name': 'Stick', + 'savables': {} + }, + 'Top_51476': { + 'hash': 51476, + 'name': 'Top', + 'savables': {} + }, + 'Woodcut_B0_B30_S30_51474': { + 'hash': 51474, + 'name': 'Woodcut_B0_B30_S30', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_B0_E': { + 'hash': 29444, + 'name': 'Woodcut_B0_E', + 'embedded': {} + }, + 'Woodcut_B0_S0_S30': { + 'hash': 35028, + 'name': 'Woodcut_B0_S0_S30', + 'embedded': { + 'Stick_1_38940': { + 'hash': 38940, + 'name': 'Stick_1_38940', + 'savables': {} + }, + 'Stick_2_38936': { + 'hash': 38936, + 'name': 'Stick_2_38936', + 'savables': {} + } + } + }, + 'Woodcut_B0_S0_S60': { + 'hash': 8102, + 'name': 'Woodcut_B0_S0_S60', + 'embedded': { + 'Stick_1_38940': { + 'hash': 38940, + 'name': 'Stick_1', + 'savables': {} + }, + 'Stick_2_38936': { + 'hash': 38936, + 'name': 'Stick_2', + 'savables': {} + }, + 'Woodcut_B0_S0_S60_35622': { + 'hash': 35622, + 'name': 'Woodcut_B0_S0_S60', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_B0_S30_S30': { + 'hash': 54764, + 'name': 'Woodcut_B0_S30_S30', + 'embedded': { + 'Stick_1_38940': { + 'hash': 38940, + 'name': 'Stick_1', + 'savables': {} + }, + 'Stick_2_38936': { + 'hash': 38936, + 'name': 'Stick_2', + 'savables': {} + }, + 'Woodcut_B0_S30_S30_35622': { + 'hash': 35622, + 'name': 'Woodcut_B0_S30_S30', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_B15_B15': { + 'hash': 38016, + 'name': 'Woodcut_B15_B15', + 'embedded': { + 'Top_4690': { + 'hash': 4690, + 'name': 'Top_4690', + 'savables': {} + } + } + }, + 'Woodcut_B30_B30': { + 'hash': 62548, + 'name': 'Woodcut_B30_B30', + 'embedded': { + 'Top_58002': { + 'hash': 58002, + 'name': 'Top_58002', + 'savables': {} + } + } + }, + 'Woodcut_B5_B5': { + 'hash': 1780, + 'name': 'Woodcut_B5_B5', + 'embedded': { + 'Top_37822': { + 'hash': 37822, + 'name': 'Top_37822', + 'savables': {} + } + } + }, + 'Woodcut_Birch_LeafClump_Base': { + 'hash': 37794, + 'name': 'Woodcut_Birch_LeafClump_Base', + 'embedded': { + 'Woodcut_Birch_LeafClump_Base_36402': { + 'hash': 36402, + 'name': 'Woodcut_Birch_LeafClump_Base', + 'savables': {} + } + } + }, + 'Woodcut_Birch_LeafClump_C1C1_1': { + 'hash': 1178, + 'name': 'Woodcut_Birch_LeafClump_C1C1_1', + 'embedded': { + 'Woodcut_Birch_LeafClump_C1C1_1_1176': { + 'hash': 1176, + 'name': 'Woodcut_Birch_LeafClump_C1C1_1', + 'savables': {} + } + } + }, + 'Woodcut_Birch_LeafClump_C1C1_1_E': { + 'hash': 7260, + 'name': 'Woodcut_Birch_LeafClump_C1C1_1_E', + 'embedded': { + 'Woodcut_Birch_LeafClump_C1C1_1_E_7258': { + 'hash': 7258, + 'name': 'Woodcut_Birch_LeafClump_C1C1_1_E', + 'savables': {} + } + } + }, + 'Woodcut_Birch_LeafClump_C1C1_2': { + 'hash': 42598, + 'name': 'Woodcut_Birch_LeafClump_C1C1_2', + 'embedded': { + 'Woodcut_Birch_LeafClump_C1C1_2_42596': { + 'hash': 42596, + 'name': 'Woodcut_Birch_LeafClump_C1C1_2', + 'savables': {} + } + } + }, + 'Woodcut_Birch_LeafClump_C1C1_2_E': { + 'hash': 10700, + 'name': 'Woodcut_Birch_LeafClump_C1C1_2_E', + 'embedded': { + 'Woodcut_Birch_LeafClump_C1C1_2_E_10698': { + 'hash': 10698, + 'name': 'Woodcut_Birch_LeafClump_C1C1_2_E', + 'savables': {} + } + } + }, + 'Woodcut_Birch_LeafClump_C1C2_1': { + 'hash': 54804, + 'name': 'Woodcut_Birch_LeafClump_C1C2_1', + 'embedded': { + 'Woodcut_Birch_LeafClump_C1C2_1_54802': { + 'hash': 54802, + 'name': 'Woodcut_Birch_LeafClump_C1C2_1', + 'savables': {} + } + } + }, + 'Woodcut_Birch_LeafClump_C1C2_1_E': { + 'hash': 2760, + 'name': 'Woodcut_Birch_LeafClump_C1C2_1_E', + 'embedded': { + 'Woodcut_Birch_LeafClump_C1C2_1_E_2758': { + 'hash': 2758, + 'name': 'Woodcut_Birch_LeafClump_C1C2_1_E', + 'savables': {} + } + } + }, + 'Woodcut_Birch_LeafClump_C1C2_2': { + 'hash': 12688, + 'name': 'Woodcut_Birch_LeafClump_C1C2_2', + 'embedded': { + 'Woodcut_Birch_LeafClump_C1C2_2_12686': { + 'hash': 12686, + 'name': 'Woodcut_Birch_LeafClump_C1C2_2', + 'savables': {} + } + } + }, + 'Woodcut_Birch_LeafClump_C1C2_2_E': { + 'hash': 54174, + 'name': 'Woodcut_Birch_LeafClump_C1C2_2_E', + 'embedded': { + 'Woodcut_Birch_LeafClump_C1C2_2_E_54172': { + 'hash': 54172, + 'name': 'Woodcut_Birch_LeafClump_C1C2_2_E', + 'savables': {} + } + } + }, + 'Woodcut_Birch_LeafClump_C1_E': { + 'hash': 55364, + 'name': 'Woodcut_Birch_LeafClump_C1_E', + 'embedded': { + 'Woodcut_Birch_LeafClump_C1_E_55362': { + 'hash': 55362, + 'name': 'Woodcut_Birch_LeafClump_C1_E', + 'savables': {} + } + } + }, + 'Woodcut_Birch_LeafClump_C2C3_1': { + 'hash': 54092, + 'name': 'Woodcut_Birch_LeafClump_C2C3_1', + 'embedded': { + 'Woodcut_Birch_LeafClump_C2C3_1_54090': { + 'hash': 54090, + 'name': 'Woodcut_Birch_LeafClump_C2C3_1', + 'savables': {} + } + } + }, + 'Woodcut_Birch_LeafClump_C2C3_1_E': { + 'hash': 2568, + 'name': 'Woodcut_Birch_LeafClump_C2C3_1_E', + 'embedded': { + 'Woodcut_Birch_LeafClump_C2C3_1_E_2566': { + 'hash': 2566, + 'name': 'Woodcut_Birch_LeafClump_C2C3_1_E', + 'savables': {} + } + } + }, + 'Woodcut_Birch_LeafClump_C2C3_2': { + 'hash': 54852, + 'name': 'Woodcut_Birch_LeafClump_C2C3_2', + 'embedded': { + 'Woodcut_Birch_LeafClump_C2C3_2_54850': { + 'hash': 54850, + 'name': 'Woodcut_Birch_LeafClump_C2C3_2', + 'savables': {} + } + } + }, + 'Woodcut_Birch_LeafClump_C2C3_2_E': { + 'hash': 54108, + 'name': 'Woodcut_Birch_LeafClump_C2C3_2_E', + 'embedded': { + 'Woodcut_Birch_LeafClump_C2C3_2_E_54106': { + 'hash': 54106, + 'name': 'Woodcut_Birch_LeafClump_C2C3_2_E', + 'savables': {} + } + } + }, + 'Woodcut_Birch_LeafClump_C2_E': { + 'hash': 12672, + 'name': 'Woodcut_Birch_LeafClump_C2_E', + 'embedded': { + 'Woodcut_Birch_LeafClump_C2_E_12670': { + 'hash': 12670, + 'name': 'Woodcut_Birch_LeafClump_C2_E', + 'savables': {} + } + } + }, + 'Woodcut_Birch_LeafClump_C3C4_1': { + 'hash': 7276, + 'name': 'Woodcut_Birch_LeafClump_C3C4_1', + 'embedded': { + 'Woodcut_Birch_LeafClump_C3C4_1_7274': { + 'hash': 7274, + 'name': 'Woodcut_Birch_LeafClump_C3C4_1', + 'savables': {} + } + } + }, + 'Woodcut_Birch_LeafClump_C3C4_1_E': { + 'hash': 34602, + 'name': 'Woodcut_Birch_LeafClump_C3C4_1_E', + 'embedded': { + 'Woodcut_Birch_LeafClump_C3C4_1_E_34600': { + 'hash': 34600, + 'name': 'Woodcut_Birch_LeafClump_C3C4_1_E', + 'savables': {} + } + } + }, + 'Woodcut_Birch_LeafClump_C3C4_2': { + 'hash': 12182, + 'name': 'Woodcut_Birch_LeafClump_C3C4_2', + 'embedded': { + 'Woodcut_Birch_LeafClump_C3C4_2_12180': { + 'hash': 12180, + 'name': 'Woodcut_Birch_LeafClump_C3C4_2', + 'savables': {} + } + } + }, + 'Woodcut_Birch_LeafClump_C3C4_2_E': { + 'hash': 11234, + 'name': 'Woodcut_Birch_LeafClump_C3C4_2_E', + 'embedded': { + 'Woodcut_Birch_LeafClump_C3C4_2_E_11232': { + 'hash': 11232, + 'name': 'Woodcut_Birch_LeafClump_C3C4_2_E', + 'savables': {} + } + } + }, + 'Woodcut_Birch_LeafClump_C3_E': { + 'hash': 54820, + 'name': 'Woodcut_Birch_LeafClump_C3_E', + 'embedded': { + 'Woodcut_Birch_LeafClump_C3_E_54818': { + 'hash': 54818, + 'name': 'Woodcut_Birch_LeafClump_C3_E', + 'savables': {} + } + } + }, + 'Woodcut_Birch_LeafClump_C4_E': { + 'hash': 44404, + 'name': 'Woodcut_Birch_LeafClump_C4_E', + 'embedded': { + 'Woodcut_Birch_LeafClump_C4_E_44402': { + 'hash': 44402, + 'name': 'Woodcut_Birch_LeafClump_C4_E', + 'savables': {} + } + } + }, + 'Woodcut_Birch_Seed_Spawner_Attachment': { + 'hash': 16026, + 'name': 'Woodcut_Birch_Seed_Spawner_Attachment', + 'embedded': { + 'Woodcut_Birch_Seed_Spawner_Attachment_36402': { + 'hash': 36402, + 'name': 'Woodcut_Birch_Seed_Spawner_Attachment', + 'savables': {} + } + } + }, + 'Woodcut_BranchRoot_V1_B0': { + 'hash': 8158, + 'name': 'Woodcut_BranchRoot_V1_B0', + 'embedded': { + 'Top_14282': { + 'hash': 14282, + 'name': 'Top_14282', + 'savables': {} + } + } + }, + 'Woodcut_BranchRoot_V1_B15_S30': { + 'hash': 22660, + 'name': 'Woodcut_BranchRoot_V1_B15_S30', + 'embedded': { + 'Top_63620': { + 'hash': 63620, + 'name': 'Top_63620', + 'savables': {} + }, + 'Branch_63622': { + 'hash': 63622, + 'name': 'Branch_63622', + 'savables': {} + } + } + }, + 'Woodcut_BranchRoot_V2_B0': { + 'hash': 50658, + 'name': 'Woodcut_BranchRoot_V2_B0', + 'embedded': { + 'Top_14282': { + 'hash': 14282, + 'name': 'Top', + 'savables': {} + }, + 'Woodcut_BranchRoot_V2_B0_10678': { + 'hash': 10678, + 'name': 'Woodcut_BranchRoot_V2_B0', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_Leaves_V1_L_F': { + 'hash': 42932, + 'name': 'Woodcut_Leaves_V1_L_F', + 'embedded': {} + }, + 'Woodcut_Leaves_V1_L_S': { + 'hash': 42928, + 'name': 'Woodcut_Leaves_V1_L_S', + 'embedded': {} + }, + 'Woodcut_Leaves_V1_S_F': { + 'hash': 42934, + 'name': 'Woodcut_Leaves_V1_S_F', + 'embedded': {} + }, + 'Woodcut_Leaves_V1_S_S': { + 'hash': 42930, + 'name': 'Woodcut_Leaves_V1_S_S', + 'embedded': {} + }, + 'Woodcut_Leaves_V2_D': { + 'hash': 63786, + 'name': 'Woodcut_Leaves_V2_D', + 'embedded': {} + }, + 'Woodcut_Leaves_V2_L': { + 'hash': 63466, + 'name': 'Woodcut_Leaves_V2_L', + 'embedded': {} + }, + 'Woodcut_Leaves_V2_Topper': { + 'hash': 26276, + 'name': 'Woodcut_Leaves_V2_Topper', + 'embedded': {} + }, + 'Woodcut_Oak_LeafClump_Base': { + 'hash': 60158, + 'name': 'Woodcut_Oak_LeafClump_Base', + 'embedded': { + 'Woodcut_Oak_LeafClump_Base_36402': { + 'hash': 36402, + 'name': 'Woodcut_Oak_LeafClump_Base', + 'savables': {} + } + } + }, + 'Woodcut_Oak_LeafClump_C1C1_1': { + 'hash': 38364, + 'name': 'Woodcut_Oak_LeafClump_C1C1_1', + 'embedded': { + 'Woodcut_Oak_LeafClump_C1C1_1_38362': { + 'hash': 38362, + 'name': 'Woodcut_Oak_LeafClump_C1C1_1', + 'savables': {} + } + } + }, + 'Woodcut_Oak_LeafClump_C1C1_2': { + 'hash': 38344, + 'name': 'Woodcut_Oak_LeafClump_C1C1_2', + 'embedded': { + 'Woodcut_Oak_LeafClump_C1C1_2_38342': { + 'hash': 38342, + 'name': 'Woodcut_Oak_LeafClump_C1C1_2', + 'savables': {} + } + } + }, + 'Woodcut_Oak_LeafClump_C1C2_1': { + 'hash': 38324, + 'name': 'Woodcut_Oak_LeafClump_C1C2_1', + 'embedded': { + 'Woodcut_Oak_LeafClump_C1C2_1_38322': { + 'hash': 38322, + 'name': 'Woodcut_Oak_LeafClump_C1C2_1', + 'savables': {} + } + } + }, + 'Woodcut_Oak_LeafClump_C1C2_2': { + 'hash': 38304, + 'name': 'Woodcut_Oak_LeafClump_C1C2_2', + 'embedded': { + 'Woodcut_Oak_LeafClump_C1C2_2_38302': { + 'hash': 38302, + 'name': 'Woodcut_Oak_LeafClump_C1C2_2', + 'savables': {} + } + } + }, + 'Woodcut_Oak_LeafClump_C1C2_E': { + 'hash': 38284, + 'name': 'Woodcut_Oak_LeafClump_C1C2_E', + 'embedded': { + 'Woodcut_Oak_LeafClump_C1C2_E_38282': { + 'hash': 38282, + 'name': 'Woodcut_Oak_LeafClump_C1C2_E', + 'savables': {} + } + } + }, + 'Woodcut_Oak_LeafClump_C1_E': { + 'hash': 38382, + 'name': 'Woodcut_Oak_LeafClump_C1_E', + 'embedded': { + 'Woodcut_Oak_LeafClump_C1_E_38380': { + 'hash': 38380, + 'name': 'Woodcut_Oak_LeafClump_C1_E', + 'savables': {} + } + } + }, + 'Woodcut_Oak_LeafClump_C2C2_1': { + 'hash': 38242, + 'name': 'Woodcut_Oak_LeafClump_C2C2_1', + 'embedded': { + 'Woodcut_Oak_LeafClump_C2C2_1_38240': { + 'hash': 38240, + 'name': 'Woodcut_Oak_LeafClump_C2C2_1', + 'savables': {} + } + } + }, + 'Woodcut_Oak_LeafClump_C2C2_2': { + 'hash': 38224, + 'name': 'Woodcut_Oak_LeafClump_C2C2_2', + 'embedded': { + 'Woodcut_Oak_LeafClump_C2C2_2_38222': { + 'hash': 38222, + 'name': 'Woodcut_Oak_LeafClump_C2C2_2', + 'savables': {} + } + } + }, + 'Woodcut_Oak_LeafClump_C2C3_1': { + 'hash': 38204, + 'name': 'Woodcut_Oak_LeafClump_C2C3_1', + 'embedded': { + 'Woodcut_Oak_LeafClump_C2C3_1_38202': { + 'hash': 38202, + 'name': 'Woodcut_Oak_LeafClump_C2C3_1', + 'savables': {} + } + } + }, + 'Woodcut_Oak_LeafClump_C2C3_2': { + 'hash': 38184, + 'name': 'Woodcut_Oak_LeafClump_C2C3_2', + 'embedded': { + 'Woodcut_Oak_LeafClump_C2C3_2_38182': { + 'hash': 38182, + 'name': 'Woodcut_Oak_LeafClump_C2C3_2', + 'savables': {} + } + } + }, + 'Woodcut_Oak_LeafClump_C2C3_E': { + 'hash': 38162, + 'name': 'Woodcut_Oak_LeafClump_C2C3_E', + 'embedded': { + 'Woodcut_Oak_LeafClump_C2C3_E_38160': { + 'hash': 38160, + 'name': 'Woodcut_Oak_LeafClump_C2C3_E', + 'savables': {} + } + } + }, + 'Woodcut_Oak_LeafClump_C2_E': { + 'hash': 38264, + 'name': 'Woodcut_Oak_LeafClump_C2_E', + 'embedded': { + 'Woodcut_Oak_LeafClump_C2_E_38262': { + 'hash': 38262, + 'name': 'Woodcut_Oak_LeafClump_C2_E', + 'savables': {} + } + } + }, + 'Woodcut_Oak_LeafClump_C3C3_1': { + 'hash': 38122, + 'name': 'Woodcut_Oak_LeafClump_C3C3_1', + 'embedded': { + 'Woodcut_Oak_LeafClump_C3C3_1_38120': { + 'hash': 38120, + 'name': 'Woodcut_Oak_LeafClump_C3C3_1', + 'savables': {} + } + } + }, + 'Woodcut_Oak_LeafClump_C3C3_2': { + 'hash': 38102, + 'name': 'Woodcut_Oak_LeafClump_C3C3_2', + 'embedded': { + 'Woodcut_Oak_LeafClump_C3C3_2_38100': { + 'hash': 38100, + 'name': 'Woodcut_Oak_LeafClump_C3C3_2', + 'savables': {} + } + } + }, + 'Woodcut_Oak_LeafClump_C3_E': { + 'hash': 38144, + 'name': 'Woodcut_Oak_LeafClump_C3_E', + 'embedded': { + 'Woodcut_Oak_LeafClump_C3_E_38142': { + 'hash': 38142, + 'name': 'Woodcut_Oak_LeafClump_C3_E', + 'savables': {} + } + } + }, + 'Woodcut_Oak_Seed_Spawner_Attachment': { + 'hash': 49710, + 'name': 'Woodcut_Oak_Seed_Spawner_Attachment', + 'embedded': { + 'Woodcut_Oak_Seed_Spawner_Attachment_36402': { + 'hash': 36402, + 'name': 'Woodcut_Oak_Seed_Spawner_Attachment', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafClump_Base': { + 'hash': 55152, + 'name': 'Woodcut_Redwood_LeafClump_Base', + 'embedded': { + 'Woodcut_Redwood_LeafClump_Base_55166': { + 'hash': 55166, + 'name': 'Woodcut_Redwood_LeafClump_Base', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafClump_T1_D30_C1C2': { + 'hash': 21374, + 'name': 'Woodcut_Redwood_LeafClump_T1_D30_C1C2', + 'embedded': { + 'Woodcut_Redwood_LeafClump_T1_D30_C1C2_21372': { + 'hash': 21372, + 'name': 'Woodcut_Redwood_LeafClump_T1_D30_C1C2', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafClump_T1_D30_C3C4': { + 'hash': 49074, + 'name': 'Woodcut_Redwood_LeafClump_T1_D30_C3C4', + 'embedded': { + 'Woodcut_Redwood_LeafClump_T1_D30_C3C4_49072': { + 'hash': 49072, + 'name': 'Woodcut_Redwood_LeafClump_T1_D30_C3C4', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafClump_T1_D30_C5C6': { + 'hash': 55378, + 'name': 'Woodcut_Redwood_LeafClump_T1_D30_C5C6', + 'embedded': { + 'Woodcut_Redwood_LeafClump_T1_D30_C5C6_55376': { + 'hash': 55376, + 'name': 'Woodcut_Redwood_LeafClump_T1_D30_C5C6', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafClump_T1_D30_C7C8': { + 'hash': 47486, + 'name': 'Woodcut_Redwood_LeafClump_T1_D30_C7C8', + 'embedded': { + 'Woodcut_Redwood_LeafClump_T1_D30_C7C8_47484': { + 'hash': 47484, + 'name': 'Woodcut_Redwood_LeafClump_T1_D30_C7C8', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafClump_T2_D30_C1C2': { + 'hash': 55954, + 'name': 'Woodcut_Redwood_LeafClump_T2_D30_C1C2', + 'embedded': { + 'Woodcut_Redwood_LeafClump_T2_D30_C1C2_55952': { + 'hash': 55952, + 'name': 'Woodcut_Redwood_LeafClump_T2_D30_C1C2', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafClump_T2_D30_C3C4': { + 'hash': 57266, + 'name': 'Woodcut_Redwood_LeafClump_T2_D30_C3C4', + 'embedded': { + 'Woodcut_Redwood_LeafClump_T2_D30_C3C4_57264': { + 'hash': 57264, + 'name': 'Woodcut_Redwood_LeafClump_T2_D30_C3C4', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafClump_T2_D30_C5C6': { + 'hash': 1528, + 'name': 'Woodcut_Redwood_LeafClump_T2_D30_C5C6', + 'embedded': { + 'Woodcut_Redwood_LeafClump_T2_D30_C5C6_1526': { + 'hash': 1526, + 'name': 'Woodcut_Redwood_LeafClump_T2_D30_C5C6', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafClump_T2_D30_C7C8': { + 'hash': 9410, + 'name': 'Woodcut_Redwood_LeafClump_T2_D30_C7C8', + 'embedded': { + 'Woodcut_Redwood_LeafClump_T2_D30_C7C8_9408': { + 'hash': 9408, + 'name': 'Woodcut_Redwood_LeafClump_T2_D30_C7C8', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafClump_T3_D30_C1C2': { + 'hash': 10666, + 'name': 'Woodcut_Redwood_LeafClump_T3_D30_C1C2', + 'embedded': { + 'Woodcut_Redwood_LeafClump_T3_D30_C1C2_10664': { + 'hash': 10664, + 'name': 'Woodcut_Redwood_LeafClump_T3_D30_C1C2', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafClump_T3_D30_C3C4': { + 'hash': 6716, + 'name': 'Woodcut_Redwood_LeafClump_T3_D30_C3C4', + 'embedded': { + 'Woodcut_Redwood_LeafClump_T3_D30_C3C4_6714': { + 'hash': 6714, + 'name': 'Woodcut_Redwood_LeafClump_T3_D30_C3C4', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafClump_T3_D30_C5C6': { + 'hash': 55520, + 'name': 'Woodcut_Redwood_LeafClump_T3_D30_C5C6', + 'embedded': { + 'Woodcut_Redwood_LeafClump_T3_D30_C5C6_55518': { + 'hash': 55518, + 'name': 'Woodcut_Redwood_LeafClump_T3_D30_C5C6', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafClump_T3_D30_C7C8': { + 'hash': 6732, + 'name': 'Woodcut_Redwood_LeafClump_T3_D30_C7C8', + 'embedded': { + 'Woodcut_Redwood_LeafClump_T3_D30_C7C8_6730': { + 'hash': 6730, + 'name': 'Woodcut_Redwood_LeafClump_T3_D30_C7C8', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafClump_T4_D30_C1': { + 'hash': 42552, + 'name': 'Woodcut_Redwood_LeafClump_T4_D30_C1', + 'embedded': { + 'Woodcut_Redwood_LeafClump_T4_D30_C1_44634': { + 'hash': 44634, + 'name': 'Woodcut_Redwood_LeafClump_T4_D30_C1', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafClump_T4_D30_C2': { + 'hash': 46726, + 'name': 'Woodcut_Redwood_LeafClump_T4_D30_C2', + 'embedded': { + 'Woodcut_Redwood_LeafClump_T4_D30_C2_46724': { + 'hash': 46724, + 'name': 'Woodcut_Redwood_LeafClump_T4_D30_C2', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafClump_T4_D30_C3': { + 'hash': 1774, + 'name': 'Woodcut_Redwood_LeafClump_T4_D30_C3', + 'embedded': { + 'Woodcut_Redwood_LeafClump_T4_D30_C3_1772': { + 'hash': 1772, + 'name': 'Woodcut_Redwood_LeafClump_T4_D30_C3', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafClump_T4_D30_C4': { + 'hash': 1512, + 'name': 'Woodcut_Redwood_LeafClump_T4_D30_C4', + 'embedded': { + 'Woodcut_Redwood_LeafClump_T4_D30_C4_1510': { + 'hash': 1510, + 'name': 'Woodcut_Redwood_LeafClump_T4_D30_C4', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafClump_T4_D30_C5': { + 'hash': 54122, + 'name': 'Woodcut_Redwood_LeafClump_T4_D30_C5', + 'embedded': { + 'Woodcut_Redwood_LeafClump_T4_D30_C5_54120': { + 'hash': 54120, + 'name': 'Woodcut_Redwood_LeafClump_T4_D30_C5', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafClump_T4_D30_C6': { + 'hash': 7242, + 'name': 'Woodcut_Redwood_LeafClump_T4_D30_C6', + 'embedded': { + 'Woodcut_Redwood_LeafClump_T4_D30_C6_7240': { + 'hash': 7240, + 'name': 'Woodcut_Redwood_LeafClump_T4_D30_C6', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafClump_T4_D30_C7': { + 'hash': 44386, + 'name': 'Woodcut_Redwood_LeafClump_T4_D30_C7', + 'embedded': { + 'Woodcut_Redwood_LeafClump_T4_D30_C7_44384': { + 'hash': 44384, + 'name': 'Woodcut_Redwood_LeafClump_T4_D30_C7', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafClump_T4_D30_C8': { + 'hash': 10754, + 'name': 'Woodcut_Redwood_LeafClump_T4_D30_C8', + 'embedded': { + 'Woodcut_Redwood_LeafClump_T4_D30_C8_10752': { + 'hash': 10752, + 'name': 'Woodcut_Redwood_LeafClump_T4_D30_C8', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_LeafTopper': { + 'hash': 34724, + 'name': 'Woodcut_Redwood_LeafTopper', + 'embedded': { + 'Woodcut_Redwood_LeafTopper_34720': { + 'hash': 34720, + 'name': 'Woodcut_Redwood_LeafTopper', + 'savables': {} + } + } + }, + 'Woodcut_Redwood_Seed_Spawner_Attachment': { + 'hash': 16012, + 'name': 'Woodcut_Redwood_Seed_Spawner_Attachment', + 'embedded': { + 'Woodcut_Redwood_Seed_Spawner_Attachment_36402': { + 'hash': 36402, + 'name': 'Woodcut_Redwood_Seed_Spawner_Attachment', + 'savables': {} + } + } + }, + 'Woodcut_Root_V1_T0': { + 'hash': 31522, + 'name': 'Woodcut_Root_V1_T0', + 'embedded': { + 'Top_49314': { + 'hash': 49314, + 'name': 'Top_49314', + 'savables': {} + } + } + }, + 'Woodcut_Root_V1_T0_B15': { + 'hash': 34660, + 'name': 'Woodcut_Root_V1_T0_B15', + 'embedded': { + 'Top_23584': { + 'hash': 23584, + 'name': 'Top_23584', + 'savables': {} + }, + 'Branch_12832': { + 'hash': 12832, + 'name': 'Branch_12832', + 'savables': {} + } + } + }, + 'Woodcut_Root_V1_T0_S30': { + 'hash': 34546, + 'name': 'Woodcut_Root_V1_T0_S30', + 'embedded': { + 'Top_56452': { + 'hash': 56452, + 'name': 'Top_56452', + 'savables': {} + }, + 'Stick_51558': { + 'hash': 51558, + 'name': 'Stick_51558', + 'savables': {} + } + } + }, + 'Woodcut_Root_V1_T30': { + 'hash': 47612, + 'name': 'Woodcut_Root_V1_T30', + 'embedded': { + 'Top_7658': { + 'hash': 7658, + 'name': 'Top_7658', + 'savables': {} + } + } + }, + 'Woodcut_S-15_S-15': { + 'hash': 39282, + 'name': 'Woodcut_S-15_S-15', + 'embedded': { + 'Top_1286': { + 'hash': 1286, + 'name': 'Top', + 'savables': {} + }, + 'Woodcut_S-15_S-15_45390': { + 'hash': 45390, + 'name': 'Woodcut_S-15_S-15', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_S0_E': { + 'hash': 25704, + 'name': 'Woodcut_S0_E', + 'embedded': {} + }, + 'Woodcut_S0_S0': { + 'hash': 44986, + 'name': 'Woodcut_S0_S0', + 'embedded': { + 'Top_1286': { + 'hash': 1286, + 'name': 'Top_1286', + 'savables': {} + } + } + }, + 'Woodcut_S0_S0_S-30': { + 'hash': 25116, + 'name': 'Woodcut_S0_S0_S-30', + 'embedded': { + 'Top_1_2062': { + 'hash': 2062, + 'name': 'Top_1', + 'savables': {} + }, + 'Top_2_60778': { + 'hash': 60778, + 'name': 'Top_2', + 'savables': {} + }, + 'Woodcut_S0_S0_S-30_64064': { + 'hash': 64064, + 'name': 'Woodcut_S0_S0_S-30', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_S0_S0_S30': { + 'hash': 190, + 'name': 'Woodcut_S0_S0_S30', + 'embedded': { + 'Top_1_2062': { + 'hash': 2062, + 'name': 'Top_1', + 'savables': {} + }, + 'Top_2_60778': { + 'hash': 60778, + 'name': 'Top_2', + 'savables': {} + }, + 'Woodcut_S0_S0_S30_64064': { + 'hash': 64064, + 'name': 'Woodcut_S0_S0_S30', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_S0_S15_S15': { + 'hash': 62106, + 'name': 'Woodcut_S0_S15_S15', + 'embedded': { + 'Top_1_2062': { + 'hash': 2062, + 'name': 'Top_1_2062', + 'savables': {} + }, + 'Top_2_60778': { + 'hash': 60778, + 'name': 'Top_2_60778', + 'savables': {} + } + } + }, + 'Woodcut_S0_S30_S30': { + 'hash': 9058, + 'name': 'Woodcut_S0_S30_S30', + 'embedded': { + 'Top_1_9064': { + 'hash': 9064, + 'name': 'Top_1', + 'savables': {} + }, + 'Top_2_9062': { + 'hash': 9062, + 'name': 'Top_2', + 'savables': {} + }, + 'Woodcut_S0_S30_S30_9060': { + 'hash': 9060, + 'name': 'Woodcut_S0_S30_S30', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_S15_S15': { + 'hash': 19364, + 'name': 'Woodcut_S15_S15', + 'embedded': { + 'Top_1286': { + 'hash': 1286, + 'name': 'Top', + 'savables': {} + }, + 'Woodcut_S15_S15_45390': { + 'hash': 45390, + 'name': 'Woodcut_S15_S15', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_SL15_SL15': { + 'hash': 7464, + 'name': 'Woodcut_SL15_SL15', + 'embedded': { + 'Top_1286': { + 'hash': 1286, + 'name': 'Top', + 'savables': {} + }, + 'Woodcut_SL15_SL15_7460': { + 'hash': 7460, + 'name': 'Woodcut_SL15_SL15', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_SR15_SR15': { + 'hash': 53266, + 'name': 'Woodcut_SR15_SR15', + 'embedded': { + 'Top_1286': { + 'hash': 1286, + 'name': 'Top', + 'savables': {} + }, + 'Woodcut_SR15_SR15_53262': { + 'hash': 53262, + 'name': 'Woodcut_SR15_SR15', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_T0_B0_B30': { + 'hash': 35026, + 'name': 'Woodcut_T0_B0_B30', + 'embedded': { + 'Branch_1_4000': { + 'hash': 4000, + 'name': 'Branch_1_4000', + 'savables': {} + }, + 'Branch_2_3996': { + 'hash': 3996, + 'name': 'Branch_2_3996', + 'savables': {} + } + } + }, + 'Woodcut_T0_B15_B30': { + 'hash': 21794, + 'name': 'Woodcut_T0_B15_B30', + 'embedded': { + 'Branch_1_634': { + 'hash': 634, + 'name': 'Branch_1_634', + 'savables': {} + }, + 'Branch_2_636': { + 'hash': 636, + 'name': 'Branch_2_636', + 'savables': {} + } + } + }, + 'Woodcut_T0_B30_B30': { + 'hash': 26492, + 'name': 'Woodcut_T0_B30_B30', + 'embedded': { + 'Branch_1_26494': { + 'hash': 26494, + 'name': 'Branch_1', + 'savables': {} + }, + 'Branch_2_26488': { + 'hash': 26488, + 'name': 'Branch_2', + 'savables': {} + }, + 'Woodcut_T0_B30_B30_26500': { + 'hash': 26500, + 'name': 'Woodcut_T0_B30_B30', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_T0_B45_B45_B60': { + 'hash': 62378, + 'name': 'Woodcut_T0_B45_B45_B60', + 'embedded': { + 'Branch_1_4000': { + 'hash': 4000, + 'name': 'Branch_1', + 'savables': {} + }, + 'Branch_2_20244': { + 'hash': 20244, + 'name': 'Branch_2', + 'savables': {} + }, + 'Branch_3_20258': { + 'hash': 20258, + 'name': 'Branch_3', + 'savables': {} + }, + 'Woodcut_T0_B45_B45_B60_35620': { + 'hash': 35620, + 'name': 'Woodcut_T0_B45_B45_B60', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_T0_E': { + 'hash': 49440, + 'name': 'Woodcut_T0_E', + 'embedded': {} + }, + 'Woodcut_T0_T0': { + 'hash': 6554, + 'name': 'Woodcut_T0_T0', + 'embedded': { + 'Top_39100': { + 'hash': 39100, + 'name': 'Top_39100', + 'savables': {} + } + } + }, + 'Woodcut_T0_T0_B30': { + 'hash': 35016, + 'name': 'Woodcut_T0_T0_B30', + 'embedded': { + 'Top_34360': { + 'hash': 34360, + 'name': 'Top_34360', + 'savables': {} + }, + 'Branch_34356': { + 'hash': 34356, + 'name': 'Branch_34356', + 'savables': {} + } + } + }, + 'Woodcut_T0_T0_B45': { + 'hash': 52242, + 'name': 'Woodcut_T0_T0_B45', + 'embedded': { + 'Top_15160': { + 'hash': 15160, + 'name': 'Top_15160', + 'savables': {} + }, + 'Branch_15162': { + 'hash': 15162, + 'name': 'Branch_15162', + 'savables': {} + } + } + }, + 'Woodcut_T0_T0_B45_B45_B60': { + 'hash': 34502, + 'name': 'Woodcut_T0_T0_B45_B45_B60', + 'embedded': { + 'Branch_1_15162': { + 'hash': 15162, + 'name': 'Branch_1', + 'savables': {} + }, + 'Branch_2_19850': { + 'hash': 19850, + 'name': 'Branch_2', + 'savables': {} + }, + 'Branch_3_19844': { + 'hash': 19844, + 'name': 'Branch_3', + 'savables': {} + }, + 'Top_15160': { + 'hash': 15160, + 'name': 'Top', + 'savables': {} + }, + 'Woodcut_T0_T0_B45_B45_B60_55228': { + 'hash': 55228, + 'name': 'Woodcut_T0_T0_B45_B45_B60', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_T0_T0_B60': { + 'hash': 29162, + 'name': 'Woodcut_T0_T0_B60', + 'embedded': { + 'Branch_15162': { + 'hash': 15162, + 'name': 'Branch', + 'savables': {} + }, + 'Top_15160': { + 'hash': 15160, + 'name': 'Top', + 'savables': {} + }, + 'Woodcut_T0_T0_B60_55228': { + 'hash': 55228, + 'name': 'Woodcut_T0_T0_B60', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_T0_T0_S30': { + 'hash': 35022, + 'name': 'Woodcut_T0_T0_S30', + 'embedded': { + 'Top_45916': { + 'hash': 45916, + 'name': 'Top_45916', + 'savables': {} + }, + 'Stick_45912': { + 'hash': 45912, + 'name': 'Stick_45912', + 'savables': {} + } + } + }, + 'Woodcut_T0_T0_S30_S30_S30': { + 'hash': 33712, + 'name': 'Woodcut_T0_T0_S30_S30_S30', + 'embedded': { + 'Top_836': { + 'hash': 836, + 'name': 'Top_836', + 'savables': {} + }, + 'Stick_1_34724': { + 'hash': 34724, + 'name': 'Stick_1_34724', + 'savables': {} + }, + 'Stick_2_17522': { + 'hash': 17522, + 'name': 'Stick_2_17522', + 'savables': {} + }, + 'Stick_3_910': { + 'hash': 910, + 'name': 'Stick_3_910', + 'savables': {} + } + } + }, + 'Woodcut_T0_T30_B30': { + 'hash': 2712, + 'name': 'Woodcut_T0_T30_B30', + 'embedded': { + 'Branch_15162': { + 'hash': 15162, + 'name': 'Branch', + 'savables': {} + }, + 'Top_15160': { + 'hash': 15160, + 'name': 'Top', + 'savables': {} + }, + 'Woodcut_T0_T30_B30_55228': { + 'hash': 55228, + 'name': 'Woodcut_T0_T30_B30', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_T15_T15': { + 'hash': 40700, + 'name': 'Woodcut_T15_T15', + 'embedded': { + 'Top_30734': { + 'hash': 30734, + 'name': 'Top_30734', + 'savables': {} + } + } + }, + 'Woodcut_T30_T30': { + 'hash': 30226, + 'name': 'Woodcut_T30_T30', + 'embedded': { + 'Top_28372': { + 'hash': 28372, + 'name': 'Top_28372', + 'savables': {} + } + } + }, + 'Woodcut_T5_T5': { + 'hash': 18498, + 'name': 'Woodcut_T5_T5', + 'embedded': { + 'Top_32750': { + 'hash': 32750, + 'name': 'Top_32750', + 'savables': {} + } + } + }, + 'Woodcut_Training_Block': { + 'hash': 13392, + 'name': 'Woodcut_Training_Block', + 'embedded': { + 'Woodcut_Training_Block_11246': { + 'hash': 11246, + 'name': 'Woodcut_Training_Block', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + } + } + }, + 'Woodcut_Twigs_V1_-30': { + 'hash': 49360, + 'name': 'Woodcut_Twigs_V1_-30', + 'embedded': {} + }, + 'Woodcut_Twigs_V1_0': { + 'hash': 64824, + 'name': 'Woodcut_Twigs_V1_0', + 'embedded': {} + }, + 'Woodcut_Twigs_V1_30': { + 'hash': 19674, + 'name': 'Woodcut_Twigs_V1_30', + 'embedded': {} + }, + 'Woodcut_Twigs_V2_-30': { + 'hash': 63554, + 'name': 'Woodcut_Twigs_V2_-30', + 'embedded': {} + }, + 'Woodcut_Twigs_V2_0': { + 'hash': 1846, + 'name': 'Woodcut_Twigs_V2_0', + 'embedded': {} + }, + 'Woodcut_Twigs_V2_30': { + 'hash': 1452, + 'name': 'Woodcut_Twigs_V2_30', + 'embedded': {} + }, + 'Woodcut_Twigs_V3_-30': { + 'hash': 49972, + 'name': 'Woodcut_Twigs_V3_-30', + 'embedded': {} + }, + 'Woodcut_Twigs_V3_0': { + 'hash': 63168, + 'name': 'Woodcut_Twigs_V3_0', + 'embedded': {} + }, + 'Woodcut_Twigs_V3_30': { + 'hash': 15084, + 'name': 'Woodcut_Twigs_V3_30', + 'embedded': {} + }, + 'Woodcut_Twigs_V4_0': { + 'hash': 52628, + 'name': 'Woodcut_Twigs_V4_0', + 'embedded': {} + }, + 'Woodcut_Twigs_V4_30': { + 'hash': 31554, + 'name': 'Woodcut_Twigs_V4_30', + 'embedded': {} + }, + 'Woodcut_Twigs_V5_-15': { + 'hash': 16424, + 'name': 'Woodcut_Twigs_V5_-15', + 'embedded': { + 'Woodcut_Twigs_V5_-15_47386': { + 'hash': 47386, + 'name': 'Woodcut_Twigs_V5_-15', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_Twigs_V5_15': { + 'hash': 32642, + 'name': 'Woodcut_Twigs_V5_15', + 'embedded': { + 'Woodcut_Twigs_V5_15_32644': { + 'hash': 32644, + 'name': 'Woodcut_Twigs_V5_15', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_Twigs_V5_L15': { + 'hash': 40208, + 'name': 'Woodcut_Twigs_V5_L15', + 'embedded': { + 'Woodcut_Twigs_V5_L15_40210': { + 'hash': 40210, + 'name': 'Woodcut_Twigs_V5_L15', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_Twigs_V5_R15': { + 'hash': 25388, + 'name': 'Woodcut_Twigs_V5_R15', + 'embedded': { + 'Woodcut_Twigs_V5_R15_25390': { + 'hash': 25390, + 'name': 'Woodcut_Twigs_V5_R15', + 'savables': { + 'WoodcutPointCollection': { + 'hash': 276353327, + 'name': 'WoodcutPointCollection' + } + } + } + } + }, + 'Woodcut_Walnut_LeafClump_Base': { + 'hash': 47632, + 'name': 'Woodcut_Walnut_LeafClump_Base', + 'embedded': { + 'Woodcut_Walnut_LeafClump_Base_47646': { + 'hash': 47646, + 'name': 'Woodcut_Walnut_LeafClump_Base', + 'savables': {} + } + } + }, + 'Woodcut_Walnut_LeafClump_C1C1': { + 'hash': 29962, + 'name': 'Woodcut_Walnut_LeafClump_C1C1', + 'embedded': { + 'Woodcut_Walnut_LeafClump_C1C1_29960': { + 'hash': 29960, + 'name': 'Woodcut_Walnut_LeafClump_C1C1', + 'savables': {} + } + } + }, + 'Woodcut_Walnut_LeafClump_C1C1_E': { + 'hash': 2796, + 'name': 'Woodcut_Walnut_LeafClump_C1C1_E', + 'embedded': { + 'Woodcut_Walnut_LeafClump_C1C1_E_2794': { + 'hash': 2794, + 'name': 'Woodcut_Walnut_LeafClump_C1C1_E', + 'savables': {} + } + } + }, + 'Woodcut_Walnut_LeafClump_C1C2': { + 'hash': 8570, + 'name': 'Woodcut_Walnut_LeafClump_C1C2', + 'embedded': { + 'Woodcut_Walnut_LeafClump_C1C2_8568': { + 'hash': 8568, + 'name': 'Woodcut_Walnut_LeafClump_C1C2', + 'savables': {} + } + } + }, + 'Woodcut_Walnut_LeafClump_C1C2_E': { + 'hash': 54836, + 'name': 'Woodcut_Walnut_LeafClump_C1C2_E', + 'embedded': { + 'Woodcut_Walnut_LeafClump_C1C2_E_54834': { + 'hash': 54834, + 'name': 'Woodcut_Walnut_LeafClump_C1C2_E', + 'savables': {} + } + } + }, + 'Woodcut_Walnut_LeafClump_C2C2': { + 'hash': 8932, + 'name': 'Woodcut_Walnut_LeafClump_C2C2', + 'embedded': { + 'Woodcut_Walnut_LeafClump_C2C2_8930': { + 'hash': 8930, + 'name': 'Woodcut_Walnut_LeafClump_C2C2', + 'savables': {} + } + } + }, + 'Woodcut_Walnut_LeafClump_C2C2_E': { + 'hash': 1792, + 'name': 'Woodcut_Walnut_LeafClump_C2C2_E', + 'embedded': { + 'Woodcut_Walnut_LeafClump_C2C2_E_1790': { + 'hash': 1790, + 'name': 'Woodcut_Walnut_LeafClump_C2C2_E', + 'savables': {} + } + } + }, + 'Woodcut_Walnut_LeafClump_C2C3': { + 'hash': 47520, + 'name': 'Woodcut_Walnut_LeafClump_C2C3', + 'embedded': { + 'Woodcut_Walnut_LeafClump_C2C3_47518': { + 'hash': 47518, + 'name': 'Woodcut_Walnut_LeafClump_C2C3', + 'savables': {} + } + } + }, + 'Woodcut_Walnut_LeafClump_C2C3_E': { + 'hash': 46292, + 'name': 'Woodcut_Walnut_LeafClump_C2C3_E', + 'embedded': { + 'Woodcut_Walnut_LeafClump_C2C3_E_46290': { + 'hash': 46290, + 'name': 'Woodcut_Walnut_LeafClump_C2C3_E', + 'savables': {} + } + } + }, + 'Woodcut_Walnut_LeafClump_C3C3': { + 'hash': 54190, + 'name': 'Woodcut_Walnut_LeafClump_C3C3', + 'embedded': { + 'Woodcut_Walnut_LeafClump_C3C3_54188': { + 'hash': 54188, + 'name': 'Woodcut_Walnut_LeafClump_C3C3', + 'savables': {} + } + } + }, + 'Woodcut_Walnut_LeafClump_C3C3_E': { + 'hash': 8292, + 'name': 'Woodcut_Walnut_LeafClump_C3C3_E', + 'embedded': { + 'Woodcut_Walnut_LeafClump_C3C3_E_8290': { + 'hash': 8290, + 'name': 'Woodcut_Walnut_LeafClump_C3C3_E', + 'savables': {} + } + } + }, + 'Woodcut_Walnut_LeafClump_C3C4': { + 'hash': 57820, + 'name': 'Woodcut_Walnut_LeafClump_C3C4', + 'embedded': { + 'Woodcut_Walnut_LeafClump_C3C4_57818': { + 'hash': 57818, + 'name': 'Woodcut_Walnut_LeafClump_C3C4', + 'savables': {} + } + } + }, + 'Woodcut_Walnut_LeafClump_C3C4_E': { + 'hash': 1546, + 'name': 'Woodcut_Walnut_LeafClump_C3C4_E', + 'embedded': { + 'Woodcut_Walnut_LeafClump_C3C4_E_1544': { + 'hash': 1544, + 'name': 'Woodcut_Walnut_LeafClump_C3C4_E', + 'savables': {} + } + } + }, + 'Woodcut_Walnut_LeafClump_C4C4_E': { + 'hash': 44372, + 'name': 'Woodcut_Walnut_LeafClump_C4C4_E', + 'embedded': { + 'Woodcut_Walnut_LeafClump_C4C4_E_44370': { + 'hash': 44370, + 'name': 'Woodcut_Walnut_LeafClump_C4C4_E', + 'savables': {} + } + } + }, + 'Woodcut_Walnut_LeafClump_C4C5_E': { + 'hash': 6218, + 'name': 'Woodcut_Walnut_LeafClump_C4C5_E', + 'embedded': { + 'Woodcut_Walnut_LeafClump_C4C5_E_6216': { + 'hash': 6216, + 'name': 'Woodcut_Walnut_LeafClump_C4C5_E', + 'savables': {} + } + } + }, + 'Woodcut_Walnut_LeafClump_C5C5_E': { + 'hash': 9940, + 'name': 'Woodcut_Walnut_LeafClump_C5C5_E', + 'embedded': { + 'Woodcut_Walnut_LeafClump_C5C5_E_9938': { + 'hash': 9938, + 'name': 'Woodcut_Walnut_LeafClump_C5C5_E', + 'savables': {} + } + } + }, + 'Woodcut_Walnut_Seed_Spawner_Attachment': { + 'hash': 16040, + 'name': 'Woodcut_Walnut_Seed_Spawner_Attachment', + 'embedded': { + 'Woodcut_Walnut_Seed_Spawner_Attachment_36402': { + 'hash': 36402, + 'name': 'Woodcut_Walnut_Seed_Spawner_Attachment', + 'savables': {} + } + } + }, + 'Woodcut_Wedge': { + 'hash': 47118, + 'name': 'Woodcut_Wedge', + 'embedded': { + 'Woodcut_Wedge_10506': { + 'hash': 10506, + 'name': 'Woodcut_Wedge', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Woodcut_Wedge_Ashen': { + 'hash': 232, + 'name': 'Woodcut_Wedge_Ashen', + 'embedded': { + 'Woodcut_Wedge_Ashen_3674': { + 'hash': 3674, + 'name': 'Woodcut_Wedge_Ashen', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Woodcut_Wedge_Burnt': { + 'hash': 290, + 'name': 'Woodcut_Wedge_Burnt', + 'embedded': { + 'Woodcut_Wedge_Burnt_3674': { + 'hash': 3674, + 'name': 'Woodcut_Wedge_Burnt', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Woodcut_Wedge_Charred': { + 'hash': 58068, + 'name': 'Woodcut_Wedge_Charred', + 'embedded': { + 'Woodcut_Wedge_Charred_3674': { + 'hash': 3674, + 'name': 'Woodcut_Wedge_Charred', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Woodcut_Wedge_Storage': { + 'hash': 12512, + 'name': 'Woodcut_Wedge_Storage', + 'embedded': { + 'Filter_Dock_57214': { + 'hash': 57214, + 'name': 'Filter_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Interaction_Point_59032': { + 'hash': 59032, + 'name': 'Interaction_Point', + 'savables': {} + }, + 'Internal_Dock_59328': { + 'hash': 59328, + 'name': 'Internal_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Withdraw_Dock_34750': { + 'hash': 34750, + 'name': 'Withdraw_Dock', + 'savables': {} + }, + 'Woodcut_Wedge_Storage_12490': { + 'hash': 12490, + 'name': 'Woodcut_Wedge_Storage', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + }, + 'CommunalStorage': { + 'hash': 3084373371, + 'name': 'CommunalStorage' + }, + 'PlayerInteractionRestrictor': { + 'hash': 2951515968, + 'name': 'PlayerInteractionRestrictor' + } + } + } + } + }, + 'Woodcutting_Path': { + 'hash': 45418, + 'name': 'Woodcutting_Path', + 'embedded': { + 'Woodcutting_Path_54368': { + 'hash': 54368, + 'name': 'Woodcutting_Path', + 'savables': { + 'PopulationPath': { + 'hash': 7704646, + 'name': 'PopulationPath' + } + } + } + } + }, + 'Woodcutting_Vines_V1_Large': { + 'hash': 24682, + 'name': 'Woodcutting_Vines_V1_Large', + 'embedded': {} + }, + 'Woodcutting_Vines_V1_Small_V1': { + 'hash': 24686, + 'name': 'Woodcutting_Vines_V1_Small_V1', + 'embedded': {} + }, + 'Woodcutting_Vines_V1_Small_V2': { + 'hash': 24684, + 'name': 'Woodcutting_Vines_V1_Small_V2', + 'embedded': {} + }, + 'Woodcutting_Vines_V1_Small_V3': { + 'hash': 24688, + 'name': 'Woodcutting_Vines_V1_Small_V3', + 'embedded': {} + }, + 'Wooden_Bag': { + 'hash': 30060, + 'name': 'Wooden_Bag', + 'embedded': { + 'Bag_Body_42972': { + 'hash': 42972, + 'name': 'Bag_Body', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + }, + 'Dock_ML_42984': { + 'hash': 42984, + 'name': 'Dock_ML', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_MM_42982': { + 'hash': 42982, + 'name': 'Dock_MM', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_MR_42980': { + 'hash': 42980, + 'name': 'Dock_MR', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_TL_42990': { + 'hash': 42990, + 'name': 'Dock_TL', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_TM_42988': { + 'hash': 42988, + 'name': 'Dock_TM', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Dock_TR_42986': { + 'hash': 42986, + 'name': 'Dock_TR', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Wooden_Bag_43012': { + 'hash': 43012, + 'name': 'Wooden_Bag', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'wooden_bag_back_straw_22280': { + 'hash': 22280, + 'name': 'wooden_bag_back_straw', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'wooden_bag_beam_01_22276': { + 'hash': 22276, + 'name': 'wooden_bag_beam_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'wooden_bag_beam_02_22320': { + 'hash': 22320, + 'name': 'wooden_bag_beam_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'wooden_bag_beam_03_22316': { + 'hash': 22316, + 'name': 'wooden_bag_beam_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'wooden_bag_beam_04_22308': { + 'hash': 22308, + 'name': 'wooden_bag_beam_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'wooden_bag_beam_05_22304': { + 'hash': 22304, + 'name': 'wooden_bag_beam_05', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'wooden_bag_beam_06_22300': { + 'hash': 22300, + 'name': 'wooden_bag_beam_06', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'wooden_bag_beam_07_22296': { + 'hash': 22296, + 'name': 'wooden_bag_beam_07', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'wooden_bag_beam_curved_01_22292': { + 'hash': 22292, + 'name': 'wooden_bag_beam_curved_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'wooden_bag_beam_curved_02_22288': { + 'hash': 22288, + 'name': 'wooden_bag_beam_curved_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'wooden_bag_front_straw_22284': { + 'hash': 22284, + 'name': 'wooden_bag_front_straw', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'wooden_bag_handle_738': { + 'hash': 738, + 'name': 'wooden_bag_handle', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'wooden_bag_handle_wraps_742': { + 'hash': 742, + 'name': 'wooden_bag_handle_wraps', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'wooden_bag_lid_straw_22312': { + 'hash': 22312, + 'name': 'wooden_bag_lid_straw', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'wooden_bag_side_01_straw_22272': { + 'hash': 22272, + 'name': 'wooden_bag_side_01_straw', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'wooden_bag_side_02_straw_22268': { + 'hash': 22268, + 'name': 'wooden_bag_side_02_straw', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Wooden_Barrel': { + 'hash': 5890, + 'name': 'Wooden_Barrel', + 'embedded': { + 'Handle_Pickup_13422': { + 'hash': 13422, + 'name': 'Handle_Pickup', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + } + } + }, + 'Handle__58484': { + 'hash': 58484, + 'name': 'Handle_', + 'savables': {} + }, + 'Wooden_Barrel_11132': { + 'hash': 11132, + 'name': 'Wooden_Barrel', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + }, + 'LiquidContainer': { + 'hash': 4179293747, + 'name': 'LiquidContainer' + } + } + } + } + }, + 'Wooden_Bowl': { + 'hash': 25908, + 'name': 'Wooden_Bowl', + 'embedded': { + 'Wooden_Bowl_23250': { + 'hash': 23250, + 'name': 'Wooden_Bowl', + 'savables': { + 'LiquidContainer': { + 'hash': 4179293747, + 'name': 'LiquidContainer' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Wooden_Bucket': { + 'hash': 63904, + 'name': 'Wooden_Bucket', + 'embedded': { + 'Bucket_Wooden_Metal_Bottom_20258': { + 'hash': 20258, + 'name': 'Bucket_Wooden_Metal_Bottom', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'Bucket_Wooden_Metal_Top_20246': { + 'hash': 20246, + 'name': 'Bucket_Wooden_Metal_Top', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'Bucket_Wooden_Wood_20270': { + 'hash': 20270, + 'name': 'Bucket_Wooden_Wood', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'Bucket_Wooden_Wood_Bottom_20262': { + 'hash': 20262, + 'name': 'Bucket_Wooden_Wood_Bottom', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'Handle_L__20254': { + 'hash': 20254, + 'name': 'Handle_L_', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'Handle_R_20266': { + 'hash': 20266, + 'name': 'Handle_R', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'Handle_Top_20250': { + 'hash': 20250, + 'name': 'Handle_Top', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'Heat_47560': { + 'hash': 47560, + 'name': 'Heat', + 'savables': { + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'Wooden_Bucket_65316': { + 'hash': 65316, + 'name': 'Wooden_Bucket', + 'savables': { + 'LiquidContainer': { + 'hash': 4179293747, + 'name': 'LiquidContainer' + }, + 'MultiHandPickup': { + 'hash': 1556697998, + 'name': 'MultiHandPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'cookingPot_plate_01_24': { + 'hash': 24, + 'name': 'cookingPot_plate_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'cookingPot_plate_02_28': { + 'hash': 28, + 'name': 'cookingPot_plate_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'cookingPot_plate_03_36': { + 'hash': 36, + 'name': 'cookingPot_plate_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'cookingPot_plate_04_32': { + 'hash': 32, + 'name': 'cookingPot_plate_04', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'cookingPot_plate_mid_01_48': { + 'hash': 48, + 'name': 'cookingPot_plate_mid_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'cookingPot_plate_mid_02_56': { + 'hash': 56, + 'name': 'cookingPot_plate_mid_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Wooden_Dice': { + 'hash': 45608, + 'name': 'Wooden_Dice', + 'embedded': { + 'Wooden_Dice_45490': { + 'hash': 45490, + 'name': 'Wooden_Dice', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Wooden_Ladle': { + 'hash': 15274, + 'name': 'Wooden_Ladle', + 'embedded': { + 'Wooden_Ladle_16772': { + 'hash': 16772, + 'name': 'Wooden_Ladle', + 'savables': { + 'LiquidContainer': { + 'hash': 4179293747, + 'name': 'LiquidContainer' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Wooden_Net': { + 'hash': 53540, + 'name': 'Wooden_Net', + 'embedded': { + 'Dock_42390': { + 'hash': 42390, + 'name': 'Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'Insert_HammerType_End_Cap_7796': { + 'hash': 7796, + 'name': 'Insert_HammerType_End_Cap', + 'savables': {} + }, + 'Wooden_Net_7480': { + 'hash': 7480, + 'name': 'Wooden_Net', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + }, + 'woodenNet_basket_17034': { + 'hash': 17034, + 'name': 'woodenNet_basket', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'woodenNet_curvedFrame_01_17018': { + 'hash': 17018, + 'name': 'woodenNet_curvedFrame_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'woodenNet_curvedFrame_brace_01_17022': { + 'hash': 17022, + 'name': 'woodenNet_curvedFrame_brace_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'woodenNet_handle_01_17026': { + 'hash': 17026, + 'name': 'woodenNet_handle_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'woodenNet_knot_01_17038': { + 'hash': 17038, + 'name': 'woodenNet_knot_01', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'woodenNet_knot_02_17030': { + 'hash': 17030, + 'name': 'woodenNet_knot_02', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + }, + 'woodenNet_knot_03_17014': { + 'hash': 17014, + 'name': 'woodenNet_knot_03', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + } + } + } + } + }, + 'Wooden_Passage_Dynamic': { + 'hash': 43806, + 'name': 'Wooden_Passage_Dynamic', + 'embedded': { + 'Enemy_Spawn_28160': { + 'hash': 28160, + 'name': 'Enemy_Spawn', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + }, + 'Spawn_43748': { + 'hash': 43748, + 'name': 'Spawn', + 'savables': { + 'DirectionalBoundsSurface': { + 'hash': 1962842866, + 'name': 'DirectionalBoundsSurface' + }, + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + } + } + }, + 'Wooden_Passage_Dynamic_43790': { + 'hash': 43790, + 'name': 'Wooden_Passage_Dynamic', + 'savables': {} + } + } + }, + 'Wooden_Short_Sword': { + 'hash': 16448, + 'name': 'Wooden_Short_Sword', + 'embedded': { + 'Wooden_Short_Sword_18792': { + 'hash': 18792, + 'name': 'Wooden_Short_Sword', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Wooden_Stake': { + 'hash': 17262, + 'name': 'Wooden_Stake', + 'embedded': { + 'Slot_Multi_11474': { + 'hash': 11474, + 'name': 'Slot_Multi', + 'savables': {} + }, + 'Wooden_Stake_17052': { + 'hash': 17052, + 'name': 'Wooden_Stake', + 'savables': { + 'DurabilityModule': { + 'hash': 1871432223, + 'name': 'DurabilityModule' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'RaycastCrafter': { + 'hash': 2815374842, + 'name': 'RaycastCrafter' + } + } + } + } + }, + 'Wooden_Stirring_Spoon': { + 'hash': 23950, + 'name': 'Wooden_Stirring_Spoon', + 'embedded': { + 'Wooden_Stirring_Spoon_26366': { + 'hash': 26366, + 'name': 'Wooden_Stirring_Spoon', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'Wyrm': { + 'hash': 21642, + 'name': 'Wyrm', + 'embedded': { + 'Animation_6144': { + 'hash': 6144, + 'name': 'Animation', + 'savables': {} + }, + 'Body_1052': { + 'hash': 1052, + 'name': 'Body', + 'savables': {} + }, + 'Gameplay_42330': { + 'hash': 42330, + 'name': 'Gameplay', + 'savables': {} + }, + 'Ground_58968': { + 'hash': 58968, + 'name': 'Ground', + 'savables': {} + }, + 'SlashDamage_L_57358': { + 'hash': 57358, + 'name': 'SlashDamage_L', + 'savables': {} + }, + 'SlashDamage_R_59218': { + 'hash': 59218, + 'name': 'SlashDamage_R', + 'savables': {} + }, + 'Spawner_240': { + 'hash': 240, + 'name': 'Spawner', + 'savables': {} + }, + 'Wyrm_37044': { + 'hash': 37044, + 'name': 'Wyrm', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Wyrm_AI_46146': { + 'hash': 46146, + 'name': 'Wyrm_AI', + 'savables': {} + }, + 'scythe_l_jnt_544': { + 'hash': 544, + 'name': 'scythe_l_jnt', + 'savables': {} + }, + 'scythe_r_jnt_542': { + 'hash': 542, + 'name': 'scythe_r_jnt', + 'savables': {} + } + } + }, + 'Wyrm_(Trial)': { + 'hash': 6004, + 'name': 'Wyrm_(Trial)', + 'embedded': { + 'Animation_6144': { + 'hash': 6144, + 'name': 'Animation', + 'savables': {} + }, + 'Body_1052': { + 'hash': 1052, + 'name': 'Body', + 'savables': {} + }, + 'Gameplay_42330': { + 'hash': 42330, + 'name': 'Gameplay', + 'savables': {} + }, + 'Ground_58968': { + 'hash': 58968, + 'name': 'Ground', + 'savables': {} + }, + 'SlashDamage_L_57358': { + 'hash': 57358, + 'name': 'SlashDamage_L', + 'savables': {} + }, + 'SlashDamage_R_59218': { + 'hash': 59218, + 'name': 'SlashDamage_R', + 'savables': {} + }, + 'Spawner_240': { + 'hash': 240, + 'name': 'Spawner', + 'savables': {} + }, + 'Wyrm_(Trial)_37044': { + 'hash': 37044, + 'name': 'Wyrm_(Trial)', + 'savables': { + 'PhysicalMaterialPart': { + 'hash': 272188517, + 'name': 'PhysicalMaterialPart' + }, + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'Wyrm_AI_46146': { + 'hash': 46146, + 'name': 'Wyrm_AI', + 'savables': {} + }, + 'scythe_l_jnt_544': { + 'hash': 544, + 'name': 'scythe_l_jnt', + 'savables': {} + }, + 'scythe_r_jnt_542': { + 'hash': 542, + 'name': 'scythe_r_jnt', + 'savables': {} + } + } + }, + 'Wyrm_Arm': { + 'hash': 46340, + 'name': 'Wyrm_Arm', + 'embedded': {} + }, + 'Wyrm_Boulder_01': { + 'hash': 37174, + 'name': 'Wyrm_Boulder_01', + 'embedded': { + 'Wyrm_Boulder_01_62528': { + 'hash': 62528, + 'name': 'Wyrm_Boulder_01', + 'savables': {} + }, + 'Wyrm_Spawner_63404': { + 'hash': 63404, + 'name': 'Wyrm_Spawner', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + } + } + }, + 'Wyrm_Crystal_Spit': { + 'hash': 37926, + 'name': 'Wyrm_Crystal_Spit', + 'embedded': { + 'CrystalBall_62940': { + 'hash': 62940, + 'name': 'CrystalBall', + 'savables': {} + }, + 'Wyrm_Crystal_Spit_62050': { + 'hash': 62050, + 'name': 'Wyrm_Crystal_Spit', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Wyrm_Spit': { + 'hash': 61454, + 'name': 'Wyrm_Spit', + 'embedded': { + 'PoisonBall_34058': { + 'hash': 34058, + 'name': 'PoisonBall', + 'savables': {} + }, + 'Wyrm_Spit_62050': { + 'hash': 62050, + 'name': 'Wyrm_Spit', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + } + } + } + } + }, + 'Xnor': { + 'hash': 42418, + 'name': 'Xnor', + 'embedded': {} + }, + 'Xor': { + 'hash': 42428, + 'name': 'Xor', + 'embedded': {} + }, + 'archery_target_puzzle_test': { + 'hash': 54358, + 'name': 'archery_target_puzzle_test', + 'embedded': {} + }, + 'cam': { + 'hash': 8760, + 'name': 'cam', + 'embedded': {} + }, + 'combat_dummy': { + 'hash': 57126, + 'name': 'combat_dummy', + 'embedded': { + 'combat_dummy_57314': { + 'hash': 57314, + 'name': 'combat_dummy', + 'savables': { + 'StatManager': { + 'hash': 2563567105, + 'name': 'StatManager' + } + } + }, + 'dummy_arm_l_01_jnt_46272': { + 'hash': 46272, + 'name': 'dummy_arm_l_01_jnt', + 'savables': {} + }, + 'dummy_arm_l_02_jnt_46248': { + 'hash': 46248, + 'name': 'dummy_arm_l_02_jnt', + 'savables': {} + }, + 'dummy_arm_l_03_jnt_46250': { + 'hash': 46250, + 'name': 'dummy_arm_l_03_jnt', + 'savables': {} + }, + 'dummy_arm_r_01_jnt_46246': { + 'hash': 46246, + 'name': 'dummy_arm_r_01_jnt', + 'savables': {} + }, + 'dummy_arm_r_02_jnt_46254': { + 'hash': 46254, + 'name': 'dummy_arm_r_02_jnt', + 'savables': {} + }, + 'dummy_arm_r_03_jnt_46256': { + 'hash': 46256, + 'name': 'dummy_arm_r_03_jnt', + 'savables': {} + }, + 'dummy_head_01_jnt_46270': { + 'hash': 46270, + 'name': 'dummy_head_01_jnt', + 'savables': {} + }, + 'dummy_head_02_jnt_46264': { + 'hash': 46264, + 'name': 'dummy_head_02_jnt', + 'savables': {} + }, + 'dummy_head_03_jnt_46262': { + 'hash': 46262, + 'name': 'dummy_head_03_jnt', + 'savables': {} + }, + 'dummy_neck_jnt_46268': { + 'hash': 46268, + 'name': 'dummy_neck_jnt', + 'savables': {} + }, + 'dummy_spineMid_jnt_46274': { + 'hash': 46274, + 'name': 'dummy_spineMid_jnt', + 'savables': {} + }, + 'dummy_spine_01_jnt_46258': { + 'hash': 46258, + 'name': 'dummy_spine_01_jnt', + 'savables': {} + }, + 'dummy_spine_02_jnt_46260': { + 'hash': 46260, + 'name': 'dummy_spine_02_jnt', + 'savables': {} + }, + 'dummy_spine_03_jnt_46266': { + 'hash': 46266, + 'name': 'dummy_spine_03_jnt', + 'savables': {} + }, + 'dummy_sternum_jnt_46252': { + 'hash': 46252, + 'name': 'dummy_sternum_jnt', + 'savables': {} + } + } + }, + 'item_pedestal_puzzle_base': { + 'hash': 27250, + 'name': 'item_pedestal_puzzle_base', + 'embedded': { + 'Pedestal_Dock_27002': { + 'hash': 27002, + 'name': 'Pedestal_Dock', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + }, + 'PickupDockPedestalSpawn': { + 'hash': 2592242915, + 'name': 'PickupDockPedestalSpawn' + } + } + }, + 'item_pedestal_puzzle_base_27194': { + 'hash': 27194, + 'name': 'item_pedestal_puzzle_base', + 'savables': { + 'LogicBoolSender': { + 'hash': 1257282635, + 'name': 'LogicBoolSender' + }, + 'LogicIntSender': { + 'hash': 2880587164, + 'name': 'LogicIntSender' + }, + 'PlaceItemPuzzleLogic': { + 'hash': 1001395212, + 'name': 'PlaceItemPuzzleLogic' + } + } + } + } + }, + 'mrk_extensionBridge_01': { + 'hash': 34038, + 'name': 'mrk_extensionBridge_01', + 'embedded': { + 'mrk_extensionBridge_01_32324': { + 'hash': 32324, + 'name': 'mrk_extensionBridge_01', + 'savables': { + 'LogicFloatReceiver': { + 'hash': 3188272159, + 'name': 'LogicFloatReceiver' + }, + 'NetworkedFloatStream': { + 'hash': 2127962967, + 'name': 'NetworkedFloatStream' + } + } + }, + 'mrk_extensionBridge_bridge_01_21508': { + 'hash': 21508, + 'name': 'mrk_extensionBridge_bridge_01', + 'savables': {} + } + } + }, + 'mrk_large_lift_01': { + 'hash': 28708, + 'name': 'mrk_large_lift_01', + 'embedded': { + 'End_61234': { + 'hash': 61234, + 'name': 'End', + 'savables': {} + }, + 'Start_1586': { + 'hash': 1586, + 'name': 'Start', + 'savables': {} + }, + 'mrk_large_lift_01_49676': { + 'hash': 49676, + 'name': 'mrk_large_lift_01', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + } + } + }, + 'mrk_lift_platform_41794': { + 'hash': 41794, + 'name': 'mrk_lift_platform', + 'savables': { + 'CurveOutput': { + 'hash': 2576456808, + 'name': 'CurveOutput' + } + } + } + } + }, + 'mrk_lift_01': { + 'hash': 45646, + 'name': 'mrk_lift_01', + 'embedded': { + 'Network_Event_1_10242': { + 'hash': 10242, + 'name': 'Network_Event_1', + 'savables': {} + }, + 'Network_Event_2_10094': { + 'hash': 10094, + 'name': 'Network_Event_2', + 'savables': {} + }, + 'Reset_Receiver_54952': { + 'hash': 54952, + 'name': 'Reset_Receiver', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + } + } + }, + 'mrk_lift_01_49676': { + 'hash': 49676, + 'name': 'mrk_lift_01', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + } + } + }, + 'mrk_lift_platform_41794': { + 'hash': 41794, + 'name': 'mrk_lift_platform', + 'savables': { + 'CurveOutput': { + 'hash': 2576456808, + 'name': 'CurveOutput' + } + } + } + } + }, + 'mrk_puzzleCore_symbol_01': { + 'hash': 48100, + 'name': 'mrk_puzzleCore_symbol_01', + 'embedded': { + 'Glow_End_49116': { + 'hash': 49116, + 'name': 'Glow_End', + 'savables': {} + }, + 'Glow_Start_40754': { + 'hash': 40754, + 'name': 'Glow_Start', + 'savables': {} + }, + 'mrk_puzzleCore_symbol_01_4198': { + 'hash': 4198, + 'name': 'mrk_puzzleCore_symbol_01', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + } + } + } + } + }, + 'mrk_puzzleCore_symbol_02': { + 'hash': 48102, + 'name': 'mrk_puzzleCore_symbol_02', + 'embedded': { + 'Glow_End_39528': { + 'hash': 39528, + 'name': 'Glow_End', + 'savables': {} + }, + 'Glow_Start_39856': { + 'hash': 39856, + 'name': 'Glow_Start', + 'savables': {} + }, + 'mrk_puzzleCore_symbol_02_4422': { + 'hash': 4422, + 'name': 'mrk_puzzleCore_symbol_02', + 'savables': { + 'LogicBoolReceiver': { + 'hash': 3751351177, + 'name': 'LogicBoolReceiver' + } + } + } + } + }, + 'ore_copper': { + 'hash': 22768, + 'name': 'ore_copper', + 'embedded': {} + }, + 'ore_gold': { + 'hash': 38596, + 'name': 'ore_gold', + 'embedded': {} + }, + 'ore_iron': { + 'hash': 60876, + 'name': 'ore_iron', + 'embedded': {} + }, + 'ore_mythril': { + 'hash': 18158, + 'name': 'ore_mythril', + 'embedded': {} + }, + 'ore_silver': { + 'hash': 26988, + 'name': 'ore_silver', + 'embedded': {} + }, + 'pot_01': { + 'hash': 44028, + 'name': 'pot_01', + 'embedded': {} + }, + 'pumpkin_flower': { + 'hash': 3116, + 'name': 'pumpkin_flower', + 'embedded': { + 'pumpkin_flower_3100': { + 'hash': 3100, + 'name': 'pumpkin_flower', + 'savables': {} + } + } + }, + 'pumpkin_full_burnt': { + 'hash': 5532, + 'name': 'pumpkin_full_burnt', + 'embedded': { + 'Cooking_29838': { + 'hash': 29838, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'pumpkin_full_burnt_5096': { + 'hash': 5096, + 'name': 'pumpkin_full_burnt', + 'savables': { + 'MultiHandPickup': { + 'hash': 1556697998, + 'name': 'MultiHandPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'pumpkin_full_cooked': { + 'hash': 5010, + 'name': 'pumpkin_full_cooked', + 'embedded': { + 'Cooking_29126': { + 'hash': 29126, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'pumpkin_full_cooked_4574': { + 'hash': 4574, + 'name': 'pumpkin_full_cooked', + 'savables': { + 'MultiHandPickup': { + 'hash': 1556697998, + 'name': 'MultiHandPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'pumpkin_full_ripe': { + 'hash': 4488, + 'name': 'pumpkin_full_ripe', + 'embedded': { + 'Chisel_Handler_32690': { + 'hash': 32690, + 'name': 'Chisel_Handler', + 'savables': {} + }, + 'Cooking_28436': { + 'hash': 28436, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'pumpkin_full_ripe_4052': { + 'hash': 4052, + 'name': 'pumpkin_full_ripe', + 'savables': { + 'MultiHandPickup': { + 'hash': 1556697998, + 'name': 'MultiHandPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'pumpkin_full_unripe': { + 'hash': 3966, + 'name': 'pumpkin_full_unripe', + 'embedded': { + 'pumpkin_full_unripe_3530': { + 'hash': 3530, + 'name': 'pumpkin_full_unripe', + 'savables': { + 'MultiHandPickup': { + 'hash': 1556697998, + 'name': 'MultiHandPickup' + }, + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'pumpkin_half_burnt': { + 'hash': 3444, + 'name': 'pumpkin_half_burnt', + 'embedded': { + 'Cooking_42504': { + 'hash': 42504, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'pumpkin_half_burnt_3136': { + 'hash': 3136, + 'name': 'pumpkin_half_burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'pumpkin_half_cooked': { + 'hash': 3082, + 'name': 'pumpkin_half_cooked', + 'embedded': { + 'Cooking_41658': { + 'hash': 41658, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'pumpkin_half_cooked_2774': { + 'hash': 2774, + 'name': 'pumpkin_half_cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'pumpkin_half_ripe': { + 'hash': 2720, + 'name': 'pumpkin_half_ripe', + 'embedded': { + 'Cooking_40786': { + 'hash': 40786, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'pumpkin_half_ripe_2412': { + 'hash': 2412, + 'name': 'pumpkin_half_ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'pumpkin_half_unripe': { + 'hash': 2358, + 'name': 'pumpkin_half_unripe', + 'embedded': { + 'pumpkin_half_unripe_2050': { + 'hash': 2050, + 'name': 'pumpkin_half_unripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'pumpkin_piece_burnt': { + 'hash': 42218, + 'name': 'pumpkin_piece_burnt', + 'embedded': { + 'Cooking_63858': { + 'hash': 63858, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'pumpkin_piece_burnt_41976': { + 'hash': 41976, + 'name': 'pumpkin_piece_burnt', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'pumpkin_piece_cooked': { + 'hash': 41930, + 'name': 'pumpkin_piece_cooked', + 'embedded': { + 'Cooking_65232': { + 'hash': 65232, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'pumpkin_piece_cooked_41654': { + 'hash': 41654, + 'name': 'pumpkin_piece_cooked', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'pumpkin_piece_ripe': { + 'hash': 41608, + 'name': 'pumpkin_piece_ripe', + 'embedded': { + 'Cooking_26172': { + 'hash': 26172, + 'name': 'Cooking', + 'savables': { + 'Cookable': { + 'hash': 205333986, + 'name': 'Cookable' + }, + 'HeatPointCollection': { + 'hash': 1217391130, + 'name': 'HeatPointCollection' + } + } + }, + 'pumpkin_piece_ripe_41332': { + 'hash': 41332, + 'name': 'pumpkin_piece_ripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + } + } + } + } + }, + 'pumpkin_piece_unripe': { + 'hash': 41286, + 'name': 'pumpkin_piece_unripe', + 'embedded': { + 'pumpkin_piece_unripe_41010': { + 'hash': 41010, + 'name': 'pumpkin_piece_unripe', + 'savables': { + 'NetworkRigidbody': { + 'hash': 2290978823, + 'name': 'NetworkRigidbody' + }, + 'Pickup': { + 'hash': 1454441398, + 'name': 'Pickup' + }, + 'PickupDecay': { + 'hash': 2807522140, + 'name': 'PickupDecay' + }, + 'RaycastCrafter': { + 'hash': 2815374842, + 'name': 'RaycastCrafter' + } + } + } + } + }, + 'ruins_orbBasin_01': { + 'hash': 27482, + 'name': 'ruins_orbBasin_01', + 'embedded': { + 'Hand_Touch_46540': { + 'hash': 46540, + 'name': 'Hand_Touch', + 'savables': { + 'AddUnlockToPlayer': { + 'hash': 1756836969, + 'name': 'AddUnlockToPlayer' + }, + 'OrbBasinVfxController': { + 'hash': 715394364, + 'name': 'OrbBasinVfxController' + }, + 'PlayerUnlockStation': { + 'hash': 2912807649, + 'name': 'PlayerUnlockStation' + } + } + }, + 'ruins_orbBasin_01_24754': { + 'hash': 24754, + 'name': 'ruins_orbBasin_01', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + } + } + }, + 'ruins_orbBasin_01TEST': { + 'hash': 58180, + 'name': 'ruins_orbBasin_01TEST', + 'embedded': { + 'Hand_Touch_46540': { + 'hash': 46540, + 'name': 'Hand_Touch', + 'savables': { + 'AddUnlockToPlayer': { + 'hash': 1756836969, + 'name': 'AddUnlockToPlayer' + }, + 'OrbBasinVfxController': { + 'hash': 715394364, + 'name': 'OrbBasinVfxController' + }, + 'PlayerUnlockStation': { + 'hash': 2912807649, + 'name': 'PlayerUnlockStation' + } + } + }, + 'ruins_orbBasin_01TEST_58178': { + 'hash': 58178, + 'name': 'ruins_orbBasin_01TEST', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + } + } + }, + 'ruins_orbBasin_01_Variant': { + 'hash': 13294, + 'name': 'ruins_orbBasin_01_Variant', + 'embedded': { + 'Hand_Touch_46540': { + 'hash': 46540, + 'name': 'Hand_Touch', + 'savables': { + 'AddUnlockToPlayer': { + 'hash': 1756836969, + 'name': 'AddUnlockToPlayer' + }, + 'OrbBasinVfxController': { + 'hash': 715394364, + 'name': 'OrbBasinVfxController' + }, + 'PlayerUnlockStation': { + 'hash': 2912807649, + 'name': 'PlayerUnlockStation' + } + } + }, + 'ruins_orbBasin_01_Variant_24754': { + 'hash': 24754, + 'name': 'ruins_orbBasin_01_Variant', + 'savables': { + 'AdditionalStaticContent': { + 'hash': 1908922854, + 'name': 'AdditionalStaticContent' + } + } + } + } + }, + 'tallPot': { + 'hash': 23320, + 'name': 'tallPot', + 'embedded': {} + }, + 'timberBlock_1Long': { + 'hash': 34586, + 'name': 'timberBlock_1Long', + 'embedded': { + 'timberBlock_1Long_46178': { + 'hash': 46178, + 'name': 'timberBlock_1Long', + 'savables': {} + } + } + }, + 'timberBlock_2Long': { + 'hash': 1898, + 'name': 'timberBlock_2Long', + 'embedded': { + 'timberBlock_2Long_372': { + 'hash': 372, + 'name': 'timberBlock_2Long', + 'savables': {} + } + } + }, + 'timberBlock_3Long': { + 'hash': 1900, + 'name': 'timberBlock_3Long', + 'embedded': { + 'timberBlock_3Long_376': { + 'hash': 376, + 'name': 'timberBlock_3Long', + 'savables': {} + } + } + }, + 'woodenPlatform_1x1': { + 'hash': 50942, + 'name': 'woodenPlatform_1x1', + 'embedded': { + 'woodenPlatform_1x1_4914': { + 'hash': 4914, + 'name': 'woodenPlatform_1x1', + 'savables': {} + } + } + }, + 'woodenPlatform_1x1_Torch': { + 'hash': 64260, + 'name': 'woodenPlatform_1x1_Torch', + 'embedded': { + 'Torch_Dock_15254': { + 'hash': 15254, + 'name': 'Torch_Dock', + 'savables': { + 'PickupDock': { + 'hash': 2592242915, + 'name': 'PickupDock' + } + } + }, + 'woodenPlatform_1x1_Torch_64256': { + 'hash': 64256, + 'name': 'woodenPlatform_1x1_Torch', + 'savables': {} + } + } + }, + 'woodenPlatform_1x2': { + 'hash': 50950, + 'name': 'woodenPlatform_1x2', + 'embedded': { + 'woodenPlatform_1x2_4598': { + 'hash': 4598, + 'name': 'woodenPlatform_1x2', + 'savables': {} + } + } + }, + 'woodenPlatform_Railings_1x1': { + 'hash': 50946, + 'name': 'woodenPlatform_Railings_1x1', + 'embedded': { + 'woodenPlatform_Railings_1x1_4200': { + 'hash': 4200, + 'name': 'woodenPlatform_Railings_1x1', + 'savables': {} + } + } + }, + 'woodenPlatform_Stairs_02': { + 'hash': 50940, + 'name': 'woodenPlatform_Stairs_02', + 'embedded': { + 'woodenPlatform_Stairs_02_3900': { + 'hash': 3900, + 'name': 'woodenPlatform_Stairs_02', + 'savables': {} + } + } + }, + 'woodenPlatform_T2x1': { + 'hash': 50944, + 'name': 'woodenPlatform_T2x1', + 'embedded': { + 'woodenPlatform_T2x1_3592': { + 'hash': 3592, + 'name': 'woodenPlatform_T2x1', + 'savables': {} + } + } + }, + 'woodenPlatform_T2x1_1': { + 'hash': 50930, + 'name': 'woodenPlatform_T2x1_1', + 'embedded': { + 'woodenPlatform_T2x1_1_3278': { + 'hash': 3278, + 'name': 'woodenPlatform_T2x1_1', + 'savables': {} + } + } + }, + 'woodenPlatform_W2x2': { + 'hash': 50932, + 'name': 'woodenPlatform_W2x2', + 'embedded': { + 'woodenPlatform_W2x2_2856': { + 'hash': 2856, + 'name': 'woodenPlatform_W2x2', + 'savables': {} + } + } + }, + 'woodenPlatform_W2x3': { + 'hash': 10176, + 'name': 'woodenPlatform_W2x3', + 'embedded': { + 'Breakable_Population_Area_32244': { + 'hash': 32244, + 'name': 'Breakable_Population_Area', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + }, + 'woodenPlatform_W2x3_10188': { + 'hash': 10188, + 'name': 'woodenPlatform_W2x3', + 'savables': {} + } + } + }, + 'woodenPlatform_W2x4': { + 'hash': 33664, + 'name': 'woodenPlatform_W2x4', + 'embedded': { + 'Breakable_Population_Area_35954': { + 'hash': 35954, + 'name': 'Breakable_Population_Area', + 'savables': { + 'PopulationSpawnArea': { + 'hash': 3070493599, + 'name': 'PopulationSpawnArea' + }, + 'SpawnArea': { + 'hash': 2617495528, + 'name': 'SpawnArea' + } + } + }, + 'woodenPlatform_W2x4_33680': { + 'hash': 33680, + 'name': 'woodenPlatform_W2x4', + 'savables': {} + } + } + } +} as const; diff --git a/src/types/AngularVelocity.ts b/src/types/AngularVelocity.ts new file mode 100644 index 0000000..44fbafe --- /dev/null +++ b/src/types/AngularVelocity.ts @@ -0,0 +1,5 @@ +export type AngularVelocity = { + x: number; + y: number; + z: number; +}; diff --git a/src/types/BinaryString.ts b/src/types/BinaryString.ts new file mode 100644 index 0000000..68f591d --- /dev/null +++ b/src/types/BinaryString.ts @@ -0,0 +1 @@ +export type BinaryString = string & { 'asserted with BinaryData.isBinaryString()': null }; diff --git a/src/ComponentHash.ts b/src/types/ComponentHash.ts similarity index 91% rename from src/ComponentHash.ts rename to src/types/ComponentHash.ts index 2900544..3d062ec 100644 --- a/src/ComponentHash.ts +++ b/src/types/ComponentHash.ts @@ -1,5 +1,7 @@ export enum ComponentHash { // AdditionalOwnedDock = 2592242915, // Duplicate of PickupDock. + AdditionalStaticContent = 1908922854, + AreaOfInfluenceReceiver = 309083880, BasicDecay = 3801256786, BasicDynamicPath = 1624211074, BasicPopulationFolder = 1931537627, @@ -22,6 +24,7 @@ export enum ComponentHash { Cookable = 205333986, CookingPot = 2882590463, Crank = 1588536425, + CurveOutput = 2576456808, CylindricalBoundsSurface = 34507654, DiggingImpactor = 3445325106, DirectionalBoundsSurface = 1962842866, @@ -32,9 +35,11 @@ export enum ComponentHash { DurabilityModule = 1871432223, Ecosystem = 259381630, Embeddable = 22446553, + Enchantable = 4134534481, EnergyBasedHeatSource = 2721336102, Fire = 3457519710, // FireDissolve = 3457519710, // Duplicate of Fire. + FireLogic = 1509838052, FireStatusRaycastCrafter = 2718386020, ForestGenerator = 875684520, ForgedPointCollection = 2272630171, @@ -70,6 +75,7 @@ export enum ComponentHash { LockableHinge = 1587058252, LogicBoolReceiver = 3751351177, LogicBoolSender = 1257282635, + LogicFloatChangeOnBool = 200292695, LogicFloatRangeReceiver = 2700376822, LogicFloatReceiver = 3188272159, LogicFloatReset = 3245685963, @@ -80,14 +86,18 @@ export enum ComponentHash { LogicIntReceiver = 1081247904, LogicIntSender = 2880587164, LogicIntThresholdReceiver = 2563434699, + LogicReset = 1934129787, LogicSumFloatReceiver = 2814234626, LogicSumIntReceiver = 1964978567, 'LogicValueSender`1' = 3810525047, LogicVector3Receiver = 1228539097, LogicVector3Sender = 2026743731, + LogicIntToBool = 2253011220, LootModule = 634164392, + MRK_ActivationLever = 2069630919, MapBoard = 2443660852, MeshPlacement = 2169673426, + ModifiableAdditionalStaticContent = 159391088, ModifiableStaticManager = 3674519521, Mould = 391977879, MouldRestrictor = 1571096900, @@ -97,6 +107,7 @@ export enum ComponentHash { NetworkedFloatStream = 2127962967, NetworkRigidbody = 2290978823, OfflinePlayerProgressionHandler = 2293737711, + OneTimeUpgradeuinteraction = 3230087383, PageInstance = 1923918202, PaperPageInstance = 2241532968, PhysicalMaterialPart = 272188517, @@ -106,11 +117,13 @@ export enum ComponentHash { PlaceItemNoDockFirePuzzleLogic = 2495475500, PlaceItemNoDockPuzzleLogic = 1176706580, PlaceItemPuzzleLogic = 1001395212, + PlayerDetect = 403040752, PlayerInteractionManager = 1211178616, PlayerInteractionRestrictor = 2951515968, PlayerLandmark = 1946741389, PlayerProxy = 1233775263, PlayerStatManager = 2743469720, + PlayerUnlockStation = 2912807649, PopulationDefinitionManager = 2978388169, PopulationFolder = 1431397437, 'PopulationFolder`2' = 986260983, @@ -122,6 +135,7 @@ export enum ComponentHash { RaycastCrafter = 2815374842, Recycler = 2450553269, RepairBox = 3820454400, + RespawnOnDestroy = 830106687, RockCluster = 1651678475, RopeGrab = 237360636, RotatePickup = 2498617949, diff --git a/src/types/EntityKey.ts b/src/types/EntityKey.ts new file mode 100644 index 0000000..c544f47 --- /dev/null +++ b/src/types/EntityKey.ts @@ -0,0 +1,7 @@ +import type { ATTPrefabName } from './ATTPrefabName.js'; + +import { ATTPrefabs } from './ATTPrefabs.js'; + +export type EntityKey = + | keyof (typeof ATTPrefabs)[TPrefabName]['embedded'] + | 'Unknown'; diff --git a/src/types/LogicOperator.ts b/src/types/LogicOperator.ts new file mode 100644 index 0000000..38da85e --- /dev/null +++ b/src/types/LogicOperator.ts @@ -0,0 +1,7 @@ +export enum LogicOperator { + And = 0, + Or = 1, + Xor = 2, + Nand = 3, + Toggle = 4 +} diff --git a/src/PhysicalMaterialPartHash.ts b/src/types/PhysicalMaterialPartHash.ts similarity index 96% rename from src/PhysicalMaterialPartHash.ts rename to src/types/PhysicalMaterialPartHash.ts index 9712c1f..57b786d 100644 --- a/src/PhysicalMaterialPartHash.ts +++ b/src/types/PhysicalMaterialPartHash.ts @@ -8,6 +8,7 @@ export enum PhysicalMaterialPartHash { Copper = 20186, DaisLeather = 33384, DaisRedLeather = 37850, + DarkSteelAlloy = 55232, EvinonSteelAlloy = 31502, Gold = 56394, Iron = 1, diff --git a/src/PopulationDefinitionHash.ts b/src/types/PopulationDefinitionHash.ts similarity index 100% rename from src/PopulationDefinitionHash.ts rename to src/types/PopulationDefinitionHash.ts diff --git a/src/types/PopulationDefinitionName.ts b/src/types/PopulationDefinitionName.ts new file mode 100644 index 0000000..ddf3622 --- /dev/null +++ b/src/types/PopulationDefinitionName.ts @@ -0,0 +1,3 @@ +import type { PopulationDefinitionHash } from './PopulationDefinitionHash.js'; + +export type PopulationDefinitionName = keyof typeof PopulationDefinitionHash; diff --git a/src/types/Position.ts b/src/types/Position.ts new file mode 100644 index 0000000..a6b48c5 --- /dev/null +++ b/src/types/Position.ts @@ -0,0 +1,5 @@ +export type Position = { + x: number; + y: number; + z: number; +}; diff --git a/src/types/PrefabChild.ts b/src/types/PrefabChild.ts new file mode 100644 index 0000000..67faf40 --- /dev/null +++ b/src/types/PrefabChild.ts @@ -0,0 +1,6 @@ +import type { Prefab } from '../Prefab.js'; + +export type PrefabChild = { + parentHash: number; + prefab: Prefab; +}; diff --git a/src/types/PrefabComponents.ts b/src/types/PrefabComponents.ts new file mode 100644 index 0000000..0247697 --- /dev/null +++ b/src/types/PrefabComponents.ts @@ -0,0 +1,5 @@ +import type { SupportedPrefabComponents } from './SupportedPrefabComponents.js'; +import type { UnknownPrefabComponents } from './UnknownPrefabComponents.js'; +import type { UnsupportedPrefabComponents } from './UnsupportedPrefabComponents.js'; + +export type PrefabComponents = SupportedPrefabComponents & UnsupportedPrefabComponents & UnknownPrefabComponents; diff --git a/src/types/PrefabEntities.ts b/src/types/PrefabEntities.ts new file mode 100644 index 0000000..f7e8d20 --- /dev/null +++ b/src/types/PrefabEntities.ts @@ -0,0 +1,6 @@ +import type { ATTPrefabName } from './ATTPrefabName.js'; +import type { Entity } from '../Entity.js'; + +export type PrefabEntities = { + [EntityName: string]: Entity; +}; diff --git a/src/PresetHash.ts b/src/types/PresetHash.ts similarity index 100% rename from src/PresetHash.ts rename to src/types/PresetHash.ts diff --git a/src/types/Rotation.ts b/src/types/Rotation.ts new file mode 100644 index 0000000..37d45cb --- /dev/null +++ b/src/types/Rotation.ts @@ -0,0 +1,6 @@ +export type Rotation = { + x: number; + y: number; + z: number; + w: number; +}; diff --git a/src/types/SaveString.ts b/src/types/SaveString.ts new file mode 100644 index 0000000..201b12e --- /dev/null +++ b/src/types/SaveString.ts @@ -0,0 +1 @@ +export type SaveString = string & { 'asserted with BinaryData.isSaveString()': null }; diff --git a/src/types/SetSpawnAreaProps.ts b/src/types/SetSpawnAreaProps.ts new file mode 100644 index 0000000..e095dc2 --- /dev/null +++ b/src/types/SetSpawnAreaProps.ts @@ -0,0 +1,13 @@ +import type { PopulationSpawnAreaComponentProps } from '../components/PopulationSpawnAreaComponent.js'; +import type { SpawnAreaComponentProps } from '../components/SpawnAreaComponent.js'; + +export type SetSpawnAreaProps = Pick< + PopulationSpawnAreaComponentProps, + | 'currentPopulation' + | 'isOneOff' + | 'isPopulationStarted' + | 'maxPopulation' + | 'numberOfSpawnPoints' + | 'startingPopulation' +> & + Pick; diff --git a/src/SpeciesHash.ts b/src/types/SpeciesHash.ts similarity index 100% rename from src/SpeciesHash.ts rename to src/types/SpeciesHash.ts diff --git a/src/types/SupportedComponent.ts b/src/types/SupportedComponent.ts new file mode 100644 index 0000000..af186da --- /dev/null +++ b/src/types/SupportedComponent.ts @@ -0,0 +1,55 @@ +import type { LogicIntSenderComponent } from '../components/LogicIntSenderComponent.js'; + +import { BasicDecayComponent } from '../components/BasicDecayComponent.js'; +import { DoorComponent } from '../components/DoorComponent.js'; +import { DurabilityModuleComponent } from '../components/DurabilityModuleComponent.js'; +import { FireComponent } from '../components/FireComponent.js'; +import { FuseComponent } from '../components/FuseComponent.js'; +import { HeatSourceBaseComponent } from '../components/HeatSourceBaseComponent.js'; +import { LiquidContainerComponent } from '../components/LiquidContainerComponent.js'; +import { LogicBoolReceiverComponent } from '../components/LogicBoolReceiverComponent.js'; +import { LogicBoolSenderComponent } from '../components/LogicBoolSenderComponent.js'; +import { LogicFloatReceiverComponent } from '../components/LogicFloatReceiverComponent.js'; +import { LogicFloatSenderComponent } from '../components/LogicFloatSenderComponent.js'; +import { LogicGateReceiverComponent } from '../components/LogicGateReceiverComponent.js'; +import { LogicIntReceiverComponent } from '../components/LogicIntReceiverComponent.js'; +import { LogicVector3ReceiverComponent } from '../components/LogicVector3ReceiverComponent.js'; +import { LogicVector3SenderComponent } from '../components/LogicVector3SenderComponent.js'; +import { NetworkRigidbodyComponent } from '../components/NetworkRigidbodyComponent.js'; +import { PhysicalMaterialPartComponent } from '../components/PhysicalMaterialPartComponent.js'; +import { PickupComponent } from '../components/PickupComponent.js'; +import { PickupDockComponent } from '../components/PickupDockComponent.js'; +import { PopulationSpawnAreaComponent } from '../components/PopulationSpawnAreaComponent.js'; +import { SentGiftComponent } from '../components/SentGiftComponent.js'; +import { SlidingDoorComponent } from '../components/SlidingDoorComponent.js'; +import { SpawnAreaComponent } from '../components/SpawnAreaComponent.js'; +import { StatManagerComponent } from '../components/StatManagerComponent.js'; +import { WoodcutTreeComponent } from '../components/WoodcutTreeComponent.js'; + +export type SupportedComponent = + | typeof BasicDecayComponent + | typeof DoorComponent + | typeof DurabilityModuleComponent + | typeof FireComponent + | typeof FuseComponent + | typeof HeatSourceBaseComponent + | typeof LiquidContainerComponent + | typeof LogicBoolReceiverComponent + | typeof LogicBoolSenderComponent + | typeof LogicFloatReceiverComponent + | typeof LogicFloatSenderComponent + | typeof LogicGateReceiverComponent + | typeof LogicIntReceiverComponent + | typeof LogicIntSenderComponent + | typeof LogicVector3ReceiverComponent + | typeof LogicVector3SenderComponent + | typeof NetworkRigidbodyComponent + | typeof PhysicalMaterialPartComponent + | typeof PickupComponent + | typeof PickupDockComponent + | typeof PopulationSpawnAreaComponent + | typeof SentGiftComponent + | typeof SlidingDoorComponent + | typeof SpawnAreaComponent + | typeof StatManagerComponent + | typeof WoodcutTreeComponent; diff --git a/src/types/SupportedPrefabComponents.ts b/src/types/SupportedPrefabComponents.ts new file mode 100644 index 0000000..c0be69a --- /dev/null +++ b/src/types/SupportedPrefabComponents.ts @@ -0,0 +1,55 @@ +import type { BasicDecayComponent } from '../components/BasicDecayComponent.js'; +import type { DoorComponent } from '../components/DoorComponent.js'; +import type { DurabilityModuleComponent } from '../components/DurabilityModuleComponent.js'; +import type { FireComponent } from '../components/FireComponent.js'; +import type { FuseComponent } from '../components/FuseComponent.js'; +import type { HeatSourceBaseComponent } from '../components/HeatSourceBaseComponent.js'; +import type { LiquidContainerComponent } from '../components/LiquidContainerComponent.js'; +import type { LogicBoolReceiverComponent } from '../components/LogicBoolReceiverComponent.js'; +import type { LogicBoolSenderComponent } from '../components/LogicBoolSenderComponent.js'; +import type { LogicFloatReceiverComponent } from '../components/LogicFloatReceiverComponent.js'; +import type { LogicFloatSenderComponent } from '../components/LogicFloatSenderComponent.js'; +import type { LogicGateReceiverComponent } from '../components/LogicGateReceiverComponent.js'; +import type { LogicIntReceiverComponent } from '../components/LogicIntReceiverComponent.js'; +import type { LogicIntSenderComponent } from '../components/LogicIntSenderComponent.js'; +import type { LogicVector3ReceiverComponent } from '../components/LogicVector3ReceiverComponent.js'; +import type { LogicVector3SenderComponent } from '../components/LogicVector3SenderComponent.js'; +import type { NetworkRigidbodyComponent } from '../components/NetworkRigidbodyComponent.js'; +import type { PhysicalMaterialPartComponent } from '../components/PhysicalMaterialPartComponent.js'; +import type { PickupComponent } from '../components/PickupComponent.js'; +import type { PickupDockComponent } from '../components/PickupDockComponent.js'; +import type { PopulationSpawnAreaComponent } from '../components/PopulationSpawnAreaComponent.js'; +import type { SentGiftComponent } from '../components/SentGiftComponent.js'; +import type { SlidingDoorComponent } from '../components/SlidingDoorComponent.js'; +import type { SpawnAreaComponent } from '../components/SpawnAreaComponent.js'; +import type { StatManagerComponent } from '../components/StatManagerComponent.js'; +import type { WoodcutTreeComponent } from '../components/WoodcutTreeComponent.js'; + +export type SupportedPrefabComponents = { + BasicDecay?: BasicDecayComponent; + Door?: DoorComponent; + DurabilityModule?: DurabilityModuleComponent; + Fire?: FireComponent; + Fuse?: FuseComponent; + HeatSourceBase?: HeatSourceBaseComponent; + LiquidContainer?: LiquidContainerComponent; + LogicBoolReceiver?: LogicBoolReceiverComponent; + LogicBoolSender?: LogicBoolSenderComponent; + LogicFloatReceiver?: LogicFloatReceiverComponent; + LogicFloatSender?: LogicFloatSenderComponent; + LogicGateReceiver?: LogicGateReceiverComponent; + LogicIntReceiver?: LogicIntReceiverComponent; + LogicIntSender?: LogicIntSenderComponent; + LogicVector3Receiver?: LogicVector3ReceiverComponent; + LogicVector3Sender?: LogicVector3SenderComponent; + NetworkRigidbody?: NetworkRigidbodyComponent; + PhysicalMaterialPart?: PhysicalMaterialPartComponent; + Pickup?: PickupComponent; + PickupDock?: PickupDockComponent; + PopulationSpawnArea?: PopulationSpawnAreaComponent; + SentGift?: SentGiftComponent; + SlidingDoor?: SlidingDoorComponent; + SpawnArea?: SpawnAreaComponent; + StatManager?: StatManagerComponent; + WoodcutTree?: WoodcutTreeComponent; +}; diff --git a/src/types/UnknownPrefabComponents.ts b/src/types/UnknownPrefabComponents.ts new file mode 100644 index 0000000..0ff80cc --- /dev/null +++ b/src/types/UnknownPrefabComponents.ts @@ -0,0 +1,3 @@ +import type { UnsupportedComponent } from '../components/UnsupportedComponent.js'; + +export type UnknownPrefabComponents = { Unknown: UnsupportedComponent[] }; diff --git a/src/types/UnsupportedPrefabComponents.ts b/src/types/UnsupportedPrefabComponents.ts new file mode 100644 index 0000000..5c1bd24 --- /dev/null +++ b/src/types/UnsupportedPrefabComponents.ts @@ -0,0 +1,9 @@ +import type { ComponentHash } from './ComponentHash.js'; +import type { SupportedPrefabComponents } from './SupportedPrefabComponents.js'; +import type { UnsupportedComponent } from '../components/UnsupportedComponent.js'; + +type ComponentName = keyof typeof ComponentHash; + +type UnsupportedComponentName = Exclude; + +export type UnsupportedPrefabComponents = { [K in UnsupportedComponentName]?: UnsupportedComponent }; diff --git a/src/types/Velocity.ts b/src/types/Velocity.ts new file mode 100644 index 0000000..f427b1f --- /dev/null +++ b/src/types/Velocity.ts @@ -0,0 +1,5 @@ +export type Velocity = { + x: number; + y: number; + z: number; +}; diff --git a/src/utils/binaryToInt.ts b/src/utils/binaryToInt.ts deleted file mode 100644 index c559f02..0000000 --- a/src/utils/binaryToInt.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const binaryToInt = (binary: string): number => { - const isPositive = Boolean(Number(binary.slice(0, 1))); - const integer = Number(`0b0${binary.slice(1)}`); - - return isPositive ? integer : integer - 2147483648; -}; diff --git a/src/utils/binaryToNumber.ts b/src/utils/binaryToNumber.ts deleted file mode 100644 index 3f79a12..0000000 --- a/src/utils/binaryToNumber.ts +++ /dev/null @@ -1 +0,0 @@ -export const binaryToNumber = (binary: string): number => Number(`0b${binary}`); diff --git a/src/utils/binaryToUIntArray.ts b/src/utils/binaryToUIntArray.ts deleted file mode 100644 index 09e96fd..0000000 --- a/src/utils/binaryToUIntArray.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { binaryToNumber } from './binaryToNumber'; - -export const binaryToUIntArray = (binary: string): number[] => { - if (binary.length % 32 !== 0) throw Error('Cannot convert binary to UInts. Bit count is not divisible by 32.'); - - return binary.match(/.{32}/g)?.map(bits => binaryToNumber(bits)) ?? []; -}; diff --git a/src/utils/binaryToULong.ts b/src/utils/binaryToULong.ts deleted file mode 100644 index 2619031..0000000 --- a/src/utils/binaryToULong.ts +++ /dev/null @@ -1 +0,0 @@ -export const binaryToULong = (binary: string): number => Number(`0b${binary.slice(32)}${binary.slice(0, 32)}`); diff --git a/src/utils/createBinaryReader.ts b/src/utils/createBinaryReader.ts deleted file mode 100644 index 1a3eb95..0000000 --- a/src/utils/createBinaryReader.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { binaryToNumber } from './binaryToNumber'; -import { binaryToInt } from './binaryToInt'; -import { binaryToULong } from './binaryToULong'; -import { unpackFloat } from './unpackFloat'; - -type Index = { current: number }; - -export type BinaryReader = { - binary: (bits: number) => string; - boolean: () => boolean; - uInt: () => number; - uShort: () => number; - uLong: () => number; - float: () => number; - int: () => number; - char: () => string; - string: () => string; -}; - -export const createBinaryReader = (binary: string): BinaryReader => { - const index: Index = { current: 0 }; - const size = binary.length; - - return { - binary: function (bits) { - if (index.current + bits > size) { - throw Error(`Cannot read ${bits} bits from binary at index ${index.current}. Binary is only ${size} bits.`); - } - - return binary.slice(index.current, (index.current += bits)); - }, - - boolean: function () { - const bit = this.binary(1); - - return Boolean(Number(bit)); - }, - - uInt: function () { - const bits = this.binary(32); - - return binaryToNumber(bits); - }, - - uShort: function () { - const bits = this.binary(16); - - return binaryToNumber(bits); - }, - - uLong: function () { - const bits = this.binary(64); - - return binaryToULong(bits); - }, - - float: function () { - const uInt = this.uInt(); - - return unpackFloat(uInt); - }, - - int: function () { - const bits = this.binary(32); - - return binaryToInt(bits); - }, - - char: function () { - const bits = this.binary(8); - const charCode = binaryToNumber(bits); - - return String.fromCharCode(charCode); - }, - - string: function () { - const length = this.uShort(); - - if (length === 0) return ''; - - /* Align bits. */ - const offset = index.current % 8 === 0 ? 0 : 8 - (index.current % 8); - - if (offset > 0) this.binary(offset); - - let currentByte = (index.current % 32) / 8; - - /* Read garbled text from binary. */ - let textBuffer = ''; - - while (textBuffer.length < length) { - textBuffer += this.char(); - } - - /* Untangle garbled text. */ - let text = ''; - let bufferIndex = 0; - - while (currentByte < 4 && bufferIndex < length) { - text += textBuffer[bufferIndex++]; - currentByte++; - } - - while (bufferIndex + 4 <= length) { - const chars = textBuffer.substr(bufferIndex, 4); - - text += chars.split('').reverse().join(''); - bufferIndex += 4; - } - - while (bufferIndex < length) { - text += textBuffer[bufferIndex++]; - } - - return text; - } - }; -}; diff --git a/src/utils/createBinaryWriter.ts b/src/utils/createBinaryWriter.ts deleted file mode 100644 index dae45e1..0000000 --- a/src/utils/createBinaryWriter.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { floatToBinary } from './floatToBinary'; -import { uShortToBinary } from './uShortToBinary'; -import { uLongToBinary } from './uLongToBinary'; -import { intToBinary } from './intToBinary'; -import { uIntToBinary } from './uIntToBinary'; -import { numberToBinary } from './numberToBinary'; - -export type BinaryWriter = { - binary: (bits: string) => void; - boolean: (bit: boolean) => void; - uInt: (number: number) => void; - uShort: (number: number) => void; - uLong: (number: number) => void; - float: (number: number) => void; - int: (number: number) => void; - char: (char: string) => void; - string: (text: string) => void; - flush: () => string; -}; - -export const createBinaryWriter = (): BinaryWriter => { - let binary: string = ''; - - return { - binary: function (bits: string): void { - binary += bits; - }, - - boolean: function (bit: boolean) { - binary += Number(bit).toString(); - }, - - uInt: function (number: number) { - binary += uIntToBinary(number); - }, - - uShort: function (number: number) { - binary += uShortToBinary(number); - }, - - uLong: function (number: number) { - binary += uLongToBinary(number); - }, - - float: function (number: number) { - binary += floatToBinary(number); - }, - - int: function (number: number) { - binary += intToBinary(number); - }, - - char: function (char: string) { - const charCode = char.charCodeAt(0); - const bits = numberToBinary(charCode).padStart(8, '0'); - - binary += bits; - }, - - string: function (textBuffer: string) { - this.uShort(textBuffer.length); - - if (textBuffer.length === 0) return; - - /* Align bits. */ - const index = binary.length; - const offset = index % 8 === 0 ? 0 : 8 - (index % 8); - - if (offset > 0) { - const align = '0'.repeat(offset); - - this.binary(align); - } - - let currentByte = (binary.length % 32) / 8; - - /* Garble text, ATT style. */ - let text = ''; - let bufferIndex = 0; - - while (currentByte < 4 && bufferIndex < textBuffer.length) { - text += textBuffer[bufferIndex++]; - currentByte++; - } - - while (bufferIndex + 4 <= textBuffer.length) { - const chars = textBuffer.substr(bufferIndex, 4); - - text += chars.split('').reverse().join(''); - bufferIndex += 4; - } - - while (bufferIndex < textBuffer.length) { - text += textBuffer[bufferIndex++]; - } - - for (const letter of text) { - this.char(letter); - } - }, - - flush: function () { - const result = binary; - binary = ''; - - return result; - } - }; -}; diff --git a/src/utils/createRandomTree.ts b/src/utils/createRandomTree.ts deleted file mode 100644 index 917f768..0000000 --- a/src/utils/createRandomTree.ts +++ /dev/null @@ -1,393 +0,0 @@ -import { ChildPrefab, PrefabData } from '../decoders'; -import { Prefab } from '../Prefab'; -import { SpeciesHash } from '../SpeciesHash'; - -type SegmentName = - | typeof ROOTS[number] - | typeof TRUNKS[number] - | typeof BRANCHES[number] - | typeof STICKS[number] - | typeof TWIGS[number] - | typeof ASH_LEAVES[number] - | typeof BIRCH_LEAVES[number] - | typeof OAK_LEAVES[number] - | typeof REDWOOD_LEAVES[number] - | typeof WALNUT_LEAVES[number]; - -type EmbeddedEntities = typeof Prefab[SegmentName]['embedded']; - -type Keys = T extends typeof Prefab | EmbeddedEntities ? keyof T : never; - -type ConnectionCandidates = [Keys, SegmentName[]]; - -type Segment = { [key in SegmentName]?: Connections }; - -type Connections = { [key in Keys]?: Segment }; - -type CompositionMap = { [segment in SegmentName]?: { [entity in Keys]?: readonly SegmentName[] } }; - -const ROOTS = [ - 'Woodcut_Root_V1_T0', - 'Woodcut_Root_V1_T0_B15', - 'Woodcut_Root_V1_T0_S30', - 'Woodcut_Root_V1_T30', - 'Woodcut_BranchRoot_V1_B0', - 'Woodcut_BranchRoot_V1_B15_S30' -] as const; - -const TRUNKS = [ - 'Woodcut_T0_B0_B30', - 'Woodcut_T0_B15_B30', - 'Woodcut_T0_T0', - 'Woodcut_T0_T0_B30', - 'Woodcut_T0_T0_B45', - 'Woodcut_T0_T0_S30', - 'Woodcut_T0_T0_S30_S30_S30', - 'Woodcut_T15_T15', - 'Woodcut_T30_T30', - 'Woodcut_T5_T5' -] as const; - -const TRUNK_TERMINATORS = ['Woodcut_T0_B0_B30', 'Woodcut_T0_B15_B30'] as const; - -const BRANCHES = [ - 'Woodcut_B0_B0', - 'Woodcut_B0_B0_S15', - 'Woodcut_B0_B15_B30', - 'Woodcut_B0_S0_S30', - 'Woodcut_B15_B15', - 'Woodcut_B30_B30', - 'Woodcut_B5_B5' -] as const; - -const BRANCH_TERMINATORS = ['Woodcut_B0_S0_S30'] as const; - -const STICKS = ['Woodcut_S0_S0', 'Woodcut_S0_S15_S15'] as const; - -const TWIGS = [ - 'Woodcut_Twigs_V1_-30', - 'Woodcut_Twigs_V1_0', - 'Woodcut_Twigs_V1_30', - 'Woodcut_Twigs_V2_-30', - 'Woodcut_Twigs_V2_0', - 'Woodcut_Twigs_V2_30', - 'Woodcut_Twigs_V3_-30', - 'Woodcut_Twigs_V3_0', - 'Woodcut_Twigs_V3_30', - 'Woodcut_Twigs_V4_0', - 'Woodcut_Twigs_V4_30', - 'Woodcut_Twigs_V5_-15', - 'Woodcut_Twigs_V5_15', - 'Woodcut_Twigs_V5_L15', - 'Woodcut_Twigs_V5_R15' -] as const; - -const ASH_LEAVES = [ - 'Woodcut_Ash_LeafClump_Base', - 'Woodcut_Ash_LeafClump_C1C1', - 'Woodcut_Ash_LeafClump_C1C2', - 'Woodcut_Ash_LeafClump_C1C2_E', - 'Woodcut_Ash_LeafClump_C1_E', - 'Woodcut_Ash_LeafClump_C1_E_1', - 'Woodcut_Ash_LeafClump_C1_E_2', - 'Woodcut_Ash_LeafClump_C2C2', - 'Woodcut_Ash_LeafClump_C2C3', - 'Woodcut_Ash_LeafClump_C2C3_E', - 'Woodcut_Ash_LeafClump_C2_E', - 'Woodcut_Ash_LeafClump_C2_E_1', - 'Woodcut_Ash_LeafClump_C3C3', - 'Woodcut_Ash_LeafClump_C3_E' -] as const; - -const BIRCH_LEAVES = [ - 'Woodcut_Birch_LeafClump_Base', - 'Woodcut_Birch_LeafClump_C1C1_1', - 'Woodcut_Birch_LeafClump_C1C1_1_E', - 'Woodcut_Birch_LeafClump_C1C1_2', - 'Woodcut_Birch_LeafClump_C1C1_2_E', - 'Woodcut_Birch_LeafClump_C1C2_1', - 'Woodcut_Birch_LeafClump_C1C2_1_E', - 'Woodcut_Birch_LeafClump_C1C2_2', - 'Woodcut_Birch_LeafClump_C1C2_2_E', - 'Woodcut_Birch_LeafClump_C1_E', - 'Woodcut_Birch_LeafClump_C2C3_1', - 'Woodcut_Birch_LeafClump_C2C3_1_E', - 'Woodcut_Birch_LeafClump_C2C3_2', - 'Woodcut_Birch_LeafClump_C2C3_2_E', - 'Woodcut_Birch_LeafClump_C2_E', - 'Woodcut_Birch_LeafClump_C3C4_1', - 'Woodcut_Birch_LeafClump_C3C4_1_E', - 'Woodcut_Birch_LeafClump_C3C4_2', - 'Woodcut_Birch_LeafClump_C3C4_2_E', - 'Woodcut_Birch_LeafClump_C3_E', - 'Woodcut_Birch_LeafClump_C4_E' -] as const; - -const OAK_LEAVES = [ - 'Woodcut_Oak_LeafClump_Base', - 'Woodcut_Oak_LeafClump_C1C1_1', - 'Woodcut_Oak_LeafClump_C1C1_2', - 'Woodcut_Oak_LeafClump_C1C2_1', - 'Woodcut_Oak_LeafClump_C1C2_2', - 'Woodcut_Oak_LeafClump_C1C2_E', - 'Woodcut_Oak_LeafClump_C1_E', - 'Woodcut_Oak_LeafClump_C2C2_1', - 'Woodcut_Oak_LeafClump_C2C2_2', - 'Woodcut_Oak_LeafClump_C2C3_1', - 'Woodcut_Oak_LeafClump_C2C3_2', - 'Woodcut_Oak_LeafClump_C2C3_E', - 'Woodcut_Oak_LeafClump_C2_E', - 'Woodcut_Oak_LeafClump_C3C3_1', - 'Woodcut_Oak_LeafClump_C3C3_2', - 'Woodcut_Oak_LeafClump_C3_E' -] as const; - -const REDWOOD_LEAVES = [ - 'Woodcut_Redwood_LeafClump_Base', - 'Woodcut_Redwood_LeafClump_T1_D30_C1C2', - 'Woodcut_Redwood_LeafClump_T1_D30_C3C4', - 'Woodcut_Redwood_LeafClump_T1_D30_C5C6', - 'Woodcut_Redwood_LeafClump_T1_D30_C7C8', - 'Woodcut_Redwood_LeafClump_T2_D30_C1C2', - 'Woodcut_Redwood_LeafClump_T2_D30_C3C4', - 'Woodcut_Redwood_LeafClump_T2_D30_C5C6', - 'Woodcut_Redwood_LeafClump_T2_D30_C7C8', - 'Woodcut_Redwood_LeafClump_T3_D30_C1C2', - 'Woodcut_Redwood_LeafClump_T3_D30_C3C4', - 'Woodcut_Redwood_LeafClump_T3_D30_C5C6', - 'Woodcut_Redwood_LeafClump_T3_D30_C7C8', - 'Woodcut_Redwood_LeafClump_T4_D30_C1', - 'Woodcut_Redwood_LeafClump_T4_D30_C2', - 'Woodcut_Redwood_LeafClump_T4_D30_C3', - 'Woodcut_Redwood_LeafClump_T4_D30_C4', - 'Woodcut_Redwood_LeafClump_T4_D30_C5', - 'Woodcut_Redwood_LeafClump_T4_D30_C6', - 'Woodcut_Redwood_LeafClump_T4_D30_C7', - 'Woodcut_Redwood_LeafClump_T4_D30_C8' -] as const; - -const WALNUT_LEAVES = [ - 'Woodcut_Walnut_LeafClump_Base', - 'Woodcut_Walnut_LeafClump_C1C1', - 'Woodcut_Walnut_LeafClump_C1C1_E', - 'Woodcut_Walnut_LeafClump_C1C2', - 'Woodcut_Walnut_LeafClump_C1C2_E', - 'Woodcut_Walnut_LeafClump_C2C2', - 'Woodcut_Walnut_LeafClump_C2C2_E', - 'Woodcut_Walnut_LeafClump_C2C3', - 'Woodcut_Walnut_LeafClump_C2C3_E', - 'Woodcut_Walnut_LeafClump_C3C3', - 'Woodcut_Walnut_LeafClump_C3C3_E', - 'Woodcut_Walnut_LeafClump_C3C4', - 'Woodcut_Walnut_LeafClump_C3C4_E', - 'Woodcut_Walnut_LeafClump_C4C4_E', - 'Woodcut_Walnut_LeafClump_C4C5_E', - 'Woodcut_Walnut_LeafClump_C5C5_E' -] as const; - -const LEAVES = { - [SpeciesHash.Ash]: ASH_LEAVES, - [SpeciesHash.Birch]: BIRCH_LEAVES, - [SpeciesHash.Oak]: OAK_LEAVES, - [SpeciesHash.Redwood]: REDWOOD_LEAVES, - [SpeciesHash.Standard]: OAK_LEAVES, - [SpeciesHash.Walnut]: WALNUT_LEAVES -}; - -const LEAF_SCALE = { - [SpeciesHash.Ash]: 4, - [SpeciesHash.Birch]: 4, - [SpeciesHash.Oak]: 4, - [SpeciesHash.Redwood]: 0.5, - [SpeciesHash.Standard]: 4, - [SpeciesHash.Walnut]: 4 -}; - -const compositionMap: CompositionMap = { - Woodcut_B0_B0: { Top_8056: BRANCHES }, - Woodcut_B0_B0_S15: { Top_53706: BRANCHES, Stick_53710: STICKS }, - Woodcut_B0_B15_B30: { Branch_1_20342: BRANCHES, Branch_2_20338: BRANCHES }, - Woodcut_B0_S0_S30: { Stick_1_38940: STICKS, Stick_2_38936: STICKS }, - Woodcut_B15_B15: { Top_4690: BRANCHES }, - Woodcut_B30_B30: { Top_58002: BRANCHES }, - Woodcut_B5_B5: { Top_37822: BRANCHES }, - Woodcut_BranchRoot_V1_B0: { Top_14282: BRANCHES }, - Woodcut_BranchRoot_V1_B15_S30: { Top_63620: BRANCHES, Branch_63622: STICKS }, - Woodcut_Root_V1_T0: { Top_49314: TRUNKS }, - Woodcut_Root_V1_T0_B15: { Top_23584: TRUNKS, Branch_12832: BRANCHES }, - Woodcut_Root_V1_T0_S30: { Top_56452: TRUNKS, Stick_51558: STICKS }, - Woodcut_Root_V1_T30: { Top_7658: TRUNKS }, - Woodcut_S0_S0: { Top_1286: STICKS }, - Woodcut_S0_S15_S15: { Top_1_2062: STICKS, Top_2_60778: STICKS }, - Woodcut_T0_B0_B30: { Branch_1_4000: BRANCHES, Branch_2_3996: BRANCHES }, - Woodcut_T0_B15_B30: { Branch_1_634: BRANCHES, Branch_2_636: BRANCHES }, - Woodcut_T0_T0: { Top_39100: TRUNKS }, - Woodcut_T0_T0_B30: { Top_34360: TRUNKS, Branch_34356: BRANCHES }, - Woodcut_T0_T0_B45: { Top_15160: TRUNKS, Branch_15162: BRANCHES }, - Woodcut_T0_T0_S30: { Top_45916: TRUNKS, Stick_45912: STICKS }, - Woodcut_T0_T0_S30_S30_S30: { Top_836: TRUNKS, Stick_1_34724: STICKS, Stick_2_17522: STICKS, Stick_3_910: STICKS }, - Woodcut_T15_T15: { Top_30734: TRUNKS }, - Woodcut_T30_T30: { Top_28372: TRUNKS }, - Woodcut_T5_T5: { Top_32750: TRUNKS } -}; - -const terminationMap: CompositionMap = { - Woodcut_B0_B0: { Top_8056: BRANCH_TERMINATORS }, - Woodcut_B0_B0_S15: { Top_53706: BRANCH_TERMINATORS, Stick_53710: TWIGS }, - Woodcut_B0_B15_B30: { Branch_1_20342: BRANCH_TERMINATORS, Branch_2_20338: BRANCH_TERMINATORS }, - Woodcut_B0_S0_S30: { Stick_1_38940: TWIGS, Stick_2_38936: TWIGS }, - Woodcut_B15_B15: { Top_4690: BRANCH_TERMINATORS }, - Woodcut_B30_B30: { Top_58002: BRANCH_TERMINATORS }, - Woodcut_B5_B5: { Top_37822: BRANCH_TERMINATORS }, - Woodcut_BranchRoot_V1_B0: { Top_14282: BRANCH_TERMINATORS }, - Woodcut_BranchRoot_V1_B15_S30: { Top_63620: BRANCH_TERMINATORS, Branch_63622: TWIGS }, - Woodcut_Root_V1_T0: { Top_49314: TRUNK_TERMINATORS }, - Woodcut_Root_V1_T0_B15: { Top_23584: TRUNK_TERMINATORS, Branch_12832: BRANCH_TERMINATORS }, - Woodcut_Root_V1_T0_S30: { Top_56452: TRUNK_TERMINATORS, Stick_51558: TWIGS }, - Woodcut_Root_V1_T30: { Top_7658: TRUNK_TERMINATORS }, - Woodcut_S0_S0: { Top_1286: TWIGS }, - Woodcut_S0_S15_S15: { Top_1_2062: TWIGS, Top_2_60778: TWIGS }, - Woodcut_T0_B0_B30: { Branch_1_4000: BRANCH_TERMINATORS, Branch_2_3996: BRANCH_TERMINATORS }, - Woodcut_T0_B15_B30: { Branch_1_634: BRANCH_TERMINATORS, Branch_2_636: BRANCH_TERMINATORS }, - Woodcut_T0_T0: { Top_39100: TRUNK_TERMINATORS }, - Woodcut_T0_T0_B30: { Top_34360: TRUNK_TERMINATORS, Branch_34356: BRANCH_TERMINATORS }, - Woodcut_T0_T0_B45: { Top_15160: TRUNK_TERMINATORS, Branch_15162: BRANCH_TERMINATORS }, - Woodcut_T0_T0_S30: { Top_45916: TRUNK_TERMINATORS, Stick_45912: TWIGS }, - Woodcut_T0_T0_S30_S30_S30: { - Top_836: TRUNK_TERMINATORS, - Stick_1_34724: TWIGS, - Stick_2_17522: TWIGS, - Stick_3_910: TWIGS - }, - Woodcut_T15_T15: { Top_30734: TRUNK_TERMINATORS }, - Woodcut_T30_T30: { Top_28372: TRUNK_TERMINATORS }, - Woodcut_T5_T5: { Top_32750: TRUNK_TERMINATORS } -}; - -const pickRandom = (choices: readonly SegmentName[]) => { - const index = Math.floor(Math.random() * choices.length); - - return choices[index]; -}; - -const populateSegment = ( - segment: SegmentName, - terminationRate: number, - terminationThreshold: number = 0, - isTerminationLayer: boolean = false -): Segment => { - /* Increase termination chance. */ - const newTerminationThreshold = Math.min(1, terminationThreshold + terminationRate); - const terminateNextLayer = isTerminationLayer || Math.random() <= newTerminationThreshold; - - /* Get the connections on segment. */ - const segmentMap = isTerminationLayer ? terminationMap : compositionMap; - const connectionMaps = Object.entries(segmentMap[segment] ?? {}) as ConnectionCandidates[]; - - /* Populate each connection with a candidate child segment and recursively generate layers for those child segments. */ - return { - [segment]: connectionMaps.reduce((connections, [connectionName, candidateSegments]) => { - const childSegment = pickRandom(candidateSegments); - const populatedSegment = populateSegment( - childSegment, - terminationRate, - newTerminationThreshold, - terminateNextLayer - ); - - return { - ...connections, - [connectionName]: populatedSegment - }; - }, {}) - }; -}; - -const createChildPrefab = (speciesHash: SpeciesHash, segment: Segment, parentHash: number = 0): ChildPrefab => { - const [segmentName, connectionMap] = Object.entries(segment)[0] as [SegmentName, Connections]; - const connections = Object.entries(connectionMap); - const rotation = randomRotation(); - - return { - parentHash, - prefab: { - prefabObject: { - hash: Prefab[segmentName].hash, - rotation - }, - childPrefabs: - connections.length === 0 - ? attachLeafNode(speciesHash, rotation) - : connections.map(([embeddedEntity, childSegment]) => - // After several hours I can't figure out the proper way to access this object and I cbf anymore. - createChildPrefab( - speciesHash, - childSegment, - (Prefab[segmentName]['embedded'] as any)[embeddedEntity].hash - ) - ) - } - }; -}; - -const attachLeafNode = ( - speciesHash: SpeciesHash, - rotation: { x: number; y: number; z: number; w: number } -): ChildPrefab[] => { - const prefab = pickRandom(LEAVES[speciesHash]); - - return [ - { - parentHash: 0, - prefab: { - prefabObject: { - hash: Prefab[prefab].hash, - rotation: { - x: -rotation.x, - y: -rotation.y, - z: -rotation.z, - w: -rotation.w - }, - scale: LEAF_SCALE[speciesHash] + Math.random() * 0.4 - } - } - } - ]; -}; - -const randomRotation = () => ({ - x: Math.random() * 2 - 1, - y: Math.random() * 2 - 1, - z: Math.random() * 2 - 1, - w: Math.random() * 2 - 1 -}); - -export const createRandomTree = ( - speciesHash: SpeciesHash, - terminationRate: number, - position: { x: number; y: number; z: number } -): PrefabData => { - const root = pickRandom(ROOTS); - - const populatedComposition = populateSegment(root, terminationRate); - const childPrefab = createChildPrefab(speciesHash, populatedComposition); - - const tree: PrefabData = { - prefabObject: { - hash: Prefab.Tree.hash, - position - }, - components: { - NetworkRigidbody: { - position, - isKinematic: true - }, - WoodcutTree: { - speciesHash: speciesHash - } - }, - childPrefabs: [childPrefab] - }; - - return tree; -}; diff --git a/src/utils/floatToBinary.ts b/src/utils/floatToBinary.ts deleted file mode 100644 index b82deaf..0000000 --- a/src/utils/floatToBinary.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { packFloat } from './packFloat'; -import { numberToBinary } from './numberToBinary'; - -export const floatToBinary = (number: number): string => numberToBinary(packFloat(number)).padStart(32, '0'); diff --git a/src/utils/index.ts b/src/utils/index.ts deleted file mode 100644 index 8b62162..0000000 --- a/src/utils/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -export { binaryToNumber } from './binaryToNumber'; -export { binaryToInt } from './binaryToInt'; -export { binaryToUIntArray } from './binaryToUIntArray'; -export { binaryToULong } from './binaryToULong'; -export { createBinaryReader, BinaryReader } from './createBinaryReader'; -export { createBinaryWriter, BinaryWriter } from './createBinaryWriter'; -export { createRandomTree } from './createRandomTree'; -export { floatToBinary } from './floatToBinary'; -export { intToBinary } from './intToBinary'; -export { numberToBinary } from './numberToBinary'; -export { parseVersionString, VersionMap } from './parseVersionString'; -export { reasonableGifts } from './reasonableGifts'; -export { uIntToBinary } from './uIntToBinary'; -export { uLongToBinary } from './uLongToBinary'; -export { uShortToBinary } from './uShortToBinary'; -export { unpackFloat } from './unpackFloat'; diff --git a/src/utils/intToBinary.ts b/src/utils/intToBinary.ts deleted file mode 100644 index c4fb1d9..0000000 --- a/src/utils/intToBinary.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { numberToBinary } from './numberToBinary'; - -const NEGATIVE_OFFSET = 2147483648; - -export const intToBinary = (number: number): string => { - const isPositive = number >= 0; - const integer = isPositive ? number : number + NEGATIVE_OFFSET; - - const isPositiveBit = Number(isPositive).toString(); - const integerBits = numberToBinary(integer).padStart(32, '0'); - - return `${isPositiveBit}${integerBits.slice(1)}`; -}; diff --git a/src/utils/isATTPrefabHash.test.ts b/src/utils/isATTPrefabHash.test.ts new file mode 100644 index 0000000..d213dcb --- /dev/null +++ b/src/utils/isATTPrefabHash.test.ts @@ -0,0 +1,25 @@ +import { ATTPrefabs } from '../types/ATTPrefabs.js'; + +import { isATTPrefabHash } from './isATTPrefabHash.js'; + +describe('isATTPrefabHash()', () => { + describe('when given a valid prefab hash', () => { + it('returns true', () => { + const validHash = ATTPrefabs.Handle_Short.hash; + + const result = isATTPrefabHash(validHash); + + expect(result).toBe(true); + }); + }); + + describe('when given an invalid prefab hash', () => { + it('returns false', () => { + const invalidHash = 0; + + const result = isATTPrefabHash(invalidHash); + + expect(result).toBe(false); + }); + }); +}); diff --git a/src/utils/isATTPrefabHash.ts b/src/utils/isATTPrefabHash.ts new file mode 100644 index 0000000..9be5775 --- /dev/null +++ b/src/utils/isATTPrefabHash.ts @@ -0,0 +1,20 @@ +import type { ATTPrefabHash } from '../types/ATTPrefabHash.js'; + +import { attPrefabHashes } from '../constants.js'; + +/** + * Asserts if a `number` is an [`ATTPrefabHash`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/ATTPrefabHash.md). + * + * @example + * import { isATTPrefabHash } from 'att-string-transcoder'; + * + * const prefabHash = 23182; + * // `prefabHash` is of type `number`. + * + * if (isATTPrefabHash(prefabHash)) { + * // `prefabHash` is of type `ATTPrefabHash`. + * } + */ +export function isATTPrefabHash(hash: number): hash is ATTPrefabHash { + return attPrefabHashes.includes(hash); +} diff --git a/src/utils/isATTPrefabName.test.ts b/src/utils/isATTPrefabName.test.ts new file mode 100644 index 0000000..dccf4ae --- /dev/null +++ b/src/utils/isATTPrefabName.test.ts @@ -0,0 +1,25 @@ +import { ATTPrefabs } from '../types/ATTPrefabs.js'; + +import { isATTPrefabName } from './isATTPrefabName.js'; + +describe('isATTPrefabName()', () => { + describe('when given a valid prefab name', () => { + it('returns true', () => { + const validName = ATTPrefabs.Handle_Short.name; + + const result = isATTPrefabName(validName); + + expect(result).toBe(true); + }); + }); + + describe('when given an invalid prefab name', () => { + it('returns false', () => { + const invalidName = 'topkek'; + + const result = isATTPrefabName(invalidName); + + expect(result).toBe(false); + }); + }); +}); diff --git a/src/utils/isATTPrefabName.ts b/src/utils/isATTPrefabName.ts new file mode 100644 index 0000000..0a8f9b6 --- /dev/null +++ b/src/utils/isATTPrefabName.ts @@ -0,0 +1,20 @@ +import type { ATTPrefabName } from '../types/ATTPrefabName.js'; + +import { ATTPrefabs } from '../types/ATTPrefabs.js'; + +/** + * Asserts if a `string` is an [`ATTPrefabName`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/ATTPrefabName.md). + * + * @example + * import { isATTPrefabName } from 'att-string-transcoder'; + * + * const prefabName = 'Anvil'; + * // `prefabName` is of type `string`. + * + * if (isATTPrefabName(prefabName)) { + * // `prefabName` is of type `ATTPrefabName`. + * } + */ +export function isATTPrefabName(name: string): name is ATTPrefabName { + return name in ATTPrefabs; +} diff --git a/src/utils/isSavableComponent.test.ts b/src/utils/isSavableComponent.test.ts new file mode 100644 index 0000000..dff7a4b --- /dev/null +++ b/src/utils/isSavableComponent.test.ts @@ -0,0 +1,38 @@ +import { ATTPrefabs } from '../types/ATTPrefabs.js'; + +import { isSavableComponent } from './isSavableComponent.js'; + +describe('isSavableComponent()', () => { + describe('when given a valid component name on a corresponding prefab hash', () => { + it('returns true', () => { + const validComponentName = ATTPrefabs.Potion_Medium.embedded.Potion_Medium_23646.savables.Pickup.name; + const correspondingPrefabHash = ATTPrefabs.Potion_Medium.hash; + + const result = isSavableComponent(validComponentName, correspondingPrefabHash); + + expect(result).toBe(true); + }); + }); + + describe('when given a valid component name on a corresponding prefab name', () => { + it('returns true', () => { + const validComponentName = ATTPrefabs.Potion_Medium.embedded.Potion_Medium_23646.savables.Pickup.name; + const correspondingPrefabName = ATTPrefabs.Potion_Medium.name; + + const result = isSavableComponent(validComponentName, correspondingPrefabName); + + expect(result).toBe(true); + }); + }); + + describe('when given a valid component name on a prefab name that does not correspond to the component', () => { + it('returns false', () => { + const validComponentName = ATTPrefabs.Potion_Medium.embedded.Potion_Medium_23646.savables.Pickup.name; + const nonCorrespondingPrefabName = ATTPrefabs.Anvil.name; + + const result = isSavableComponent(validComponentName, nonCorrespondingPrefabName); + + expect(result).toBe(false); + }); + }); +}); diff --git a/src/utils/isSavableComponent.ts b/src/utils/isSavableComponent.ts new file mode 100644 index 0000000..344d301 --- /dev/null +++ b/src/utils/isSavableComponent.ts @@ -0,0 +1,32 @@ +import type { ATTPrefabHash } from '../types/ATTPrefabHash.js'; +import type { ATTPrefabName } from '../types/ATTPrefabName.js'; +import type { SupportedPrefabComponents } from '../types/SupportedPrefabComponents.js'; + +import { attPrefabNames } from '../constants.js'; +import { ATTPrefabs } from '../types/ATTPrefabs.js'; + +type Embed = { savables?: { [saveable: string]: { hash: number; name: string } } }; + +/** + * Returns whether or not the given component name belongs to a component that is normally savable + * on the given prefab hash or name. + * + * @example + * import { isSavableComponent } from 'att-string-transcoder'; + * + * if (isSavableComponent('NetworkRigidbody', 'Handle_Short')) { + * // `Handle_Short` can save `NetworkRigidbody` component data. + * } + */ +export function isSavableComponent(componentName: keyof SupportedPrefabComponents, prefabName: ATTPrefabName): boolean; +export function isSavableComponent(componentName: keyof SupportedPrefabComponents, prefabHash: ATTPrefabHash): boolean; +export function isSavableComponent( + componentName: keyof SupportedPrefabComponents, + prefabArg: ATTPrefabName | ATTPrefabHash +): boolean { + const name = typeof prefabArg === 'string' ? prefabArg : attPrefabNames[prefabArg]; + const prefab = ATTPrefabs[name]; + const embed = Object.entries(prefab.embedded).find(([key]) => key.startsWith(`${name}_`))?.[1]; + + return typeof embed?.savables?.[componentName] !== 'undefined'; +} diff --git a/src/utils/isUnknownComponent.test.ts b/src/utils/isUnknownComponent.test.ts new file mode 100644 index 0000000..eda42d1 --- /dev/null +++ b/src/utils/isUnknownComponent.test.ts @@ -0,0 +1,26 @@ +import { Component } from '../components/Component.js'; +import { NetworkRigidbodyComponent } from '../components/NetworkRigidbodyComponent.js'; + +import { isUnknownComponent } from './isUnknownComponent.js'; + +describe('isUnknownComponent()', () => { + describe('when given a known component', () => { + it('returns false', () => { + const knownComponent = new NetworkRigidbodyComponent({ version: 1 }); + + const result = isUnknownComponent(knownComponent); + + expect(result).toBe(false); + }); + }); + + describe('when given an unknown component', () => { + it('returns true', () => { + const unknownComponent = new Component({ hash: 0, name: 'Unknown', version: 1 }); + + const result = isUnknownComponent(unknownComponent); + + expect(result).toBe(true); + }); + }); +}); diff --git a/src/utils/isUnknownComponent.ts b/src/utils/isUnknownComponent.ts new file mode 100644 index 0000000..7ede618 --- /dev/null +++ b/src/utils/isUnknownComponent.ts @@ -0,0 +1,16 @@ +import type { Component } from '../components/Component.js'; +import type { UnsupportedComponent } from '../components/UnsupportedComponent.js'; + +/** + * Asserts if a `component` is an [`UnsupportedComponent`](https://github.com/mdingena/att-string-transcoder/tree/main/docs/UnsupportedComponent.md). + * + * @example + * import { isUnknownComponent } from 'att-string-transcoder'; + * + * if (isUnknownComponent(component)) { + * // `component` is of type `UnsupportedComponent`. + * } + */ +export function isUnknownComponent(component: Component): component is UnsupportedComponent { + return component.name === 'Unknown'; +} diff --git a/src/utils/numberToBinary.ts b/src/utils/numberToBinary.ts deleted file mode 100644 index 288768f..0000000 --- a/src/utils/numberToBinary.ts +++ /dev/null @@ -1 +0,0 @@ -export const numberToBinary = (number: number): string => number.toString(2); diff --git a/src/utils/packFloat.ts b/src/utils/packFloat.ts deleted file mode 100644 index 07ca3af..0000000 --- a/src/utils/packFloat.ts +++ /dev/null @@ -1,20 +0,0 @@ -import ieee754 from 'ieee754'; -import bitwise from 'bitwise'; -import { Bit } from 'bitwise/types'; - -export const packFloat = (number: number) => { - const buffer = Buffer.from(new Uint8Array(4)); - let bits: number = 0; - - ieee754.write(buffer, number, 0, true, 23, 4); - - const integer = buffer.readUInt32LE(0); - - for (var i = 0; i < 32; i++) { - const bit: Bit = bitwise.integer.getBit(integer, 31 - i); - - bits = bitwise.integer.setBit(bits, 31 - i, bit); - } - - return bits >>> 0; -}; diff --git a/src/utils/parseVersionString.ts b/src/utils/parseVersionString.ts deleted file mode 100644 index 99c4884..0000000 --- a/src/utils/parseVersionString.ts +++ /dev/null @@ -1,32 +0,0 @@ -export type VersionMap = { [hash: number]: number }; - -export const parseVersionString = (versionString: string | undefined): VersionMap => { - if (typeof versionString === 'undefined') return {}; - - if (versionString.substr(-1) !== ',') { - throw new Error('String contains invalid versioning. Check string format. Did you copy-paste the whole string?'); - } - - const versionArray = versionString.split(',').slice(0, -1); - const expectedCount = Number(versionArray.shift()); - - if (expectedCount !== versionArray.length / 2) { - throw new Error( - `String contains invalid versioning. Expected ${expectedCount} versions but parsed ${versionArray.length / 2}.` - ); - } - - const versions: VersionMap = {}; - let lastKey = 0; - - versionArray.map(Number).forEach((element, index) => { - const isHash = index % 2 === 0; - const key = isHash ? element : lastKey; - const value = isHash ? 0 : element; - - versions[key] = value; - lastKey = key; - }); - - return versions; -}; diff --git a/src/utils/readChildren.test.ts b/src/utils/readChildren.test.ts new file mode 100644 index 0000000..94a77f4 --- /dev/null +++ b/src/utils/readChildren.test.ts @@ -0,0 +1,61 @@ +import type { PrefabChild } from '../types/PrefabChild.js'; + +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { Prefab } from '../Prefab.js'; + +import { readChildren } from './readChildren.js'; + +describe('readChildren()', () => { + let fastForwardedReader: BinaryReader; + const child = new Prefab('Guard'); + const parent = new Prefab('Handle_Short', { + children: [ + { + parentHash: 6136, + prefab: child + } + ] + }); + + beforeEach(() => { + const saveString = parent.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // Component hash === termination hash. + reader.readUnsignedInteger(); // Entity hash === termination hash. + + fastForwardedReader = reader; + }); + + it('returns PrefabChild[]', () => { + const children = readChildren(fastForwardedReader); + + expect(children).toStrictEqual([ + { + parentHash: 6136, + prefab: child + } + ]); + }); +}); diff --git a/src/utils/readChildren.ts b/src/utils/readChildren.ts new file mode 100644 index 0000000..6caf88a --- /dev/null +++ b/src/utils/readChildren.ts @@ -0,0 +1,40 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { PrefabChild } from '../types/PrefabChild.js'; + +import { Prefab } from '../Prefab.js'; + +/** + * Reads all child prefabs from the given `BinaryReader` and returns an array of `PrefabChild`. + * + * @example + * import { BinaryReader, readChildren } from 'att-string-transcoder'; + * + * const reader = new BinaryReader('...'); + * + * const componentVersions = new Map([ + * [ComponentHash.NetworkRigidbody, 1], + * [ComponentHash.PhysicalMaterialPart, 1], + * [ComponentHash.Pickup, 2] + * // etc... + * ]); + * + * const children = readChildren(reader, componentVersions); + */ +export function readChildren(reader: BinaryReader, componentVersions?: Map): PrefabChild[] { + const children: PrefabChild[] = []; + + const isLooping = true; + + while (isLooping) { + const hasChild = reader.readBoolean(); + + if (!hasChild) break; + + const parentHash = reader.readUnsignedInteger(); + const prefab = Prefab.fromBinary(reader, componentVersions); + + children.push({ parentHash, prefab }); + } + + return children; +} diff --git a/src/utils/readComponent.test.ts b/src/utils/readComponent.test.ts new file mode 100644 index 0000000..741eb2a --- /dev/null +++ b/src/utils/readComponent.test.ts @@ -0,0 +1,135 @@ +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { Prefab } from '../Prefab.js'; +import { Component } from '../components/Component.js'; +import { NetworkRigidbodyComponent } from '../components/NetworkRigidbodyComponent.js'; +import { UnsupportedComponent } from '../components/UnsupportedComponent.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { readComponent } from './readComponent.js'; + +describe('readComponent()', () => { + describe('when reading a supported component', () => { + let fastForwardedReader: BinaryReader; + const componentHash = ComponentHash.NetworkRigidbody; + const componentName = 'NetworkRigidbody'; + const componentVersion = 1; + const prefab = new Prefab('Handle_Short', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ + version: componentVersion, + isKinematic: true, + velocity: { x: 1337, y: 420, z: 69 } + }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + + fastForwardedReader = reader; + }); + + it('returns a Component', () => { + const hash = fastForwardedReader.readUnsignedInteger(); + + if (hash !== componentHash) { + throw new Error('Invalid test data.'); + } + + const component = readComponent(fastForwardedReader, componentHash, componentName, componentVersion); + + expect(component).toBeInstanceOf(Component); + expect(component).toBeInstanceOf(NetworkRigidbodyComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect((component as NetworkRigidbodyComponent).isKinematic).toBe(true); + expect((component as NetworkRigidbodyComponent).velocity).toStrictEqual({ x: 1337, y: 420, z: 69 }); + }); + }); + + describe('when reading an unsupported component', () => { + let fastForwardedReader: BinaryReader; + const componentHash = ComponentHash.RandomSpawnRectangle; + const componentName = 'RandomSpawnRectangle'; + const componentVersion = 1; + const prefab = new Prefab('Handle_Short', { + components: { + RandomSpawnRectangle: new UnsupportedComponent({ + hash: componentHash, + name: componentName, + version: componentVersion, + rawData: '00000001001101111111' as BinaryString + }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + + fastForwardedReader = reader; + }); + + it('returns an UnsupportedComponent', () => { + const hash = fastForwardedReader.readUnsignedInteger(); + + if (hash !== componentHash) { + throw new Error('Invalid test data.'); + } + + const component = readComponent(fastForwardedReader, componentHash, componentName, componentVersion); + + expect(component).toBeInstanceOf(Component); + expect(component).toBeInstanceOf(UnsupportedComponent); + expect(component.hash).toStrictEqual(componentHash); + expect(component.name).toStrictEqual(componentName); + expect((component as UnsupportedComponent).rawData).toStrictEqual('00000001001101111111' as BinaryString); + }); + }); +}); diff --git a/src/utils/readComponent.ts b/src/utils/readComponent.ts new file mode 100644 index 0000000..7ba8bbd --- /dev/null +++ b/src/utils/readComponent.ts @@ -0,0 +1,33 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { Component } from '../components/Component.js'; + +import { UnsupportedComponent } from '../components/UnsupportedComponent.js'; +import { supportedComponents } from '../supportedComponents.js'; + +/** + * Reads next component from the given `BinaryReader` and returns a `Component` instance. + * + * @example + * import { BinaryReader, readChildren } from 'att-string-transcoder'; + * + * const reader = new BinaryReader('...'); + * const hash = 2290978823; + * const name = 'NetworkRigidbody'; + * const version = 1; + * + * const component = readComponent(reader, hash, name, version); + */ +export function readComponent(reader: BinaryReader, hash: number, name: string, version: number): Component { + /* Get the component's data length. */ + const dataLength = reader.readUnsignedInteger(); + + /* Get the component's class. */ + const SupportedComponent = supportedComponents[name]; + + /* Create a component instance from the binary data string. */ + if (typeof SupportedComponent === 'undefined') { + return UnsupportedComponent.fromBinary(reader, version, hash, name, dataLength); + } else { + return SupportedComponent.fromBinary(reader, version); + } +} diff --git a/src/utils/readComponents.test.ts b/src/utils/readComponents.test.ts new file mode 100644 index 0000000..d684ae7 --- /dev/null +++ b/src/utils/readComponents.test.ts @@ -0,0 +1,133 @@ +import type { BinaryString } from '../types/BinaryString.js'; + +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { Prefab } from '../Prefab.js'; +import { NetworkRigidbodyComponent } from '../components/NetworkRigidbodyComponent.js'; +import { UnsupportedComponent } from '../components/UnsupportedComponent.js'; +import { latestSupportedComponentVersions } from '../constants.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { readComponents } from './readComponents.js'; + +const mockedUnknownComponentHash = 1337; +const mockedUnknownComponentVersion = 42; + +describe('readComponents()', () => { + describe('when reading components', () => { + let fastForwardedReader: BinaryReader; + const firstComponentHash = ComponentHash.NetworkRigidbody; + const firstComponentName = 'NetworkRigidbody'; + const firstComponentVersion = 1; + const secondComponentHash = ComponentHash.RandomSpawnRectangle; + const secondComponentName = 'RandomSpawnRectangle'; + const secondComponentVersion = 1; + const thirdComponentHash = mockedUnknownComponentHash; + const thirdComponentName = 'Unknown'; + const thirdComponentVersion = mockedUnknownComponentVersion; + const prefab = new Prefab('Handle_Short', { + components: { + NetworkRigidbody: new NetworkRigidbodyComponent({ + version: firstComponentVersion, + isKinematic: true, + velocity: { x: 1337, y: 420, z: 69 } + }), + RandomSpawnRectangle: new UnsupportedComponent({ + hash: secondComponentHash, + name: secondComponentName, + version: secondComponentVersion, + rawData: '00000001001101111111' as BinaryString + }), + Unknown: [ + new UnsupportedComponent({ + hash: thirdComponentHash, + name: thirdComponentName, + version: thirdComponentVersion, + rawData: '11110111001100010000' as BinaryString + }) + ] + } + }); + + beforeEach(() => { + latestSupportedComponentVersions.set(mockedUnknownComponentHash, mockedUnknownComponentVersion); + + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + + fastForwardedReader = reader; + }); + + afterEach(() => { + latestSupportedComponentVersions.delete(mockedUnknownComponentHash); + }); + + it('returns PrefabComponents', () => { + const components = readComponents(fastForwardedReader); + + expect(components.NetworkRigidbody).toBeInstanceOf(NetworkRigidbodyComponent); + expect(components.NetworkRigidbody?.hash).toStrictEqual(firstComponentHash); + expect(components.NetworkRigidbody?.name).toStrictEqual(firstComponentName); + expect(components.NetworkRigidbody?.version).toStrictEqual(firstComponentVersion); + expect(components.NetworkRigidbody?.isKinematic).toBe(true); + expect(components.NetworkRigidbody?.velocity).toStrictEqual({ x: 1337, y: 420, z: 69 }); + + expect(components.RandomSpawnRectangle).toBeInstanceOf(UnsupportedComponent); + expect(components.RandomSpawnRectangle?.hash).toStrictEqual(secondComponentHash); + expect(components.RandomSpawnRectangle?.name).toStrictEqual(secondComponentName); + expect(components.RandomSpawnRectangle?.version).toStrictEqual(secondComponentVersion); + expect(components.RandomSpawnRectangle?.rawData).toStrictEqual('00000001001101111111' as BinaryString); + + expect(components.Unknown[0]).toBeInstanceOf(UnsupportedComponent); + expect(components.Unknown[0]?.hash).toStrictEqual(thirdComponentHash); + expect(components.Unknown[0]?.name).toStrictEqual(thirdComponentName); + expect(components.Unknown[0]?.version).toStrictEqual(thirdComponentVersion); + expect(components.Unknown[0]?.rawData).toStrictEqual('11110111001100010000' as BinaryString); + }); + + describe('when given componentVersions and the requested version is not supported', () => { + beforeEach(() => { + /* This doesn't really happen but we need to tweak this a little for testing purposes. */ + (latestSupportedComponentVersions as Map).set( + mockedUnknownComponentHash, + undefined + ); + }); + + afterEach(() => { + latestSupportedComponentVersions.delete(mockedUnknownComponentHash); + }); + + it('throws an error', () => { + const expectedToThrow = () => + readComponents(fastForwardedReader, latestSupportedComponentVersions as Map); + const expectedError = new Error( + `Could not determine version of "Unknown" (${mockedUnknownComponentHash}) component. A SaveString with chunk versioning pairs is required to read this data.` + ); + + expect(expectedToThrow).toThrowError(expectedError); + }); + }); + }); +}); diff --git a/src/utils/readComponents.ts b/src/utils/readComponents.ts new file mode 100644 index 0000000..9274181 --- /dev/null +++ b/src/utils/readComponents.ts @@ -0,0 +1,60 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { Component } from '../components/Component.js'; +import type { PrefabComponents } from '../types/PrefabComponents.js'; +import type { UnknownPrefabComponents } from '../types/UnknownPrefabComponents.js'; + +import { latestSupportedComponentVersions, terminatorHash } from '../constants.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { isUnknownComponent } from './isUnknownComponent.js'; +import { readComponent } from './readComponent.js'; + +type KnownPrefabComponents = Record; + +/** + * Reads all components from the given `BinaryReader` and returns a `PrefabComponents` object. + * + * @example + * import { BinaryReader, readComponents } from 'att-string-transcoder'; + * + * const reader = new BinaryReader('...'); + * + * const versions = new Map([ + * [ComponentHash.NetworkRigidbody, 1], + * [ComponentHash.PhysicalMaterialPart, 1], + * [ComponentHash.Pickup, 2] + * // etc... + * ]); + * + * const component = readComponents(reader, versions); + */ +export function readComponents(reader: BinaryReader, versions?: Map): PrefabComponents { + const components = Object.assign({} as KnownPrefabComponents, { Unknown: [] } as UnknownPrefabComponents); + + const isLooping = true; + + while (isLooping) { + const hash = reader.readUnsignedInteger(); + + if (hash === terminatorHash) break; + + const name = ComponentHash[hash] ?? 'Unknown'; + const version = versions?.get(hash) ?? latestSupportedComponentVersions.get(hash); + + if (typeof version === 'undefined') { + throw new Error( + `Could not determine version of "${name}" (${hash}) component. A SaveString with chunk versioning pairs is required to read this data.` + ); + } + + const component = readComponent(reader, hash, name, version); + + if (isUnknownComponent(component)) { + components.Unknown.push(component); + } else { + components[name] = component; + } + } + + return components; +} diff --git a/src/utils/readEntities.test.ts b/src/utils/readEntities.test.ts new file mode 100644 index 0000000..0d10857 --- /dev/null +++ b/src/utils/readEntities.test.ts @@ -0,0 +1,72 @@ +import { BinaryData } from '../BinaryData.js'; +import { BinaryReader } from '../BinaryReader.js'; +import { Entity } from '../Entity.js'; +import { Prefab } from '../Prefab.js'; + +import { readEntities } from './readEntities.js'; + +describe('readEntities()', () => { + describe('when reading entities', () => { + let fastForwardedReader: BinaryReader; + const firstEntityHash = 6136; + const firstEntityName = 'Slot_Multi'; + const secondEntityHash = 23002; + const secondEntityName = 'Unknown'; + const prefabName = 'Handle_Short'; + const prefab = new Prefab(prefabName, { + entities: { + Slot_Multi_6136: new Entity(`${firstEntityName}_${firstEntityHash}`, { + hash: firstEntityHash, + isAlive: true + }), + Unknown_23002: new Entity(secondEntityName, { + hash: secondEntityHash, + isAlive: false + }) + } + }); + + beforeEach(() => { + const saveString = prefab.toSaveString(); + const [dataString] = saveString.split('|'); + + if (typeof dataString === 'undefined') { + throw new Error('Invalid test data.'); + } + + const unsignedIntegers = dataString.split(',').map(Number); + + const data = BinaryData.fromUnsignedIntegerArray(unsignedIntegers); + const reader = new BinaryReader(data.toBinaryString()); + + reader.readUnsignedInteger(); // Root prefab hash. + reader.readUnsignedInteger(); // SaveString bytes. + reader.readUnsignedInteger(); // Parent prefab hash. + reader.readFloat(); // Parent position X. + reader.readFloat(); // Parent position Y. + reader.readFloat(); // Parent position Z. + reader.readFloat(); // Parent rotation X. + reader.readFloat(); // Parent rotation Y. + reader.readFloat(); // Parent rotation Z. + reader.readFloat(); // Parent rotation W. + reader.readFloat(); // Parent scale. + reader.readUnsignedInteger(); // Component hash === termination hash. + + fastForwardedReader = reader; + }); + + it('returns PrefabEntities', () => { + const entities = readEntities(fastForwardedReader, prefabName); + + expect(entities['Slot_Multi_6136']).toBeInstanceOf(Entity); + expect(entities['Slot_Multi_6136']?.hash).toStrictEqual(firstEntityHash); + expect(entities['Slot_Multi_6136']?.name).toStrictEqual(firstEntityName); + expect(entities['Slot_Multi_6136']?.isAlive).toBe(true); + + expect(entities['Unknown_23002']).toBeInstanceOf(Entity); + expect(entities['Unknown_23002']?.hash).toStrictEqual(secondEntityHash); + expect(entities['Unknown_23002']?.name).toStrictEqual(secondEntityName); + expect(entities['Unknown_23002']?.isAlive).toBe(false); + }); + }); +}); diff --git a/src/utils/readEntities.ts b/src/utils/readEntities.ts new file mode 100644 index 0000000..3afc83c --- /dev/null +++ b/src/utils/readEntities.ts @@ -0,0 +1,61 @@ +import type { BinaryReader } from '../BinaryReader.js'; +import type { ATTPrefabName } from '../types/ATTPrefabName.js'; +import type { PrefabEntities } from '../types/PrefabEntities.js'; + +import { Entity } from '../Entity.js'; +import { terminatorHash } from '../constants.js'; +import { ATTPrefabs } from '../types/ATTPrefabs.js'; + +/** + * Reads all entities from the given `BinaryReader` and returns a `PrefabEntities` object. + * + * @example + * import { BinaryReader, readEntities, type ATTPrefabName } from 'att-string-transcoder'; + * + * const reader = new BinaryReader('...'); + * const prefabName = 'Handle_Short' as ATTPrefabName; + * + * const componentVersions = new Map([ + * [ComponentHash.NetworkRigidbody, 1], + * [ComponentHash.PhysicalMaterialPart, 1], + * [ComponentHash.Pickup, 2] + * // etc... + * ]); + * + * const component = readEntities(reader, prefabName, componentVersions); + */ +export function readEntities( + reader: BinaryReader, + prefabName: ATTPrefabName, + componentVersions?: Map +): PrefabEntities { + const entities: Record> = {}; + + const isLooping = true; + + while (isLooping) { + const hash = reader.readUnsignedInteger(); + + if (hash === terminatorHash) break; + + /* Get the entity's data length and ignore it. */ + reader.readUnsignedInteger(); + + const entity = Object.values<{ + hash: number; + name: string; + savables: Record; + }>(ATTPrefabs[prefabName].embedded).find(attPrefabEntity => attPrefabEntity.hash === hash); + + const name = entity?.name ?? 'Unknown'; + const key = `${name}_${hash}`; + + entities[key] = Entity.fromBinary(reader, { + hash, + key: name === 'Unknown' ? name : key, + componentVersions + }); + } + + return entities; +} diff --git a/src/utils/reasonableGifts.ts b/src/utils/reasonableGifts.ts deleted file mode 100644 index 61819f4..0000000 --- a/src/utils/reasonableGifts.ts +++ /dev/null @@ -1,30 +0,0 @@ -export const reasonableGifts = [ - 16998, 16378, 17200, 17291, 17282, 16204, 16142, 17162, 16326, 16276, 17038, 17240, 16246, 17084, 17334, 25908, 15274, - 23950, 51672, 62140, 43186, 34428, 28160, 21776, 17348, 5144, 9304, 23552, 39010, 6940, 17828, 10962, 4920, 62282, - 15658, 57966, 52360, 42764, 42138, 1736, 34412, 50322, 9918, 10056, 17400, 63886, 56124, 11332, 26788, 55310, 25802, - 44380, 55914, 9704, 49402, 56720, 54482, 22876, 9630, 36438, 7092, 50412, 44360, 61488, 12492, 6934, 3558, 16448, - 62594, 50988, 43836, 23206, 47760, 63204, 34570, 1274, 24046, 32160, 38606, 26748, 17478, 11938, 20892, 30124, 64172, - 64410, 22988, 61098, 25290, 20300, 61400, 61856, 19316, 60598, 41438, 19180, 3506, 42230, 34898, 5920, 28636, 27820, - 24198, 20640, 57838, 53200, 18456, 24220, 47662, 44066, 44204, 59588, 43146, 15476, 54404, 40478, 53576, 63728, 31646, - 3532, 41402, 7014, 7918, 25446, 36248, 18734, 43552, 59342, 15584, 27314, 50484, 15500, 902, 31614, 62102, 14844, - 40010, 6740, 65526, 2000, 7278, 62012, 49890, 47468, 45012, 42556, 32526, 64844, 42916, 2562, 50328, 50326, 50252, - 41870, 43452, 47394, 43674, 43502, 43294, 24406, 20570, 33190, 43430, 10908, 8440, 5972, 47126, 46510, 61666, 53372, - 50916, 48460, 60330, 9414, 54182, 29148, 40066, 58270, 47142, 44488, 41834, 43856, 41428, 38966, 36504, 34042, 31580, - 46660, 46888, 61658, 43272, 40816, 38360, 62634, 60742, 58838, 56934, 64146, 63758, 63354, 62950, 10440, 55030, 54506, - 53982, 53458, 62546, 62142, 61738, 61334, 52934, 52530, 52126, 49162, 60930, 60526, 60122, 59718, 1266, 57564, 48718, - 48214, 47730, 43966, 59314, 58910, 58506, 58102, 29078, 32068, 1574, 57840, 54692, 52146, 59748, 50612, 48134, 45822, - 50692, 3444, 3082, 2720, 2358, 42218, 41930, 41608, 41286, 38742, 38098, 37454, 36810, 57698, 57294, 56890, 56486, - 29032, 12632, 61180, 40460, 8586, 53540, 17262, 37066, 25418, 62120, 36772, 36190, 8858, 42340, 51610, 80, 2356, - 47018, 56300, 57348, 1150, 21312, 61414, 19490, 1850, 13220, 53570, 23644, 22498, 14826, 38578, 56460, 29772, 56546, - 27416, 23400, 2924, 56894, 34892, 25100, 64640, 61656, 7232, 52756, 4530, 50602, 50888, 44704, 12416, 59936, 38566, - 13142, 63498, 50608, 24072, 31326, 40748, 23642, 61648, 60868, 32850, 32198, 30092, 23012, 24774, 16464, 31034, 23528, - 13158, 35324, 19354, 1056, 39880, 32874, 54214, 64560, 61020, 31418, 7852, 59468, 25122, 7102, 30060, 41760, 19658, - 2792, 2484, 8002, 39484, 61650, 57872, 61652, 11702, 22768, 38596, 60876, 18158, 26988, 61654, 35878, 49578, 55930, - 9586, 34986, 41638, 46508, 61670, 23514, 61634, 61674, 20564, 38942, 65358, 51764, 31620, 47150, 5170, 64848, 56698, - 45608, 17270, 23526, 7676, 30164, 55462, 57998, 20128, 21558, 12388, 12386, 17266, 17238, 42894, 17420, 57048, 56830, - 1600, 49774, 50184, 9018, 17174, 15124, 53124, 48902, 960, 34994, 32002, 41052, 27038, 29856, 17258, 49188, 4412, - 40366, 29296, 63156, 36126, 46874, 59586, 20684, 44824, 33230, 50548, 35274, 55274, 17302, 55054, 44172, 47118, 232, - 290, 58068, 9140, 18358, 30180, 13444, 31838, 8530, 42430, 62050, 53576, 63728, 31646, 3532, 14248, 39056, 15506, - 37176, 16684, 8298, 17814, 41172, 18722, 62968, 49464, 19936, 63878, 20844, 45716, 21882, 13804, 48128, 37392, 6004, - 21642, 54404, 40478, 17772, 61448, 2370, 27128, 38096, 9466 -]; diff --git a/src/utils/uIntToBinary.ts b/src/utils/uIntToBinary.ts deleted file mode 100644 index 5a9e39b..0000000 --- a/src/utils/uIntToBinary.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { numberToBinary } from './numberToBinary'; - -export const uIntToBinary = (uInt: number): string => numberToBinary(uInt).padStart(32, '0'); diff --git a/src/utils/uLongToBinary.ts b/src/utils/uLongToBinary.ts deleted file mode 100644 index c87a093..0000000 --- a/src/utils/uLongToBinary.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { numberToBinary } from './numberToBinary'; - -export const uLongToBinary = (number: number): string => { - const binary = numberToBinary(number).padStart(64, '0'); - - return `${binary.slice(32)}${binary.slice(0, 32)}`; -}; diff --git a/src/utils/uShortToBinary.ts b/src/utils/uShortToBinary.ts deleted file mode 100644 index 9495387..0000000 --- a/src/utils/uShortToBinary.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { numberToBinary } from './numberToBinary'; - -export const uShortToBinary = (number: number): string => { - return numberToBinary(number).padStart(16, '0'); -}; diff --git a/src/utils/unpackFloat.ts b/src/utils/unpackFloat.ts deleted file mode 100644 index 4cd50d3..0000000 --- a/src/utils/unpackFloat.ts +++ /dev/null @@ -1,13 +0,0 @@ -import ieee754 from 'ieee754'; - -/** - * Convert IEEE754 integer to JavaScript number. - * Thanks to https://github.com/edencomputing/attprefabulator/ - */ -export const unpackFloat = (uInt: number) => { - const buffer = Buffer.from(new Uint8Array(4)); - - buffer.writeUInt32LE(uInt); - - return ieee754.read(buffer, 0, true, 23, 4); -}; diff --git a/src/utils/writeChildren.test.ts b/src/utils/writeChildren.test.ts new file mode 100644 index 0000000..c2bc2c0 --- /dev/null +++ b/src/utils/writeChildren.test.ts @@ -0,0 +1,31 @@ +import type { PrefabChild } from '../types/PrefabChild.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { Prefab } from '../Prefab.js'; + +import { writeChildren } from './writeChildren.js'; + +describe('writeChildren()', () => { + let prefabChildren: PrefabChild[]; + + beforeEach(() => { + prefabChildren = [ + { parentHash: 1337, prefab: new Prefab('Phantom_Guard') }, + { parentHash: 420, prefab: new Prefab('Phantom_Guard') }, + { parentHash: 69, prefab: new Prefab('Phantom_Guard') } + ]; + }); + + it('stores PrefabChildren in the given BinaryWriter', () => { + const expectedData = + '1000000000000000000000101001110010000000000000000000110110001110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111100000000000000000000000001111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000011010010000000000000000000001101100011100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111111000000000000000000000000011111110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000001000101000000000000000000011011000111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111110000000000000000000000000111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'; + + const writer = new BinaryWriter(); + + writeChildren(writer, prefabChildren, new Map()); + + const data = writer.flush(); + + expect(data).toStrictEqual(expectedData); + }); +}); diff --git a/src/utils/writeChildren.ts b/src/utils/writeChildren.ts new file mode 100644 index 0000000..bd39063 --- /dev/null +++ b/src/utils/writeChildren.ts @@ -0,0 +1,55 @@ +import type { BinaryWriter } from '../BinaryWriter.js'; +import type { PrefabChild } from '../types/PrefabChild.js'; + +/** + * Writes given child prefabs to the given `BinaryWriter`. + * + * @example + * import { BinaryWriter, writeChildren } from 'att-string-transcoder'; + * + * const writer = new BinaryWriter(); + * + * const children = [ + * { + * parentHash: 0, + * prefab: new Prefab('Guard') + * } + * ]; + * + * const componentVersions = new Map([ + * [ComponentHash.NetworkRigidbody, 1], + * [ComponentHash.PhysicalMaterialPart, 1], + * [ComponentHash.Pickup, 2] + * // etc... + * ]); + * + * writeChildren(writer, children, componentVersions); + */ +export function writeChildren( + writer: BinaryWriter, + children: PrefabChild[], + componentVersions: Map +): void { + for (const { parentHash, prefab } of children) { + /** + * @property {boolean} hasChild + */ + writer.writeBoolean(true); + + /** + * @property {number} parentHash + */ + writer.writeUnsignedInteger(parentHash); + + /** + * @property {Prefab} prefab + */ + const data = prefab.toBinary(componentVersions); + writer.writeBits(data); + } + + /** + * @property {boolean} terminatorBit + */ + writer.writeBoolean(false); +} diff --git a/src/utils/writeComponents.test.ts b/src/utils/writeComponents.test.ts new file mode 100644 index 0000000..1864da2 --- /dev/null +++ b/src/utils/writeComponents.test.ts @@ -0,0 +1,70 @@ +import type { BinaryString } from '../types/BinaryString.js'; +import type { PrefabComponents } from '../types/PrefabComponents.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { NetworkRigidbodyComponent } from '../components/NetworkRigidbodyComponent.js'; +import { UnsupportedComponent } from '../components/UnsupportedComponent.js'; +import { ComponentHash } from '../types/ComponentHash.js'; + +import { writeComponents } from './writeComponents.js'; + +const mockedUnknownComponentHash = 1337; +const mockedUnknownComponentVersion = 42; + +describe('writeComponents()', () => { + const firstComponentHash = ComponentHash.NetworkRigidbody; + const firstComponentVersion = 1; + const secondComponentHash = ComponentHash.RandomSpawnRectangle; + const secondComponentName = 'RandomSpawnRectangle'; + const secondComponentVersion = 1; + const thirdComponentHash = mockedUnknownComponentHash; + const thirdComponentName = 'Unknown'; + const thirdComponentVersion = mockedUnknownComponentVersion; + + let prefabComponents: PrefabComponents; + + beforeEach(() => { + prefabComponents = { + NetworkRigidbody: new NetworkRigidbodyComponent({ + version: firstComponentVersion, + isKinematic: true, + velocity: { x: 1337, y: 420, z: 69 } + }), + RandomSpawnRectangle: new UnsupportedComponent({ + hash: secondComponentHash, + name: secondComponentName, + version: secondComponentVersion, + rawData: '00000001001101111111' as BinaryString + }), + Unknown: [ + new UnsupportedComponent({ + hash: thirdComponentHash, + name: thirdComponentName, + version: thirdComponentVersion, + rawData: '11110111001100010000' as BinaryString + }) + ] + }; + }); + + it('stores PrefabComponents in the given BinaryWriter', () => { + const expectedData = + '1000100010001101100100000000011100000000000000000000000110100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111111000000000000000000000001001000100101001110010000000000000010000111101001000000000000000000100001010001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010111000110111111010100011110001000000000000000000000000000101000000000100110111111100000000000000000000010100111001000000000000000000000000000101001111011100110001000000000000000000000000000000000000'; + + const writer = new BinaryWriter(); + + writeComponents( + writer, + prefabComponents, + new Map([ + [firstComponentHash, firstComponentVersion], + [secondComponentHash, secondComponentVersion], + [thirdComponentHash, thirdComponentVersion] + ]) + ); + + const data = writer.flush(); + + expect(data).toStrictEqual(expectedData); + }); +}); diff --git a/src/utils/writeComponents.ts b/src/utils/writeComponents.ts new file mode 100644 index 0000000..ed14839 --- /dev/null +++ b/src/utils/writeComponents.ts @@ -0,0 +1,53 @@ +import type { BinaryWriter } from '../BinaryWriter.js'; +import type { PrefabComponents } from '../types/PrefabComponents.js'; + +import { terminatorHash } from '../constants.js'; + +/** + * Writes given components to the given `BinaryWriter`. + * + * @example + * import { BinaryWriter, writeComponents } from 'att-string-transcoder'; + * + * const writer = new BinaryWriter(); + * + * const components = { + * NetworkRigidbody: new NetworkRigidbody({ version: 1 }), + * Unknown: [] + * }; + * + * const versions = new Map([ + * [ComponentHash.NetworkRigidbody, 1], + * [ComponentHash.PhysicalMaterialPart, 1], + * [ComponentHash.Pickup, 2] + * // etc... + * ]); + * + * writeComponents(writer, components, versions); + */ +export function writeComponents( + writer: BinaryWriter, + components: PrefabComponents, + versions: Map +): void { + for (const component of Object.values(components)) { + if (Array.isArray(component)) { + for (const unknownComponent of component) { + /** + * @property {Component} unknownComponent + */ + unknownComponent.write(writer, versions.get(unknownComponent.hash)); + } + } else { + /** + * @property {Component} unknownComponent + */ + component.write(writer, versions.get(component.hash)); + } + } + + /** + * @property {number} terminatorHash + */ + writer.writeUnsignedInteger(terminatorHash); +} diff --git a/src/utils/writeEntities.test.ts b/src/utils/writeEntities.test.ts new file mode 100644 index 0000000..5530c74 --- /dev/null +++ b/src/utils/writeEntities.test.ts @@ -0,0 +1,39 @@ +import type { PrefabEntities } from '../types/PrefabEntities.js'; + +import { BinaryWriter } from '../BinaryWriter.js'; +import { Entity } from '../Entity.js'; + +import { writeEntities } from './writeEntities.js'; + +describe('writeEntities()', () => { + const secondEntityHash = 23002; + const secondEntityKey = 'Unknown'; + + let prefabEntities: PrefabEntities<'Torch'>; + + beforeEach(() => { + prefabEntities = { + Fire_30100: new Entity('Fire_30100', { + hash: 30100, + isAlive: true + }), + Unknown_23002: new Entity(secondEntityKey, { + hash: secondEntityHash, + isAlive: false + }) + }; + }); + + it('stores PrefabEntities in the given BinaryWriter', () => { + const expectedData = + '0000000000000000011101011001010000000000000000000000000000100001100000000000000000000000000000000000000000000000001011001110110100000000000000000000000000010000100000000000000000000000000000000000000000000000000000000000000000'; + + const writer = new BinaryWriter(); + + writeEntities(writer, prefabEntities, new Map()); + + const data = writer.flush(); + + expect(data).toStrictEqual(expectedData); + }); +}); diff --git a/src/utils/writeEntities.ts b/src/utils/writeEntities.ts new file mode 100644 index 0000000..a5e8c66 --- /dev/null +++ b/src/utils/writeEntities.ts @@ -0,0 +1,44 @@ +import type { BinaryWriter } from '../BinaryWriter.js'; +import type { ATTPrefabName } from '../types/ATTPrefabName.js'; +import type { PrefabEntities } from '../types/PrefabEntities.js'; + +import { terminatorHash } from '../constants.js'; + +/** + * Writes given entities to the given `BinaryWriter`. + * + * @example + * import { BinaryWriter, Entity, writeEntities } from 'att-string-transcoder'; + * + * const writer = new BinaryWriter(); + * + * const entities = { + * Fire_30100: new Entity<'Torch'>('Fire_30100') + * }; + * + * const componentVersions = new Map([ + * [ComponentHash.NetworkRigidbody, 1], + * [ComponentHash.PhysicalMaterialPart, 1], + * [ComponentHash.Pickup, 2] + * // etc... + * ]); + * + * writeEntities(writer, entities, componentVersions); + */ +export function writeEntities( + writer: BinaryWriter, + entities: PrefabEntities, + componentVersions: Map +): void { + for (const entity of Object.values(entities)) { + /** + * @property {Entity} entity + */ + entity.write(writer, componentVersions); + } + + /** + * @property {number} terminatorHash + */ + writer.writeUnsignedInteger(terminatorHash); +} diff --git a/tests/createPrefab.test.ts b/tests/createPrefab.test.ts deleted file mode 100644 index 623e0db..0000000 --- a/tests/createPrefab.test.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { createPrefab, Prefab, NetworkRigidbody } from '../src'; - -const PREFAB = Prefab.Handle_Short; - -describe('createPrefab', () => { - it('creates a prefab factory', () => { - const prefabFactory = createPrefab(PREFAB); - - expect(prefabFactory).toHaveProperty(['data', 'prefabObject', 'hash'], Prefab.Handle_Short.hash); - }); - - it('sets new position', () => { - const prefabFactory = createPrefab(PREFAB); - - expect(prefabFactory.data.prefabObject.position).toBe(undefined); - - const x = 0, - y = 69, - z = 420, - position = { x, y, z }; - - prefabFactory.setPosition(x, y, z); - - expect(prefabFactory.data.prefabObject.position).toStrictEqual(position); - expect((prefabFactory.data.components!.NetworkRigidbody as NetworkRigidbody).position).toStrictEqual(position); - }); - - it('sets new rotation', () => { - const prefabFactory = createPrefab(PREFAB); - - expect(prefabFactory.data.prefabObject.rotation).toBe(undefined); - - const x = 0, - y = 0.69, - z = 0.42, - w = 0.123, - rotation = { x, y, z, w }; - - prefabFactory.setRotation(x, y, z, w); - - expect(prefabFactory.data.prefabObject.rotation).toStrictEqual(rotation); - expect((prefabFactory.data.components!.NetworkRigidbody as NetworkRigidbody).rotation).toStrictEqual(rotation); - }); - - it('sets it on fire', () => { - const prefabFactory = createPrefab(PREFAB); - - expect(prefabFactory.data.embeddedEntities).toStrictEqual({}); - - prefabFactory.setOnFire(); - - expect(prefabFactory.data.embeddedEntities).toStrictEqual({ - Fire: { - isAlive: true, - components: { - HeatSourceBase: { - isLit: true - } - } - } - }); - }); - - it('uses a slot', () => { - const prefabFactory = createPrefab(PREFAB); - - expect(prefabFactory.data.childPrefabs).toStrictEqual([]); - - const guardFactory = createPrefab(Prefab.Guard); - prefabFactory.useSlot('Slot_PommelType_30776', guardFactory); - - expect(prefabFactory.data.childPrefabs).toStrictEqual([ - { - parentHash: Prefab.Handle_Short.embedded.Slot_PommelType_30776.hash, - prefab: guardFactory.data - } - ]); - }); - - it('outputs a string', () => { - const prefabFactory = createPrefab(PREFAB); - - expect(prefabFactory.toString()).toEqual('42230,48,42230,0,0,0,0,0,0,1065353216,1065353216,0,0,0,|0,'); - }); -}); diff --git a/tests/createString.test.ts b/tests/createString.test.ts deleted file mode 100644 index 5d87664..0000000 --- a/tests/createString.test.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { createString } from '../src'; -import { handle, litGrassClump } from './data/unencodedPrefabObjects'; -import { grassClumpOnFire, shortHandleWithLargeGuardAndLargeBlade } from './data/encodedPrefabObjects'; - -describe('createString', () => { - it('encodes a prefab object', () => { - const encodedPrefab = createString(handle); - - expect(encodedPrefab).toStrictEqual(shortHandleWithLargeGuardAndLargeBlade); - }); - - it('creates a version string', () => { - const encodedPrefab = createString(litGrassClump); - - expect(encodedPrefab).toStrictEqual(grassClumpOnFire); - }); -}); diff --git a/tests/data/decodedStrings.ts b/tests/data/decodedStrings.ts deleted file mode 100644 index b538724..0000000 --- a/tests/data/decodedStrings.ts +++ /dev/null @@ -1,80 +0,0 @@ -export const decodedEmptyFlask = { - 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: [] - } -}; diff --git a/tests/data/encodedPrefabObjects.ts b/tests/data/encodedPrefabObjects.ts deleted file mode 100644 index efee988..0000000 --- a/tests/data/encodedPrefabObjects.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const shortHandleWithLargeGuardAndLargeBlade = - '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,'; -export const grassClumpOnFire = - '57872,80,57872,0,0,0,0,0,0,1065353216,1065353216,0,30100,194,4202164032,48,3221225472,343781376,1836894,0,0,0,|1,4109360768,2,'; diff --git a/tests/data/encodedStrings.ts b/tests/data/encodedStrings.ts deleted file mode 100644 index 16a0620..0000000 --- a/tests/data/encodedStrings.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const encodedEmptyFlask = - '23644,174,23644,3291400193,1124083418,1120267189,3096667348,3179446942,3130806411,1065319104,1065353224,2290978823,418,3291400193,1124083418,1120267189,3096667348,3179446942,3130806411,1065319104,1073741824,0,0,0,0,0,363610349,2147483656,1028202108,4266048908,3221225489,1476395008,0,63251750,2751463424,2183611311,3892314146,1056964608,83,704643072,2175490177,3674210304,276468284,4185915392,0,0,|150,1908922854,1,159391088,1,3801256786,3,272188517,1,237360636,2,391977879,2,277505782,2,22446553,2,403040752,2,2617495528,1,2978042925,1,2801168996,2,2495475500,2,1176706580,2,1001395212,2,1874870249,2,3230087383,1,2498617949,1,1714180166,2,3109677933,2,1509838052,1,320224849,1,2272630171,1,1217391130,1,276353327,1,1823429789,1,3402094521,1,751359624,1,3608460219,1,1390862571,1,1085701614,1,3445325106,1,2126500253,1,2624099526,1,1871432223,1,3373651539,1,654225716,1,1454441398,1,3704379512,1,3257374625,1,2262399392,2,309083880,1,586602603,1,1934129787,1,3146178080,1,661497638,1,2293737711,1,496827038,1,2912807649,1,2190886200,1,2069630919,1,3920618075,1,3665939353,1,3901697682,1,1211178616,1,2951515968,1,1588536425,1,2576456808,1,2127962967,1,70871065,1,1063725326,1,3101665521,1,2815374842,1,4081488368,1,3820454400,4,1624211074,1,7704646,1,830106687,1,1651678475,1,2400796504,1,910018632,2,4144776006,3,566175523,1,2975913730,1,875684520,1,2169673426,1,3450348902,1,1233775263,1,43510150,2,1645673210,2,3431876266,1,4095875831,1,2314081177,1,2590537994,2,2443660852,1,967932020,1,3171294583,1,3751351177,1,1257282635,2,200292695,3,2700376822,1,3188272159,1,3245685963,1,2120963769,1,392344172,1,1391720462,2,2610542999,1,1081247904,1,2880587164,1,2563434699,1,2253011220,1,2814234626,1,1964978567,1,1228539097,1,2026743731,1,3538443740,1,634164392,5,2759613175,1,3642863935,2,4134534481,1,1931537627,1,259381630,1,3932346318,1,2978388169,1,1431397437,2,3070493599,2,3588929783,1,3640332570,1,1787084913,4,1454955908,1,788405183,1,2563567105,2,766675725,1,2882590463,1,1499506132,1,205333986,1,4179293747,1,3236280681,3,902024186,1,2450553269,1,2629079826,1,963907309,1,1753993206,2,1923918202,2,1776498660,3,3638500874,2,1098050191,3,3084373371,1,2833060406,1,1587058252,1,2592242915,2,34507654,1,1962842866,1,4282337604,1,3561515449,1,2290978823,1,3674519521,1,2081565440,1,4109360768,2,3457519710,2,'; diff --git a/tests/data/unencodedPrefabObjects.ts b/tests/data/unencodedPrefabObjects.ts deleted file mode 100644 index 9a05c27..0000000 --- a/tests/data/unencodedPrefabObjects.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Prefab, PrefabData, PhysicalMaterialPartHash } from '../../src'; - -const position = { - x: -701, - y: 128.2, - z: 100 -}; - -export const blade: PrefabData = { - prefabObject: { - hash: Prefab.Large_Longsword_Blade.hash - }, - components: { - PhysicalMaterialPart: { - materialHash: PhysicalMaterialPartHash.EvinonSteelAlloy - }, - DurabilityModule: { - integrity: 0.01 - } - } -}; - -export const guard: PrefabData = { - prefabObject: { - hash: Prefab.Large_Guard_Rectangle.hash - }, - components: { - PhysicalMaterialPart: { - materialHash: PhysicalMaterialPartHash.Copper - }, - DurabilityModule: { - integrity: 0.01 - } - }, - childPrefabs: [ - { - parentHash: 51896, // @todo extend PrefabEmbeddedEntityHash - prefab: blade - } - ] -}; - -export const handle: PrefabData = { - prefabObject: { - hash: Prefab.Handle_Short.hash, - position - }, - components: { - NetworkRigidbody: { - position - } - }, - childPrefabs: [ - { - parentHash: 6136, // @todo extend PrefabEmbeddedEntityHash - prefab: guard - } - ] -}; - -export const litGrassClump: PrefabData = { - prefabObject: { - hash: Prefab.Grass_Clump.hash - }, - embeddedEntities: { - Fire: { - components: { - HeatSourceBase: {} - } - } - } -}; diff --git a/tests/decodeString.test.ts b/tests/decodeString.test.ts deleted file mode 100644 index 4855272..0000000 --- a/tests/decodeString.test.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { decodeString } from '../src'; -import { encodedEmptyFlask } from './data/encodedStrings'; -import { decodedEmptyFlask } from './data/decodedStrings'; - -describe('decodeString', () => { - it('decodes a string of UInts', () => { - const decodedString = decodeString(encodedEmptyFlask); - - expect(decodedString).toStrictEqual(decodedEmptyFlask); - }); -}); diff --git a/tsconfig-cjs.json b/tsconfig-cjs.json new file mode 100644 index 0000000..c65069c --- /dev/null +++ b/tsconfig-cjs.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "commonjs", + "moduleResolution": "Node", + "outDir": "dist/cjs", + "verbatimModuleSyntax": false + }, + "include": ["src/**/*"], + "exclude": ["src/**/*.test.*"] +} diff --git a/tsconfig-esm.json b/tsconfig-esm.json new file mode 100644 index 0000000..77f3e41 --- /dev/null +++ b/tsconfig-esm.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "declaration": true, + "declarationDir": "dist/types", + "declarationMap": false, + "outDir": "dist/esm", + "verbatimModuleSyntax": true + }, + "include": ["src/**/*"], + "exclude": ["src/**/*.test.*"] +} diff --git a/tsconfig.json b/tsconfig.json index 513c08e..94b5c84 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,16 +1,26 @@ { "compilerOptions": { + "allowJs": false, + "allowUnreachableCode": false, + "allowUnusedLabels": false, "esModuleInterop": true, + "exactOptionalPropertyTypes": true, "forceConsistentCasingInFileNames": true, - "module": "commonjs", - "declaration": true, - "declarationMap": false, - "sourceMap": false, - "outDir": "./dist", + "lib": ["ES2023"], + "module": "NodeNext", + "moduleResolution": "NodeNext", + "noFallthroughCasesInSwitch": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noPropertyAccessFromIndexSignature": true, + "noUncheckedIndexedAccess": true, + "noUnusedLocals": true, + "noUnusedParameters": true, "skipLibCheck": true, + "sourceMap": false, "strict": true, - "lib": ["es2017"], - "target": "es6" + "target": "ESNext", + "verbatimModuleSyntax": true }, - "include": ["./src/**/*", "./decodeString.js"] + "include": ["src/**/*", "vitest.config.ts"] } diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..748a8a5 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,22 @@ +import { defineConfig } from 'vitest/config'; + +const srcFileGlob = '*.ts'; +const testFileGlob = '*.test.ts'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: [`src/**/${testFileGlob}`], + watchExclude: ['**/node_modules/*', '**/dist/*'], + coverage: { + enabled: true, + all: true, + reportOnFailure: false, + skipFull: true, + 100: true, + include: [`src/**/${srcFileGlob}`], + exclude: [`**/${testFileGlob}`, '**/*.d.ts', 'src/index.ts', 'src/types/*'] + } + } +});