[
  {
    "path": ".github/CONTRIBUTING.md",
    "content": "# Contributing\n\nWhen contributing to this repository, please first discuss the change you wish to make via\n[GitHub issues](https://github.com/refinedmods/refinedstorage/issues), [Discord](https://discordapp.com/invite/VYzsydb),\nor any other method with the owners of this repository before making a change.\n\n## Pull requests\n\n- Keep your pull request (PR) as small as possible, this makes reviewing easier.\n- Commits serve a clear purpose and have a fitting commit message.\n- Branches are kept up to date by rebasing (updating a branch by merging makes for a confusing Git history).\n- PRs are merged by merging the commits on top of the target branch (which is `develop`).\n- Remember to add your changes in `CHANGELOG.md`. If your changes are merely technical, it's not necessary to update the\n  changelog as it's not relevant for users.\n\n### Commit messages\n\nCommit messages must adhere to [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/). We\nuse [Commitlint](https://commitlint.js.org/) to validate commit messages.\n\nWe use\nthe [conventional configuration](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional)\nfor Commitlint.\n\nIt is recommended to install\nthe [Conventional Commit plugin](https://plugins.jetbrains.com/plugin/13389-conventional-commit) to make it\neasier to write commit messages.\n\n### Branch names\n\nBecause we use merge commits when merging a PR, branch names will be part of the history of the repository. That is why\nbranch names must follow a certain standard.\n\nThe format is `{category}/GH-{issue number}/{lowercase-description}` and a branch name can be maximum 50 characters of\nlength.\n\nCategory must match a\ncategory [used in our Commitlint config](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional#type-enum).\n\nValid examples are:\n\n- `fix/GH-123/add-branch-linting`\n- `docs/GH-123/cleanup`\n\n## Versioning\n\nThis project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n### Version metadata\n\nThe code doesn't contain version metadata: `build.gradle` specifies a version of `0.0.0` (via Refined Architect).\nThe versioning information is entirely contained in Git by using tags.\n\nPer [Semantic Versioning](https://semver.org/spec/v2.0.0.html), the version number being released depends on the changes\nin that release. We usually can't predict those\nchanges at the start of a release cycle, so we can't bump the version at the start of a release cycle. That means that\nthe version number being released is determined at release time.\n\nBecause the version number is determined at release time, we can't store any versioning metadata in the\ncode (`build.gradle`). If we did, `build.gradle` would have the version number of the latest released version during the\nrelease cycle of the new version, which isn't correct.\n\n### Dealing with Minecraft\n\nWhenever we port to a new Minecraft version, at least the minor version should be incremented.\n\nThis is needed so that we can still support older Minecraft versions without the version numbers conflicting.\n\n## Changelog\n\nThe changelog is kept in `CHANGELOG.md`.\n\nKeeping a readable, relevant and user-friendly changelog is essential for our end users\nto stay up to date with the project.\n\nPlease refrain from using technical terminology or adding entries for technical changes\nthat are (generally) not relevant to the end-user.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).\n\n## Gitflow\n\nThis project uses [Gitflow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow).\n\n## Documentation\n\nDocumentation must be kept up to date when adding or changing functionality.\n\n### Javadoc\n\nJavadoc is available after every release on https://refinedmods.com/javadoc/refinedstorage.\n\n### API annotations\n\nPublic APIs must be annotated with an `@API` annotation\nfrom [API Guardian](https://github.com/apiguardian-team/apiguardian).\n\n## Code style\n\nWe use [Checkstyle](https://checkstyle.sourceforge.io/) in our build workflow to validate coding style.\n\nIt is recommended to import the [config/checkstyle/checkstyle.xml](../config/checkstyle/checkstyle.xml) file into your\nIDE, so that formatting rules are respected.\n\nMoreover, the [CheckStyle-IDEA plugin](https://plugins.jetbrains.com/plugin/1065-checkstyle-idea) can be used to check\nif there are no style violations.\n\n## Release process\n\nThe release process is automated and follows Gitflow.\n\nBefore running the \"Draft release\" workflow to start the release process make sure `CHANGELOG.md` contains all the\nunreleased changes.\n\nTo determine the version number to be released, the workflow will ask you which release type this is (major, minor,\npatch).\nThe latest version from `CHANGELOG.md` will be used as a base, and that will be incremented\ndepending on the release type.\n\n`CHANGELOG.md` will be updated by this workflow, you can review this in the resulting release PR.\n\nIf you merge the release PR, the \"Publish release\" workflow will automatically publish the release. An additional PR\nwill be created to merge the changes in `CHANGELOG.md` back into `develop`.\n\n## Hotfix process\n\nThe hotfix process is semi-automated and follows Gitflow:\n\n- Create a hotfix branch off `main`.\n- Commit your changes on this branch.\n- Update `CHANGELOG.md` (with version number and release date) manually on this branch.\n- Push the branch and create a PR for it, merging into `main`.\n\nThe \"Publish release\" workflow will take care of the rest.\n\n## Workflows\n\nWe have a few GitHub workflows:\n\n- Build (PRs, pushes to `develop` and `main`)\n- Draft release (manual trigger)\n- Publish release (merging a PR to `main`)\n- Validate changelog (PRs)\n  - To validate if `CHANGELOG.md` is valid and updated.\n  - Not every pull request needs a changelog change, so the `skip-changelog` label can be added to the pull request to\n    ignore this.\n- Validate commit messages (PRs)\n  - Validates whether the commits on a pull request\n    respect [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).\n  - We use\n    the [conventional configuration](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional).\n- Validate branch names (PRs)\n- Issue for unsupported version (issues)\n  - Posts a message on a GitHub issue if the issue is about an unsupported version.\n- Lock resolved issues and PRs (every night)\n\n### Build\n\nThe build workflow triggers when a pull request is updated or when a commit is pushed to `develop` or `main`.\n\nThe build workflow takes care of the following:\n\n- Running a Gradle build, running our tests in the process and generating an aggregated code coverage report for the API\n  modules.\n- Code style validation with Checkstyle.\n- Mutation and line coverage test with Pitest.\n- Uploading the artifacts on the action.\n\n### Draft release\n\nThe draft release workflow is a manual workflow which will create a release branch from `develop`.\n\nTo determine the version number to be released, it will extract the latest version number from `CHANGELOG.md` and\nincrement it depending on the release type selected.\n\nThis workflow takes care of the following:\n\n- Creating the release branch.\n- Updating the changelog on this release branch.\n- Creating a pull request merging the release branch into `main`.\n\n### Publish release\n\nThe \"publish release\" workflow is triggered when a release or hotfix PR is merged to `main`. Usually, this will be the\nPR created earlier in the \"Draft release\" workflow.\n\nThe workflow takes care of the following:\n\n- Extracting the version number from the release or hotfix branch name that is merged in the PR.\n- Extracting the changelog entry for this version number.\n- Running a build.\n- Publishing on [GitHub packages](https://github.com/refinedmods/refinedstorage/packages) and\n  CreeperHost Maven.\n- Publishing Javadoc on [GitHub pages](https://github.com/refinedmods/javadoc).\n- Deploying on [GitHub releases](https://github.com/refinedmods/refinedstorage/releases).\n- Announcing the release on Discord and Twitter.\n- Creating a PR that merges `main` back into `develop` to get the changes to `CHANGELOG.md` and `build.gradle`\n  into `develop` from the draft release workflow.\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "patreon: raoulvdberge\nko_fi: raoulvdberge\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n    - name: 🚫 No support for v1.x\n      url: https://refinedmods.com/refined-storage/need-help.html#_supported_versions\n      about: Refined Storage v1.x is no longer maintained. We do not accept issues or provide support for it.\n    - name: 🛠 Refined Storage v2.x Issue Tracker\n      url: https://github.com/refinedmods/refinedstorage2/issues\n      about: Report all bugs, suggestions, and support requests for Refined Storage v2.x here.\n    - name: Discord Community Support\n      url: https://discordapp.com/invite/VYzsydb\n      about: Please ask and answer questions here. Issues should be used for bugs and feature requests.\n"
  },
  {
    "path": ".github/SUPPORT.md",
    "content": "# Support\n\nIf you have a problem and need help, we offer various channels where you can ask for help.\n\n## I have a question\n\nQuestions can be asked on [Discord](https://discordapp.com/invite/VYzsydb).\n\n## I have found a bug\n\nIf you have found a bug, please report it on [GitHub issues](https://github.com/refinedmods/refinedstorage/issues)."
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: Build\non:\n  push:\n    branches:\n      - develop\n      - main\n  pull_request:\n    types: [ opened, synchronize, reopened ]\njobs:\n  build:\n    uses: refinedmods/refinedarchitect/.github/workflows/build.yml@v0.11.4\n    with:\n      mutation-testing: false\n      sonarqube: false\n    secrets: inherit\n"
  },
  {
    "path": ".github/workflows/draft-release.yml",
    "content": "name: Draft release\non:\n  workflow_dispatch:\n    inputs:\n      release-type:\n        description: 'Release type'\n        required: true\n        default: 'minor'\n        type: choice\n        options:\n          - major\n          - minor\n          - patch\n      version-number-override:\n        description: 'Version number override'\n        required: false\n        type: string\njobs:\n  draft:\n    uses: refinedmods/refinedarchitect/.github/workflows/draft-release.yml@v0.11.4\n    with:\n      release-type: ${{ inputs.release-type }}\n      version-number-override: ${{ inputs.version-number-override }}\n    secrets: inherit\n"
  },
  {
    "path": ".github/workflows/issue-for-unsupported-version.yml",
    "content": "name: Issue for unsupported version\non:\n  issues:\n    types: [ labeled, unlabeled, reopened ]\njobs:\n  unsupported-labeler:\n    uses: refinedmods/refinedarchitect/.github/workflows/issue-for-unsupported-version.yml@v0.11.4"
  },
  {
    "path": ".github/workflows/publish-release.yml",
    "content": "name: Publish release\non:\n  pull_request:\n    branches:\n      - main\n    types:\n      - closed\njobs:\n  publish-release:\n    uses: refinedmods/refinedarchitect/.github/workflows/publish-release.yml@v0.11.4\n    secrets: inherit\n    with:\n      project-name: 'Refined Storage'\n      announce: true\n      mutation-testing: false\n      curseforge: true\n      modrinth: true\n      sonarqube: false"
  },
  {
    "path": ".github/workflows/resolved-issue-locking.yml",
    "content": "name: Lock resolved issues and PRs\non:\n  schedule:\n    - cron: '0 0 * * *'\njobs:\n  lock:\n    uses: refinedmods/refinedarchitect/.github/workflows/resolved-issue-locking.yml@v0.11.4"
  },
  {
    "path": ".github/workflows/validate-branch-name.yml",
    "content": "name: Validate branch name\non: [ pull_request ]\njobs:\n  validate-branch-name:\n    uses: refinedmods/refinedarchitect/.github/workflows/validate-branch-name.yml@v0.11.4"
  },
  {
    "path": ".github/workflows/validate-changelog.yml",
    "content": "name: Validate changelog\non:\n  pull_request:\n    types: [ opened, synchronize, reopened, ready_for_review, labeled, unlabeled ]\njobs:\n  validate-changelog:\n    uses: refinedmods/refinedarchitect/.github/workflows/validate-changelog.yml@v0.11.4\n    with:\n      validation-level: 'warn'"
  },
  {
    "path": ".github/workflows/validate-commit-messages.yml",
    "content": "name: Validate commit messages\non: [ pull_request ]\njobs:\n  validate-commit-messages:\n    uses: refinedmods/refinedarchitect/.github/workflows/validate-commit-messages.yml@v0.11.4"
  },
  {
    "path": ".gitignore",
    "content": ".gradle/\n.nb-gradle/\n.settings/\nbuild/\neclipse/\n.classpath\n.nb-gradle-properties\n.project\n*.launch\nruns/\n*.iml\n*.ipr\n*.iws\n.idea/\nout/\n/bin/\nlogs/\n**/.DS_Store\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres\nto [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n## [1.13.0-beta.4] - 2024-03-07\n\n### Added\n\n-   Added Hungarian translation.\n\n### Fixed\n\n-   Fixed an error that occurred when targeting the crafter with Jade installed\n\n## [1.13.0-beta.3] - 2024-03-05\n\n### Fixed\n\n-   Fixed items in disks deserializing with an empty NBT tag.\n-   Fixed placing fluids in the pattern grid disconnecting the client.\n\n## [1.13.0-beta.2] - 2024-02-16\n\n### Fixed\n\n-   Fixed JEI transfer in the Pattern Grid wrongly choosing \"Processing\" mode.\n-   Fixed JEI transfer not working in single player.\n\n## [1.13.0-beta.1] - 2024-02-12\n\n### Added\n\n-   Ported to Minecraft 1.20.4.\n\n## [1.12.4] - 2023-11-05\n\n### Added\n\n-   Re-added compatibility with Inventory Sorter.\n\n### Fixed\n\n-   Various world corruption issues if Refined Storage blocks were removed unexpectedly or with another mod.\n-   Fixed Grid search bar not being able to lose focus.\n-   Fixed JEI transfer crash for larger processing recipes.\n-   Fixed rare autocrafting crash.\n-   Fixed some models in inactive state being emissive.\n-   Fixed Controller item not rendering energy state correctly.\n-   Fixed duplication bug with the Crafting Grid.\n-   Fixed fluid duplication bug with the Importer and GregTechCEu machines.\n-   Attempted to fix issue where Grid doesn't load items and requires a client restart.\n-   Fixed Crafter Manager slots being able to sort with Inventory Sorter.\n-   Fixed duplication bug in the Crafter with Inventory Sorter.\n\n## [1.12.3] - 2023-07-07\n\n### Fixed\n\n-   Fixed not being able to type \"e\" in Grid search box.\n\n## [1.12.2] - 2023-07-05\n\n### Fixed\n\n-   The Grid detailed tooltip now has a small font size again.\n-   Fixed not being able to close GUIs anymore with autoselected search box mode.\n-   Fixed lingering tooltips of side buttons.\n\n## [1.12.1] - 2023-07-03\n\n### Fixed\n\n-   Fixed packages not being published to Maven.\n\n## [1.12.0] - 2023-07-03\n\n### Changed\n\n-   Ported to Minecraft 1.20.1.\n\n### Fixed\n\n-   Fixed GUI side buttons not working sometimes when using Refined Storage with addons.\n\n## [1.11.7] - 2023-11-12\n\n### Fixed\n\n-   Various world corruption issues if Refined Storage blocks were removed unexpectedly or with another mod.\n-   Fixed JEI transfer crash for larger processing recipes.\n-   Fixed rare autocrafting crash.\n-   Fixed duplication bug with the Crafting Grid.\n-   Fixed fluid duplication bug with the Importer and GregTechCEu machines.\n-   Attempted to fix issue where Grid doesn't load items and requires a client restart.\n\n## [1.11.6] - 2023-03-30\n\n### Fixed\n\n-   Fixed not being able to search with JEI when the Grid is open.\n-   Fixed a bunch of issues where chunks would unintentionally be loaded by RS.\n-   Reduced block updates when a controller is turning on and off constantly.\n\n## [1.11.5] - 2023-02-12\n\n### Fixed\n\n-   Fixed some craftable items not showing as craftable in JEI\n-   Fixed Grid crashing on exit if JEI mod is not used\n-   Fixed rare multithreading crash\n-   Fixed Constructor being able to drop more than the maximum stack size for an item \n\n## [1.11.4] - 2022-12-20\n\n### Fixed\n\n-   Fixed duplication bug in the Interface.\n\n## [1.11.3] - 2022-12-20\n\n### Fixed\n\n-   Fixed external storage cache being de-synced from the network cache.\n-   Fixed external storage using an out of date block entity for getting handler.\n-   Fixed inventory slots being reused incorrectly in rare cases in the JEI transfer handler.\n\n### Changed\n\n-   Increased packet size limit.\n\n## [1.11.2] - 2022-12-17\n\n### Added\n\n-   Available items indicator in JEI now updates while JEI is open.\n\n### Fixed\n\n-   Fixed chained crafters not taking over the name of the root crafter.\n-   Fixed lag when opening JEI in large systems.\n-   Made Refined Storage more robust against crashes when moving network blocks by unconventional means.\n\n## [1.11.1] - 2022-10-30\n\n### Fixed\n\n-   Fixed not using Forge silicon tag for recipes.\n-   Small corrections to the Korean translation.\n\n## [1.11.0] - 2022-09-30\n\n### Changed\n\n-   Ported to Minecraft 1.19.2.\n\n## [1.10.6] - 2023-11-26\n\n### Fixed\n\n-   Fixed a bunch of issues where chunks would unintentionally be loaded by RS.\n-   Reduced block updates when a controller is turning on and off constantly.\n-   Various world corruption issues if Refined Storage blocks were removed unexpectedly or with another mod.\n-   Fixed JEI transfer crash for larger processing recipes.\n-   Fixed rare autocrafting crash.\n-   Fixed duplication bug with the Crafting Grid.\n-   Fixed fluid duplication bug with the Importer in certain situations.\n-   Attempted to fix issue where Grid doesn't load items and requires a client restart.\n\n## [1.10.5] - 2023-02-12\n\n### Fixed\n\n-   Fixed rare multithreading crash\n-   Fixed Constructor being able to drop more than the maximum stack size for an item\n\n## [1.10.4] - 2022-12-20\n\n### Fixed\n\n-   Fixed external storage cache being de-synced from the network cache.\n-   Fixed external storage using an out of date block entity for getting handler.\n-   Fixed chained crafters not taking over the name of the root crafter.\n-   Made Refined Storage more robust against crashes when moving network blocks by unconventional means.\n-   Fixed duplication bug in the Interface.\n\n### Changed\n\n-   Increased packet size limit.\n\n## [1.10.3] - 2022-08-06\n\n### Fixed\n\n-   Fixed Destructor dupe bug\n-   Fixed being unable to insert items into the Storage Monitor\n-   Fixed Storage Monitor not showing all matching items in non-exact mode\n-   Fixed items getting lost on Creative Disk when more than 2,147,483,647 of one type is stored\n-   Fixed incorrect autocrafting keybind prompt on macOS\n-   Fixed crashing the game when a network block was removed in a bad way\n-   Fixed duplication bug with Constructors and Shulker Boxes\n-   Fixed breaking blocks with pickaxe taking too much time\n\n### Changed\n\n-   Improved performance for grid updates\n-   Improved waterlogging to behave more like vanilla\n-   JEI version 9.7.1 or higher is now required\n\n### Added\n\n-   Forge relocation and Packing Tape blacklist tag entries to prevent block movement\n-   Japanese translations for certain autocrafting actions\n\n## [1.10.2] - 2022-03-26\n\n### Changed\n\n-   Ported to Minecraft 1.18.2.\n\n## [1.10.1] - 2022-03-26\n\n### Fixed\n\n-   Fixed crash when opening alternatives screen.\n\n## [1.10.0] - 2022-01-25\n\n### Fixed\n\n-   Fixed multiple bugs related to transferring recipes into the Crafting Grid.\n-   Processing patterns now use the order of items/fluids specified in the pattern\n    by [@necauqua](https://github.com/necauqua) and [@Darkere](https://github.com/Darkere).\n-   Fixed autocrafting task getting stuck if two tasks fulfilled each others requirements.\n-   Fixed fluid autocrafting breaking when using 2 stacks of the same fluid in a pattern.\n-   Amount specifying screen is now limited to valid values.\n-   Fixed crash on servers when starting with latest Forge.\n\n## [1.10.0-beta.4] - 2021-12-28\n\n### Fixed\n\n-   Fixed client crash when hovering over a fluid in the Fluid Grid by [@jackodsteel](https://github.com/jackodsteel).\n-   Fixed random client crashes when starting the game.\n\n### Changed\n\n-   Update Korean translation by [@mindy15963](https://github.com/mindy15963).\n\n## [1.10.0-beta.3] - 2021-12-17\n\n### Fixed\n\n-   Fixed networks and network devices being removed when a chunk unloads.\n\n## [1.10.0-beta.2] - 2021-12-16\n\n### Fixed\n\n-   Fixed all Refined Storage advancements being granted when joining a world.\n-   Fixed potential Pattern crash when loading Minecraft.\n\n## [1.10.0-beta.1] - 2021-12-15\n\n### Fixed\n\n-   Fixed Relay not working.\n-   Fixed Wireless Transmitter only working upright.\n-   Fixed Portable Grid not opening when pointing at a block.\n-   Fixed being able to circumvent locked slots by scrolling.\n\n### Changed\n\n-   Added more slots to the Pattern Grid.\n-   Combined fluid and item view in the Pattern Grid.\n-   Ported to Minecraft 1.18.1.\n-   Focused side buttons now display their tooltip properly.\n-   Improved performance of retrieving patterns by [@metalshark](https://github.com/metalshark).\n\n## [1.9.18] - 2022-05-18\n\n### Fixed\n\n-   Fixed potential Pattern crash when loading Minecraft.\n\n## [1.9.17] - 2022-01-30\n\n### Added\n\n-   More slots for the Pattern Grid.\n\n### Changed\n\n-   Combined fluid and item view in the Pattern Grid.\n-   Processing patterns now use the order of items/fluids specified in the pattern.\n-   Amount specifying screen is now limited to valid values.\n\n### Fixed\n\n-   Fixed Relay not working.\n-   Fixed Wireless Transmitter only working upright.\n-   Fixed Portable Grid not opening when pointing at a block.\n-   Fixed being able to circumvent locked slots by scrolling.\n-   Fixed multiple bugs related to transferring recipes into the crafting grid.\n-   Fixed autocrafting task getting stuck if two tasks fulfilled each others requirements.\n-   Fixed fluid autocrafting breaking when using 2 stacks of the same fluid in a pattern.\n\n## [1.9.16] - 2021-11-16\n\n### Added\n\n-   Added Covers for all cable types.\n-   Added Polish translation.\n-   Added Italian translation.\n-   Addons can now override how crafters insert items.\n\n### Changed\n\n-   Improved JEI integration to pick the best option when transferring items.\n\n### Fixed\n\n-   Fixed an issue where too many items in a grid would kick the player.\n-   Fixed an issue where the portable grid does not open from Inventory anymore after some use.\n-   Fixed craftable view in grids not showing items that were already in storage.\n-   Fixed Wireless Crafting Monitor not working as Curio.\n-   Fixed wrong slot being locked in some cases when opening a wireless item.\n-   Slightly sped up External Storage item look up.\n-   Fixed extraction from Storage Monitor not respecting maximum stack size.\n\n## [1.9.15] - 2021-07-25\n\n### Fixed\n\n-   Fixed Refined Storage Addons compatibility.\n\n## [1.9.14] - 2021-07-25\n\n### Added\n\n-   Implemented Curios support.\n\n## [1.9.13] - 2021-06-14\n\n### Added\n\n-   Added some performance improvements for autocrafting.\n\n### Fixed\n\n-   Fixed count on Storage Monitor having Z fighting.\n-   Fixed items on Storage Monitor not being flat.\n-   Fixed crash when using an External Storage on a fluid inventory.\n-   Fixed a memory leak in the pattern cache.\n-   Fixed Detector crashing when dyed.\n-   Fixed autocrafting being stuck after clicking \"Start\".\n-   Fixed Crafting Monitor not being able to show hours.\n-   Fixed capacity rendering of infinite storages.\n-   Fixed wrong alignment for the JEI request autocrafting tooltip.\n-   Fixed mobs getting stuck in Refined Storage cables.\n-   Fixed dismantling storage blocks ignoring stack size.\n-   Fixed Ice and Fire banners breaking with Refined Storage.\n-   Fixed empty keybinding causing GL errors.\n-   Fixed some parts of the Japanese translation.\n-   Fixed rendering issue on blocks when using OptiFine.\n\n### Removed\n\n-   Removed experimental pipeline nagging message.\n\n## [1.9.12] - 2021-02-07\n\n### Fixed\n\n-   Fixed some issues when using the Grid when it's offline.\n-   Fixed crafting events not being fired in some cases in the Grid.\n-   Fixed not being able to set fluid filter slot output quantity.\n-   Fixed mod id search not working for Industrial Foregoing.\n-   Fixed fluid autocrafting duplicating fluids.\n-   Fixed some Grid crashes.\n-   Fixed constructor not using compare mode correctly in some cases.\n-   Fixed duplication bug in the Interface.\n\n## [1.9.11] - 2021-01-03\n\n### Fixed\n\n-   Fixed disks and network devices not loading when they did not previously exist\n    -   If you are affected by this please go to the world/data/ folder and remove the \".temp\" ending from the files\n        before\n        launching.\n\n## [1.9.10] - 2021-01-02\n\n### Changed\n\n-   Update Japanese translation.\n\n### Fixed\n\n-   Improve performance of the Grid view.\n-   Fixed Disk Manipulator model glitches.\n-   Improve performance of the Disk Manipulator.\n-   Fixed being unable to set quantity in output slots of the Pattern Grid.\n-   Fixed External Storage in fluid mode losing track of fluids sometimes.\n-   Added code to avoid / minimize data corruption issues caused by Minecraft.\n-   Fixed processing autocrafting orders stealing items from each other.\n-   Fixed Constructor in fluid mode voiding fluid source blocks in front of it.\n-   Fixed crash when recoloring blocks that have no rotation component.\n-   Fixed reloading resource packs breaking Refined Storage textures.\n\n## [1.9.9] - 2020-11-14\n\n### Fixed\n\n-   Fixed Refined Storage sidebuttons displaying over the JEI bookmark pagination buttons.\n-   Fixed issue where Crafters may fail to recognize an inventory/tank for some patterns.\n-   Fixed issue where the Crafter Manager can crash on invalid patterns.\n-   Fixed issue where alternatives in the Pattern Grid weren't being saved properly.\n-   Fixed not being able to change the Exporter filter slot count with regulator mode without closing and re-opening the\n    container.\n\n## [1.9.8] - 2020-10-24\n\n### Added\n\n-   Added a JEI synchronized (two-way) search box mode to the Grid.\n-   Added a nag message when a player joins the world that asks the player to enable the experimental Forge lighting\n    pipeline to ensure correct rendering.\n\n### Fixed\n\n-   Fixed server crash when scrolling in Grid.\n-   Fixed various issues with Grid interactions working without power.\n-   Fixed changing rotation not updating blocks.\n\n## [1.9.7] - 2020-10-04\n\n### Added\n\n-   Added functionality to move items in the Grid with shift/ctrl + scrolling.\n\n### Changed\n\n-   Changed JEI transfer error mechanics.\n\n### Fixed\n\n-   Fixed crash when opening Controller GUI.\n-   Fixed dye being consumed without effect in some cases.\n-   Fixed deadlock caused by Portable Grid.\n-   Fixed custom tooltips not working in the Grid.\n\n## [1.9.6] - 2020-09-25\n\n### Added\n\n-   Port to Minecraft 1.16.3.\n-   Added colored block variants.\n-   Added functionality to show missing items in the JEI transfer screen.\n-   Added functionality to request missing items from autocrafting in the JEI transfer screen.\n-   Added client config option to remember the Grid search query.\n\n### Fixed\n\n-   Fixed Portable Grid losing enchantments when placing and breaking.\n\n## [1.9.5] - 2020-09-06\n\n### Added\n\n-   Re-added the `/refinedstorage disk create <player> <id>` command.\n-   Added the `/refinedstorage disk list` command.\n-   Added the `/refinedstorage disk list <player>` command.\n-   Added the `/refinedstorage network list <dimension>` command.\n-   Added the `/refinedstorage network get <dimension> <pos>` command.\n-   Added the `/refinedstorage network get <dimension> <pos> autocrafting list` command.\n-   Added the `/refinedstorage network get <dimension> <pos> autocrafting get <id>` command.\n-   Added the `/refinedstorage network get <dimension> <pos> autocrafting cancel` command.\n-   Added the `/refinedstorage network get <dimension> <pos> autocrafting cancel <id>` command.\n-   Added JEI ghost ingredient dragging support.\n\n### Fixed\n\n-   Fixed text field not being focused in amount specifying screens.\n\n## [1.9.4] - 2020-08-30\n\n### Fixed\n\n-   Fixed JEI recipes/usages keys not working in Grids.\n\n## [1.9.3-beta] - 2020-08-24\n\n### Added\n\n-   Port to Minecraft 1.16.2.\n\n### Changed\n\n-   Updated Japanese translation.\n-   Updated Taiwanese translation.\n-   Refactored autocrafting code.\n\n### Fixed\n\n-   Fixed duplication bug with the Constructor.\n\n## [1.9.2-beta.2] - 2020-09-11\n\n### Fixed\n\n-   Fixed duplication bug with the Constructor.\n\n## [1.9.2-beta.1] - 2020-07-17\n\n### Added\n\n-   Re-added interdimensional networks with the Network Transmitter and Network Receiver.\n-   Re-added MouseTweaks integration.\n\n### Changed\n\n-   Networks that are in a chunk that isn't loaded will no longer work, they will turn off. Chunkload the Controller to\n    maintain a functioning network over long distances.\n\n### Fixed\n\n-   Fixed crash with Forge version 67.\n-   Fixed cases where Refined Storage unwillingly acts like a chunkloader.\n-   Fixed Network Transmitters being able to connect to any network device.\n-   Fixed Crafting Tweaks buttons being in the wrong position after changing the size configuration of the Grid.\n\n## [1.9.1-beta] - 2020-07-14\n\n### Fixed\n\n-   Fixed server crash.\n\n## [1.9.0-beta] - 2020-07-14\n\n### Added\n\n-   Port to Minecraft 1.16.\n\n### Fixed\n\n-   Fixed wrench requiring shift click to rotate blocks.\n\n## [1.8.8] - 2020-07-13\n\n### Fixed\n\n-   Fixed duplication bug and weird behavior in the Crafting Grid matrix.\n\n## [1.8.7] - 2020-07-11\n\n### Fixed\n\n-   Fixed Regulator mode item and fluid counts not saving properly.\n-   Fixed Wireless Crafting Monitor not closing properly.\n-   Fixed Controller always using energy, even when disabled with redstone.\n-   Fixed internal crafting inventory not being returned when Controller is broken.\n-   Fixed bug where autocrafting tasks started on the same tick make the wrong assumption about available items and\n    fluids.\n-   Fixed bug where the \"To craft\" amount in the Crafting Preview window is wrong.\n-   Fixed bug where non-pattern items are able to be inserted into the Crafter Manager (Darkere)\n-   Fixed performance issue where shapes of cable blocks were constantly being recalculated.\n\n### Changed\n\n-   Drastically improved shift clicking performance in Crafting Grid.\n\n### Removed\n\n-   Removed autocrafting engine version from crafting preview screen.\n\n## [1.8.6-beta] - 2020-06-26\n\n### Fixed\n\n-   Fixed Constructor duplication bug.\n\n## [1.8.5-beta] - 2020-06-18\n\n### Added\n\n-   Re-added all the language files.\n-   Japanese translations.\n\n### Fixed\n\n-   Fixed Portable Grid voiding the disk when extracting with full inventory.\n-   Fixed Constructor extracting 2 buckets when placing fluid.\n-   Fixed Stack Overflow error with regulator upgrades.\n-   Fixed visual bug with the Detector not updating its values.\n-   Fixed Constructor placing the filtered item instead of the extracted.\n-   Fixed duplication bug with filter slots.\n-   Fixed shift crafting in a Grid not using the player.\n-   Fixed bug where shift clicking gives too many items.\n\n### Changed\n\n-   Cancelling a crafting task now also unlocks all Crafters related to that task.\n-   External Storage will now always show the exact maximum capacity as reported by the attached inventory.\n-   Crafters no longer expose their inventory to the side they are facing.\n-   Changed package name to `com.refinedmods.refinedstorage`, this is a breaking change for addons.\n\n## [1.8.4-beta] - 2020-05-26\n\n### Fixed\n\n-   Fixed autocrafting Crafting Monitor crash.\n\n## [1.8.3-beta] - 2020-04-29\n\n### Added\n\n-   A new experimental autocrafting engine that's enabled by default. This should improve autocrafting performance.\n-   The Regulator Upgrade that can be inserted into a Exporter. This ensures a certain amount of items and fluids is\n    kept in stock in a connected inventory.\n-   Debug logging on the server when an expensive operation occurs.\n\n### Fixed\n\n-   Fixed Exporter not exporting anything when using a Stack Upgrade and there isn't space for 64 items in the inventory.\n-   Fixed Controller always using the base usage even when turned off.\n-   Fixed severe memory leak in the storage cache.\n\n### Changed\n\n-   Wireless Transmitters can now be placed on any block and in any direction.\n\n## [1.8.2-beta] - 2020-04-25\n\n### Added\n\n-   Refined Storage silicon is now present in `forge:silicon` tag for mod compatibility.\n-   Waterlogging to all cable blocks.\n-   Create zh_tw translation.\n-   Re-added zh_cn translation.\n\n### Fixed\n\n-   Fixed storage block dropping extra processor.\n\n### Changed\n\n-   Updated pt_br translation.\n\n## [1.8.1-beta] - 2020-01-30\n\n### Added\n\n-   Port to Minecraft 1.15.2.\n-   Fluid support for the Storage Monitor.\n\n## [1.8.0-beta] - 2020-01-21\n\n### Added\n\n-   Port to Minecraft 1.15.\n\n## [1.7.3-beta] - 2019-12-30\n\n### Fixed\n\n-   Fixed severe energy update lag introduced by version 1.7.2.\n\n## [1.7.2-beta] - 2019-12-29\n\n### Added\n\n-   Resource packs can now define the font colors that Refined Storage GUIs need to use.\n\n### Fixed\n\n-   Fixed crash when loading a network.\n-   Fixed being able to drain energy from the Refined Storage Controller.\n-   Fixed the Grid crashing on a item/fluid update-heavy storage system.\n-   Fixed the Grid displaying the old quantity when shift clicking an entire stack out.\n-   Fixed crash with the Disk Manipulator and using item/fluid filters when inserting into the network.\n-   Fixed the network being able to run off 1 FE/t.\n\n### Changed\n\n-   Patterns being added or removed from the network are now propagated as well to clients that are watching a Grid.\n-   When pressing ESCAPE in the search box on the Grid or Crafter Manager, focus on the search bar will be lost first\n    before closing the GUI immediately. Then on the next ESCAPE press, the GUI will be closed.\n\n## [1.7.1-alpha] - 2019-11-19\n\n### Fixed\n\n-   Fixed Pattern Grid causing world hanging on load.\n-   Fixed External Storage not refreshing when the storage is broken or replaced.\n-   Fixed delay in block update when placing a cable block.\n-   Fixed holder of cable blocks sometimes conflicting with a cable connection while rendering.\n-   Fixed being able to move wireless items in inventory when using a keybinding to open.\n-   Fixed crash when breaking a Grid, Crafting Monitor, Crafter Manager or Portable Grid when another player is still\n    using it.\n\n### Changed\n\n-   The Pattern Grid now switches automatically between crafting pattern and processing pattern mode when using JEI\n    transfer.\n-   The Pattern Grid now switches automatically between crafting pattern and processing pattern mode when re-inserting an\n    existing Pattern.\n-   Grids now do not sort if you interact with it while holding shift.\n\n### Removed\n\n-   Exact mode for processing patterns no longer exist, you can now define per-slot which item/fluid tags are allowed to\n    be used by autocrafting, by using CTRL + click on the filter slot in the Pattern Grid.\n-   Removed migration code for the development builds that were released on Discord (not on CurseForge). If you used the\n    development builds and never used version 1.7.0 before, first switch to 1.7.0, open your world, modify a storage disk,\n    and then upgrade to 1.7.1.\n\n## [1.7.0-alpha] - 2019-11-02\n\n### Added\n\n-   Port to Minecraft 1.14.\n\n### Fixed\n\n-   Fixed the Fluid Grid not having a View type setting.\n\n### Changed\n\n-   Oredict mode for Patterns has been replaced with \"Exact mode\" (by default on). When exact mode is off, Refined Storage\n    will use equivalent items or fluids from the Minecraft item/fluid tag system.\n-   Grid filtering with \"$\" now does filtering based on item/fluid tag name instead of oredict name.\n-   When binding a network item to a network you can now bind to any network block, not only the Controller.\n\n### Removed\n\n-   The Reader and Writer, this will return later in an addon mod.\n-   Cross dimensional functionality on the Network Transmitter for the moment, this will return later.\n-   Covers.\n\n## [1.7.0+10] - 2019-10-29\n\n### Added\n\n-   Re-added oredict mode as \"exact mode\" (for fluids too!).\n-   Re-added the Crafter Manager.\n-   Re-added the Crafting Monitor.\n-   Re-added the Wireless Crafting Monitor.\n\n### Fixed\n\n-   Fixed the ugly checkboxes\n-   Misc bugfixes and crash fixes.\n\n## [1.7.0+9] - 2019-10-28\n\n### Added\n\n-   Re-add the Crafter and autocrafting.\n\n### Fixed\n\n-   Misc bugfixes and crash fixes.\n\n## [1.7.0+8] - 2019-10-27\n\n### Added\n\n-   Re-added the Constructor.\n-   Re-added the Destructor.\n-   Re-added the Disk Manipulator.\n-   Re-added the Portable Grid.\n\n## [1.7.0+7] - 2019-10-22\n\n### Fixed\n\n-   Fixed a crash that can happen when opening a world.\n\n## [1.7.0+6] - 2019-10-22\n\n### Added\n\n-   Re-added the Network Transmitter (not cross dimensional yet).\n-   Re-added the Network Receiver.\n-   Re-added the Relay.\n-   Re-added the Detector.\n-   Re-added the Security Manager.\n-   Re-added the Interface.\n-   Re-added the Fluid Interface.\n-   Re-added the Wireless Transmitter.\n-   Re-added the Storage Monitor.\n-   Re-added the Wireless Grid.\n-   Re-added the Wireless Fluid Grid.\n\n### Fixed\n\n-   Misc bugfixes and crash fixes.\n\n## [1.7.0+5] - 2019-10-17\n\n### Added\n\n-   Re-added the External Storage.\n-   Re-added the Importer.\n-   Re-added the Exporter.\n\n### Removed\n\n-   Cutting Tool (you may get a Forge warning about that one, it's safe to ignore).\n-   The \"compare nbt\" side button, replaced it with \"exact mode\".\n\n## [1.7.0+4] - 2019-10-15\n\n### Added\n\n-   Re-added all the storage blocks.\n-   Re-added JEI integration.\n\n### Fixed\n\n-   Misc bugfixes and crash fixes.\n\n## [1.7.0+3] - 2019-10-12\n\n### Added\n\n-   Re-added the Crafting Grid.\n-   Re-added the Pattern Grid.\n-   Re-added the Fluid Grid.\n-   Re-added Optifine compatibility.\n\n## [1.7.0+2] - 2019-10-10\n\n### Added\n\n-   More config values.\n\n### Fixed\n\n-   Misc bugfixes and crash fixes.\n\n### Removed\n\n-   Free dirt every 10 ticks.\n\n## [1.7.0+1] - 2019-10-09\n\n### Added\n\n-   Re-added the Controller.\n-   Re-added the Disk Drive.\n-   Re-added the Grid.\n\n## [1.6.16] - 2020-04-26\n\n### Fixed\n\n-   Fixed erroring controller tile entity.\n-   Fixed Inventory Tweaks sorting not respecting locked slots.\n-   Fixed OpenComputers driver voiding excess fluids.\n-   Fixed being able to move wireless items in inventory.\n\n### Changed\n\n-   Updated Russian translation.\n\n## [1.6.15] - 2019-07-21\n\n### Fixed\n\n-   Fixed recipes with more than 1 bucket of fluid not transferring from JEI.\n-   Fixed oredict crafting patterns redefining recipes.\n-   Fixed Portable Grids not keeping their enchantments when placed.\n-   Fixed JEI hotkeys not working on fluid filter slots.\n-   Fixed crash when opening Crafter Manager with FTB Quests installed.\n-   Fixed a bug where the container slots weren't synced when opening a Grid.\n\n### Changed\n\n-   Shortened crafting text for the Russion translation to fix Grid overlays.\n-   GregTech Community Edition Wires and Machines are now banned from rendering on Refined Storage patterns because they are causing crashes.\n\n## [1.6.14] - 2019-03-23\n\n### Fixed\n\n-   Fixed server crash\n\n## [1.6.13] - 2019-03-23\n\n### Added\n\n-   Added keybindings to open wireless items. The default one set to open a Wireless Crafting Grid from Refined Storage Addons is CTRL + G.\n-   Added Grid quantity formatting for item counts over 1 billion.\n\n### Changed\n\n-   Updated German translation.\n-   Updated Chinese translation.\n-   The Constructor and Destructor now interacts with the world using their owner's profile.\n\n### Fixed\n\n-   Fixed Interface with Crafting Upgrade being stuck if an earlier item configuration has missing items or fluids.\n-   Fixed wrong item count for oredict patterns.\n-   Fixed autocrafting duplication bug.\n-   Fixed Crafting Pattern not rendering tile entity items like a chest.\n\n## [1.6.12] - 2018-11-28\n\n### Added\n\n-   Added a completion percentage to the Crafting Monitor.\n\n### Changed\n\n-   Updated Russian translation.\n-   Increased the speed of autocrafting.\n\n### Fixed\n\n-   Fixed External Storage sending storage updates when it is disabled.\n-   Fixed slight performance issue with loading Crafters from disk.\n-   Fixed storage GUIs overflowing on large numbers.\n\n## [1.6.11] - 2018-11-24\n\n### Fixed\n\n-   Fixed blocks neighboring a controller breaking when returning from a dimension in a unchunkloaded area.\n\n## [1.6.10] - 2018-11-23\n\n### Added\n\n-   Added fluid functions for the fluid autocrafting to the OpenComputers integration.\n\n### Changed\n\n-   Updated Russian translation.\n-   Slightly increased performance of the External Storage.\n\n### Fixed\n\n-   Fixed client FPS stalling when using \"@\" mod search in the Grid.\n-   Fixed client FPS stalling when using \"#\" tooltip search in the Grid.\n-   Fixed fluid inputs/outputs in the Pattern Grid not being set when you re-insert a Pattern with fluid inputs/outputs.\n-   Fixed bug where the Pattern Grid doesn't update it's output slot when manually configuring a crafting pattern.\n-   Fixed network node scanning allowing multiple controllers in some cases.\n-   Fixed OpenComputers integration not giving back a crafting task instance in the schedule task API.\n-   Fixed OpenComputers integration causing log spam when getting processing patterns.\n-   Fixed OpenComputers voiding items with extract item API when there is no inventory space.\n-   Fixed CraftingTweaks buttons resetting sometimes in the Crafting Grid.\n-   Fixed Refined Storage jars not being signed.\n-   Fixed crafting task stalling when there's not enough space in the inventory.\n-   Fixed another duplication bug with a disconnected Crafting Grid.\n-   Fixed oredict mode in autocrafting not working at all.\n\n### Removed\n\n-   Removed getMissingItem.\n-   Removed the Interdimensional Upgrade, Network Transmitters are now cross dimensional by default.\n-   Removed the per block FE cost of the Network Transmitter, it draws a fixed amount of FE/t now.\n\n## [1.6.9] - 2018-10-27\n\n### Changed\n\n-   You can now interact with the fluid container input slot in the Fluid Interface.\n\n### Fixed\n\n-   Fixed OpenComputers \"unknown error\" when using extract item API.\n-   Fixed client FPS stuttering when opening a Crafting Grid.\n-   Fixed rare Grid crashing issue.\n\n## [1.6.8] - 2018-10-20\n\n### Fixed\n\n-   Fixed Ender IO incompatibility.\n\n## [1.6.7] - 2018-10-19\n\n### Changed\n\n-   The Processor Binding recipe now only gives 8 items instead of 16.\n\n### Fixed\n\n-   Fixed the Raw Processor recipes not taking oredicted silicon.\n-   Fixed the Processor Binding recipe not taking oredicted slimeballs.\n\n## [1.6.6] - 2018-10-18\n\n### Added\n\n-   Added new Crafter modes: ignore redstone signal, redstone signal unlocks autocrafting, redstone signal locks autocrafting and redstone pulse inserts next set.\n-   Added a config option to configure the autocrafting calculation timeout in milliseconds.\n-   Added throttling for network devices that can request autocrafting.\n\n### Changed\n\n-   Renamed Cut Processors to Raw Processors and those are now made with Processor Binding instead of a Cutting Tool.\n-   You can no longer start a crafting task if it has missing items or fluids.\n-   The Security Manager now supports Security Cards that have no player assigned to them. It is the default security card for players that aren't configured.\n-   If no default Security Card is configured in the Security Manager, an unconfigured player is allowed to do everything in the network. Create a default Security Card.\n\n### Fixed\n\n-   Fixed an autocrafting bug where it crashed when external inventories couldn't be filled.\n-   Fixed a duplication bug with a disconnected Crafting Grid.\n-   Fixed oredict autocrafting sometimes reporting that a craftable item is missing.\n-   Fixed fluid autocrafting without item inputs locking when there's not enough space for the fluids.\n-   Fixed Grid \"last changed\" date not changing when using clear button or JEI transfer.\n-   Fixed a duplication bug when pressing clear on a Wireless Crafting Grid from Refined Storage Addons.\n-   Fixed a duplication bug with autocrafting and External Storages.\n-   Fixed Crafting Manager displaying wrong name for chained crafters connected to some blocks.\n-   Fixed crafting task losing internal buffer when network runs out of energy.\n\n### Removed\n\n-   Removed handling of reusable items in autocrafting, to avoid problems.\n\n## [1.6.5] - 2018-09-11\n\n### Changed\n\n-   The Pattern Grid in fluid mode now supports up to 64 buckets in the input and output processing slots.\n\n### Fixed\n\n-   Fixed Refined Storage silicon's oredict entry being registered too late.\n-   Fixed duplication bug with filter slots.\n\n## [1.6.4] - 2018-09-02\n\n### Changed\n\n-   Rewrote autocrafting again, bringing performance up to par with other autocrafting mods.\n-   Autocrafting now reserves items and fluids in an internal inventory to avoid having the storage network steal stacks required for autocrafting.\n-   Reworked the Crafting Monitor to be more condensed and more clear.\n\n### Fixed\n\n-   Fixed not being able to craft upgrades that require enchanted books.\n-   Fixed quick jittering of the Grid and Crafting Monitor when opening them because the tabs appear.\n\n### Removed\n\n-   Removed left / right click functionality on filter slots to increase / decrease the amount, replaced that functionality with a dialog.\n\n## [1.6.3] - 2018-08-02\n\n### Added\n\n-   Re-added a single mode Wrench that can rotate blocks and break Refined Storage covers.\n\n### Fixed\n\n-   Fixed crash with Wireless Fluid Grid.\n-   Fixed Reborn Storage crafting being slower than normal.\n\n## [1.6.2] - 2018-07-30\n\n### Fixed\n\n-   Fixed Grid searching not working.\n\n## [1.6.1] - 2018-07-30\n\n### Added\n\n-   Added fluid autocrafting.\n-   Added Crafting Upgrade support for fluids on the Exporter, Constructor and Fluid Interface.\n-   Added config option to hide covers in the creative mode tabs and JEI.\n\n### Changed\n\n-   The Portable Grid now supports fluid disks.\n-   Filters now support fluids and can be inserted in the Fluid Grid.\n-   You can now keep fluids in stock by attaching a External Storage in fluid mode to a Fluid Interface with a Crafting Upgrade.\n-   You can now specify the amount to export in the Fluid Interface.\n-   Updated Russian translation.\n-   Overhauled and updated German translation.\n-   The Crafting Upgrade no longer schedules requests when there are items or fluids missing.\n-   Made the Crafting Preview window bigger.\n\n### Fixed\n\n-   Fixed crash log when opening Pattern Grid GUI.\n-   Fixed being able to put non fluid containers in Fluid Interface input slot.\n-   Fixed Grid filters not updating Grid.\n\n### Removed\n\n-   Removed \"emit signal when item is being autocrafted\" option in the Detector.\n\n## [1.6.0] - 2018-07-20\n\n### Added\n\n-   Added the Cutting Tool.\n-   Added covers.\n-   Added new storage disk system where the storage disk data (items, fluids) are stored off the disk itself, in another file (refinedstorage_disks.dat). The disk itself only stores its ID.\n-   Added /createdisk command which creates a disk based on the disk ID. Turn on advanced tooltips to see the disk ID on a disk item.\n-   Added config option to configure controller max receive rate.\n-   Added config option to configure energy capacity of Refined Storage items.\n-   Added config option to change Reader / Writer channel energy capacity.\n-   Added a fully charged regular Controller to the creative menu.\n-   Added a missing config option for Crafter Manager energy usage.\n-   Added support for Disk Drive / Storage Block storage and capacity to OC integration.\n-   Added \"Search box mode\" button to the Crafter Manager.\n\n### Changed\n\n-   Renamed \"Printed Processors\" to \"Cut Processors\".\n-   Rewrote autocrafting.\n-   Rewrote network energy storage.\n-   The Controller item now shows a durability bar for the energy.\n-   You can no longer put a Filter in filter slots to gain additional filter slots.\n-   You can now re-insert Processing Patterns in the Pattern Grid and have the inputs and outputs be completed.\n-   If an Interface is configured to expose the entire network storage (by configuring no export slots), it will no longer expose the entire RS storage, due to performance issues.\n-   The Portable Grid no longer exposes a inventory for crossmod interaction, due to performance issues.\n-   The Crafting Monitor is now resizable and its size can be configured (stretched, small, medium, large).\n-   The Crafting Monitor now splits its tasks over tabs.\n-   An empty blacklist now means: accept any item. An empty whitelist now means: don't accept any item (an empty whitelist USED to mean: accept any item).\n-   The Importer now skips over empty slots.\n-   The Exporter now round-robins over every configured item or fluid to export instead of exporting them all at once.\n-   Updated Russian translation.\n-   Autocrafting tasks that take longer than 5 seconds to CALCULATE (NOT execute) are automatically stopped to avoid server strain.\n-   Changed fluid storage progression to be 64k - 256k - 1024k - 4096k.\n-   Made all IO blocks have a blacklist instead of a whitelist by default.\n\n### Fixed\n\n-   Fixed bug where pattern was recipe pattern was creatable when there was no recipe output.\n-   Fixed a crash when breaking an Ender IO conduit with the Destructor.\n-   Fixed bug where storage disks in Portable Grids could be moved into themselves.\n-   Fixed the Crafter crashing when opening it while connected to a Primal Tech Grill or Kiln.\n-   Fixed bug where Crafting Upgrade on Interface kept too many items in stock.\n-   Fixed bug where External Storage could only handle 1 fluid inventory per block.\n-   Fixed shift clicking a created pattern going into Grid inventory.\n-   Fixed crash when moving a wireless item with the number keys.\n-   Fixed bug where item storage tracker didn't save sometimes.\n-   Fixed bug where External Storage doesn't detect new inventory when rotating.\n-   Fixed JEI recipe transferring in Pattern Grid allowing non-processing recipes in processing mode and vice-versa.\n-   Fixed using Interfaces for minimum stock levels failing when requester is also an Interface.\n-   Fixed ItemZoom incompatibility in Grid and crafting preview window.\n-   Fixed shift clicking upgrades into Interface making upgrades go to import slots.\n-   Fixed duplication glitch with storages.\n-   Prevent accidental Grid scrollbar click after clicking JEI recipe transfer button.\n\n### Removed\n\n-   Removed Regulator mode in the Exporter.\n-   Removed MCMultiPart integration.\n-   Removed Project E integration.\n-   Removed blocking mode in autocrafting.\n-   Removed the Wrench.\n-   Removed \"void excess items or fluids\" functionality on storages.\n-   Removed the Solderer.\n-   Removed \"compare oredict\" buttons on Exporter, Importer, etc.\n-   Removed ConnectedTexturesMod integration for fullbright textures, RS now has fullbright textures natively.\n-   Removed autocrafting with fluids (the bucket filling mechanic). This will be replaced in a later version with native fluid autocrafting, where Crafters can insert fluids to external inventories.\n\n## [1.5.34] - 2018-05-22\n\n### Added\n\n-   Added OR search operator to the Grid with \"|\".\n-   Added new `getPattern(stack:table)` function for OpenComputers integration.\n\n### Changed\n\n-   Empty patterns can no longer be inserted in the pattern result slot in the Pattern Grid with hoppers.\n-   `getPatterns()` now only returns all the outputs, this to limit memory usage in OpenComputers (only affects OC integration).\n-   Allow crafters to be daisy-chained.\n\n### Fixed\n\n-   Fixed repeated key events not getting handled in some cases.\n\n## [1.5.33] - 2018-04-22\n\n### Added\n\n-   Added Crafter Manager.\n\n### Changed\n\n-   Patterns in the Crafter slots now automatically render the output without pressing shift.\n-   Increased Grid performance.\n-   Various internal refactors.\n\n### Fixed\n\n-   Fixed Disk Manipulator not extracting items.\n-   Fixed filter slots not caring about max stack size.\n-   Fixed model warning about Portable Grid.\n-   Fixed crash when autocompleting Ender IO recipes from JEI.\n-   Fixed Grid not always using all combinations when using JEI autocompletion.\n\n## [1.5.32] - 2018-03-08\n\n### Added\n\n-   Added Spanish translation.\n\n### Changed\n\n-   Changed stack quantity of craftable items from 1 to 0 to fix Quantity Sorting.\n-   Changed fluid stack amount to not display \"0\" anymore.\n-   Disk Manipulator in fluid mode will now extract a bucket at a time instead of 1 mB (or 64 buckets at a time with a Stack Upgrade instead of 64 mB).\n\n### Fixed\n\n-   Fixed issue where the Pattern Grid can only overwrite patterns when blank ones are present.\n-   Fixed not being able to extract half a stack of items with max stack size 1 in Grid when using right click.\n-   Fixed 2 same stacks using capabilities without NBT tag not treated equal.\n-   Fixed NBT/metadata check on exporting in an Interface.\n-   Fixed Disk Manipulator being stuck on unemptiable, non-empty disks.\n-   Fixed orientations of the Portable Grid.\n-   Fixed crafting event in Crafting Grid being fired twice.\n-   Fixed a crash when the Constructor tries to place a block when a multipart is attached to it.\n-   Fixed an autocrafting crash.\n-   Attempted to fix FPS drop on Grid sorting.\n\n## [1.5.31] - 2017-12-31\n\n### Changed\n\n-   Storage disk and block stored and capacity counts are formatted now in the tooltip.\n-   Improved the \"cannot craft! loop in processing...\" error message.\n-   Made the Disk Manipulator unsided (inserting goes to insert slots and extracting from output slots).\n\n### Fixed\n\n-   Fixed error logs when toggling the Pattern Grid from and to processing mode.\n-   Fixed pattern slots in Crafters not being accessible.\n-   Fixed rare Grid crash.\n-   Fixed OpenComputers cable showing up in Grid as air.\n\n## [1.5.30] - 2017-12-24\n\n### Fixed\n\n-   Fixed crashing bug when MCMultiPart is not installed.\n\n## [1.5.29] - 2017-12-23\n\n### Changed\n\n-   Update Forge to 2577 (minimum Forge version required is now 2555 for MC 1.12.2).\n\n### Fixed\n\n-   Fixed bug where MCMP multiparts were blocking RS network connections.\n-   Fixed Reader/Writers for energy extracting energy when not needed.\n\n## [1.5.28] - 2017-12-13\n\n### Changed\n\n-   Item Reader/Writers can now store 16 stacks.\n-   Fluid Reader/Writers can now store 16 buckets.\n-   Energy Reader/Writers can now store 16000 FE.\n\n### Fixed\n\n-   Fixed Writers not pushing energy.\n\n## [1.5.27-beta] - 2017-12-09\n\n### Fixed\n\n-   Fixed non-oredict patterns not consuming resources.\n\n## [1.5.26-beta] - 2017-12-09\n\n### Added\n\n-   Added Funky Locomotion integration.\n\n### Fixed\n\n-   Fixed Exporter in Regulator Mode not regulating properly when same item is specified multiple times.\n-   Fixed air appearing in Grid.\n-   Fixed config categories not correctly appearing in ingame config GUI.\n-   Fixed craftable items showing \"1 total\" if not stored in system in Grid.\n-   Minor fixes to autocrafting.\n\n### Removed\n\n-   Removed \"detailed\" Grid view type variant, made detailed tooltips a config option instead.\n\n## [1.5.25] - 2017-11-28\n\n### Fixed\n\n-   Fixed not being able to autocraft different Storage Drawers' wood drawers.\n-   Fixed not being able to autocraft certain Modular Routers items.\n-   Fixed last modified date not being sent when extracting from an External Storage.\n\n## [1.5.24] - 2017-11-26\n\n### Added\n\n-   Added \"Last modified\" sorting option in the Grid.\n-   Added a \"detailed\" variant for every Grid view type option, to disable the modified information on the tooltip.\n\n### Changed\n\n-   The Grid now displays last modified information (player name and date) and size on tooltips of stacks.\n\n### Fixed\n\n-   Fixed Exporter with Stack Upgrade not working correctly in Regulator Mode.\n-   Fixed crash with the Constructor.\n-   Fixed patterns being able to crash when no inputs are provided.\n-   Fixed possible crash with network scanning.\n\n### Removed\n\n-   Removed craft-only mode for the Exporter.\n\n## [1.5.23] - 2017-11-13\n\n### Fixed\n\n-   Fixed duplication bug with autocrafting.\n-   Fixed Fluid Interface with Stack Upgrade not exporting fluids.\n-   Fixed fluids in Fluid Grid not showing actual mB on tooltip when pressing CTRL + SHIFT.\n\n## [1.5.22] - 2017-11-11\n\n### Added\n\n-   Added oredict, blocking, processing, ore inputs access to OpenComputers API.\n-   Added shortcut to clear Grid crafting matrix (CTRL+X).\n\n### Changed\n\n-   The Crafter can now only store 1 stack size pattern per slot.\n-   You can now re-insert a Pattern in the pattern output slot in the Pattern Grid to modify an existing pattern.\n-   The Refined Storage jar is now signed.\n-   Updated Chinese translation.\n\n### Fixed\n\n-   Fixed not being able to use JEI R and U keys on Grid with tabs.\n-   Fixed lag when opening a Grid with lots of items by offloading the grid sorting to another thread.\n-   Performance improvement when adding patterns to the network.\n\n## [1.5.21] - 2017-10-19\n\n### Changed\n\n-   Updated Portuguese (Brazilian) translation.\n\n### Fixed\n\n-   Fixed crash with External Storage.\n-   Fixed stack-crafting in the crafting grid (crafting table) causing lag on a dedicated server.\n-   Fixed cable blocks, Wireless Transmitter, Detector and Portable Grid acting as full blocks (being able to place torches on them etc).\n\n## [1.5.20] - 2017-10-09\n\n### Fixed\n\n-   Restore MC 1.12.0 compatibility.\n\n## [1.5.19] - 2017-10-08\n\n### Changed\n\n-   Updated Forge to 2493 (MC 1.12.2).\n\n### Fixed\n\n-   Fixed Refined Storage blocks requiring a pickaxe to be broken.\n-   Fixed Grid GUI crash.\n-   Fixed device names overflowing Controller GUI.\n-   Fixed high CPU load when Refined Storage GUIs are open.\n-   Fixed not being able to extract Mekanism tanks and bins from the Grid.\n-   Fixed not being able to craft Immersive Engineering Revolver.\n-   Fixed rare bug when server crashes on startup due to network node not existing.\n\n## [1.5.18] - 2017-09-08\n\n### Added\n\n-   Added Project E integration for the External Storage on the Transmutation Table.\n-   Added Project E integration for the energy values of Solderer items.\n-   Added support for more than 4 grid tabs in the Grid by putting filters IN filters.\n-   Added protection for other mods causing crashes when drawing an item or display name.\n\n### Changed\n\n-   Reader and Writer blocks now face the block you're placing it on, not the player.\n-   Pressing SHIFT over an item in the Grid will no longer display the full unformatted count, instead, use CTRL + SHIFT and it will be displayed in the tooltip.\n-   The Fortune Upgrade doesn't use NBT anymore to store the fortune level.\n\n### Fixed\n\n-   Fixed network not disconnecting when Controller is broken.\n-   Fixed bug where when multiple Fortune Upgrades are inserted, it chooses the first Fortune Upgrade instead of the highest one.\n-   Fixed some translations having too big \"Craft\" text.\n-   Fixed crash with GUI when toggling the Grid size quickly.\n-   Fixed scrollbar not scrolling correctly when clicked with mouse when grid tabs are visible.\n-   Fixed Reader and Writers GUIs still displaying channels even if not connected.\n-   Fixed Solderer resetting progress when the inventory changes.\n\n## [1.5.17] - 2017-08-19\n\n### Added\n\n-   Re-added support for OpenComputers.\n\n### Fixed\n\n-   Fixed crash with Grid.\n\n## [1.5.16] - 2017-08-09\n\n### Fixed\n\n-   Fixed crash when placing a Controller.\n-   Fixed crash when configuring an Exporter.\n-   Fixed Refined Storage not running in MC 1.12 and only on MC 1.12.1.\n\n## [1.5.15] - 2017-08-09\n\n### Added\n\n-   Added InventoryTweaks Grid sorting.\n-   Added InventoryTweaks inventory sort ability in Refined Storage GUIs.\n-   Added CTM integration for Disk Manipulator.\n\n### Changed\n\n-   Updated Forge to 2444 (MC 1.12.1).\n\n### Fixed\n\n-   Fixed possible rare dupe bug with Importer.\n-   Fixed Shulker Box dupe bug with Destructor.\n-   Fixed Grid crash with search history.\n-   Fixed Grid crash with search field.\n-   Fixed External Storage not working without Storage Drawers.\n-   Fixed External Storage not calculating max stack size in the calculation of it's capacity display in the GUI.\n-   Fixed Refined Storage not drawing small text correctly with Unicode font.\n-   Fixed dupe bug with External Storage connected to an item handler.\n\n## [1.5.14] - 2017-08-03\n\n### Added\n\n-   Added config option to modify the Solderer speed per Speed Upgrade, defaulting to 22.5% faster per upgrade, making it 90% faster on a fully upgraded Solderer.\n-   Added CTM integration.\n\n### Changed\n\n-   Updated Forge to 2426.\n-   Updated French translation.\n\n### Fixed\n\n-   Fixed more crashes relating to scrollbar in GUIs.\n-   Fixed crash with Detector.\n-   Fixed bug where pattern create button wasn't visible when grid tabs were selected.\n-   Fixed performance issue with Controllers turning off and on and Interfaces.\n-   Fixed Interfaces exposing network inventory don't hide storages that are disconnected.\n\n## [1.5.13] - 2017-07-20\n\n### Fixed\n\n-   Fixed Wireless Fluid Grid not using up energy.\n-   Fixed Wireless Crafting Monitor remaining in network item list.\n\n## [1.5.12] - 2017-07-17\n\n### Added\n\n-   Added additional API for grids.\n\n### Changed\n\n-   The Network Transmitter now uses 1 FE/t per block instead of 4 FE/t.\n\n## [1.5.11] - 2017-07-16\n\n### Fixed\n\n-   Fixed not being able to smelt quartz into silicon.\n-   Fixed Grid extracting wrong enchanted books.\n\n## [1.5.10] - 2017-07-15\n\n### Fixed\n\n-   Fixed crash relating to MCMP.\n\n### Changed\n\n-   Converted Solderer recipes to JSON.\n-   Implemented controller update throttling, should fix lag issues with controllers that constantly turn off and on.\n\n## [1.5.9] - 2017-07-10\n\n### Fixed\n\n-   Fixed not being able to extract anything when connecting an External Storage to Storage Drawers.\n\n## [1.5.8] - 2017-07-08\n\n### Changed\n\n-   Updated Forge to 2400.\n-   Updated Storage Drawers API.\n-   Autocrafting can now fill water bottles with water from the fluid storage - regular bottles or pattern for regular bottles are required.\n\n### Fixed\n\n-   Fixed bug where disks have to be re-inserted in the Disk Drive in order to work again after rejoining a chunk.\n-   Fixed bug where items inserted in Storage Drawers through External Storage with a Drawer Controller wouldn't respect drawer priority rules.\n-   Fixed crash on server when getting an advancement.\n\n### Removed\n\n-   Removed migration support for worlds from MC 1.10.2. To migrate your world to MC 1.12 from MC 1.10.2, first open it in MC 1.11.2.\n\n## [1.5.7] - 2017-07-04\n\n### Added\n\n-   Added advancements.\n\n### Changed\n\n-   Exposed pattern inventory for Pattern Grid.\n\n### Fixed\n\n-   Fixed crashes relating to scrollbar in GUIs.\n\n## [1.5.6] - 2017-06-29\n\n### Changed\n\n-   Updated Forge to stable 2387.\n\n### Fixed\n\n-   Fixed bug where players couldn't place regular blocks next to secured networks.\n\n### Removed\n\n-   Removed Processing Pattern Encoder, that functionality is now available in the Pattern Grid.\n\n## [1.5.5-beta] - 2017-06-25\n\n### Changed\n\n-   Updated Forge to 2363.\n\n## [1.5.4-beta] - 2017-06-24\n\n### Fixed\n\n-   Fixed External Storage crashing.\n-   Fixed crash when node data mismatches between world and dat file.\n\n## [1.5.3-beta] - 2017-06-24\n\n### Added\n\n-   The Portable Grid now exposes an inventory for interaction with other mods or vanilla.\n-   The Interface now exposes the entire storage inventory (if no slots are set for exporting) for interaction with other mods or vanilla.\n\n### Changed\n\n-   Updated Forge to 2359.\n-   Updated MCMultiPart to 2.2.1.\n\n### Fixed\n\n-   Fixed Solderer crashing.\n-   Fixed Solderer being able to work with insufficient ingredients.\n-   Fixed Interface extracting from itself when trying to keep items in stock.\n-   Fixed Quartz Enriched Iron recipe only giving 1 instead of 4.\n-   Fixed Debug Storage disks not working correctly.\n-   Fixed Disk Drive giving incorrect capacity for creative and debug storage disks.\n\n### Removed\n\n-   The Relay now reacts instantly to a redstone signal again, removed throttling for it.\n\n## [1.5.2-beta] - 2017-06-20\n\n### Fixed\n\n-   Fixed a bug where loading nodes would abort when a single node has an error while reading.\n-   Fixed Filters not persisting correctly in Portable Grid.\n\n## [1.5.1-beta] - 2017-06-20\n\n### Added\n\n-   Re-added MCMultiPart support.\n-   Added back crafting recipes.\n\n### Changed\n\n-   Updated Forge to 2340.\n-   Changed Grid recipe.\n-   Changed Crafting Monitor recipe.\n\n### Fixed\n\n-   Fixed Filters not persisting correctly in Wireless Grid and Wireless Crafting Monitor.\n-   Fixed Disk Drive recipe not using ore dictionary for chest.\n-   Fixed crash when getting tooltip for grid item.\n\n### Removed\n\n-   Removed Tesla integration.\n-   Removed RS energy units, the entire mod is powered with Forge Energy now.\n\n## [1.5.0-alpha] - 2017-06-14\n\n### Added\n\n-   Port to Minecraft 1.12.\n-   The Portable Grid now doesn't despawn anymore when dropped in the world.\n\n### Fixed\n\n-   Fixed bug where oredict autocrafting didn't work in some cases.\n\n### Removed\n\n-   Removed MCMultiPart support (will be re-added as soon as MCMultiPart for MC 1.12 is available).\n-   Removed OpenComputers support (will be re-added as soon as OpenComputers for MC 1.12 is available).\n-   Removed crafting recipes, until Forge adds the recipe system back.\n\n## [1.4.20] - 2017-07-15\n\n### Fixed\n\n-   Fixed crash relating to MCMP.\n\n## [1.4.19] - 2017-07-15\n\n### Added\n\n-   Implemented controller update throttling, should fix lag issues with controllers that constantly turn off and on.\n\n### Fixed\n\n-   Fixed bug where players couldn't place regular blocks next to secured networks.\n-   Fixed crashes relating to scrollbar in GUIs.\n-   Fixed bug where disks have to be re-inserted in the Disk Drive in order to work again after rejoining a chunk.\n\n## [1.4.18] - 2017-06-24\n\n### Fixed\n\n-   Fixed Solderer crashing.\n-   Fixed Interface extracting from itself when trying to keep items in stock.\n-   Fixed Solderer being able to work with insufficient ingredients.\n-   Fixed Disk Drive giving incorrect capacity for creative and debug storage disks.\n-   Fixed External Storage crashing.\n-   Fixed crash when node data mismatches between world and dat file.\n\n### Removed\n\n-   The Relay now reacts instantly to a redstone signal again, removed throttling for it.\n\n## [1.4.17] - 2017-06-20\n\n### Fixed\n\n-   Fixed Filters not persisting correctly in Wireless Grid, Wireless Crafting Monitor and Portable Grid.\n-   Fixed Disk Drive recipe not using ore dictionary for chest.\n-   Fixed a bug where loading nodes would abort when a single node has an error while reading.\n\n## [1.4.16] - 2017-06-14\n\n### Added\n\n-   The Portable Grid now doesn't despawn anymore when dropped in the world.\n\n### Fixed\n\n-   Fixed bug where oredict autocrafting didn't work in some cases.\n\n## [1.4.15] - 2017-06-14\n\n### Changed\n\n-   Updated Storage Drawers API, fixes crashes.\n\n## [1.4.14] - 2017-06-13\n\n### Fixed\n\n-   Fixed Solderer not accepting books made in anvil.\n\n## [1.4.13] - 2017-06-13\n\n### Added\n\n-   The Portable Grid now has an indicator whether it's connected or disconnected and shows the disk.\n\n### Fixed\n\n-   Fixed Portable Grid model.\n-   Fixed ore dictionary causing problems with Solderer.\n-   Fixed ore dictionary items not showing up in JEI for the Solderer.\n\n### Removed\n\n-   Removed Quartz Enriched Iron ore dictionary entry.\n\n## [1.4.12] - 2017-06-10\n\n### Added\n\n-   Added Korean translation.\n-   Implemented block update throttling when network turns on and off.\n\n### Changed\n\n-   Updated Forge to 2315.\n-   Updated JEI to 4.5.0.\n-   You can now shift click items from the Grid crafting slots to the player inventory when the Grid is disconnected.\n\n### Fixed\n\n-   Fixed error logs when watching a Controller when a network changes.\n\n### Removed\n\n-   Removed Collosal Chests integration.\n\n## [1.4.11] - 2017-06-05\n\n### Added\n\n-   Added support for External Storage on Interfaces and other Refined Storage blocks, so you can keep items in stock easier.\n-   You now have to sneak to place the Portable Grid in the world.\n\n### Changed\n\n-   The Machine Casing now requires 1 piece of stone in the middle.\n-   Changed recipe of Disk Drive to no longer require a Solderer.\n-   Changed recipe of Interface to no longer require a Basic Processor, but a Machine Casing instead.\n\n### Fixed\n\n-   Fixed bug where storages that are removed remain visible.\n-   Fixed bug where the GUI didn't close when a block is broken, causing a dupe bug with the Portable Grid.\n\n### Removed\n\n-   Removed debug log configuration option, as it's no longer needed.\n-   Removed \"autocraft on redstone signal\" option in the Crafter, use an External Storage in combination with an Interface with the Crafting Upgrade instead.\n\n## [1.4.10-beta] - 2017-05-25\n\n### Changed\n\n-   Improved performance of network scanning.\n\n### Fixed\n\n-   Fixed crash when attempting to get direction of a node.\n-   Fixed bug where some network parts don't want to connect to the storage system.\n\n## [1.4.9-beta] - 2017-05-24\n\n### Fixed\n\n-   Fixed bug where inventory data was lost sometimes upon opening the world.\n\n## [1.4.8-beta] - 2017-05-24\n\n### Fixed\n\n-   Fixed missing config categories in ingame config.\n-   Fixed Controller not working anymore after changing redstone setting.\n-   Fixed crash when placing or destroying network blocks.\n\n## [1.4.7-beta] - 2017-05-23\n\n### Added\n\n-   Added config option \"debugLog\" that logs diagnostic info to help developers to fix the inventory loss bug, please enable it if you are experiencing this issue.\n\n### Fixed\n\n-   Fixed bug where Portable Grid would dupe in inventory.\n-   Worked around an autocrafting bug to prevent crashes.\n\n## [1.4.6-beta] - 2017-05-17\n\n### Changed\n\n-   Performance improvement to network scanning.\n\n### Fixed\n\n-   Fixed Wrench opening GUIs while performing action.\n-   Fixed client Grid GUI clearing and causing crashes after starting an autocrafting request.\n\n### Removed\n\n-   Removed debug output from v1.4.5.\n\n## [1.4.5-beta] - 2017-05-14\n\n### Added\n\n-   Added Portable Grid.\n-   Added OpenComputers integration.\n\n### Changed\n\n-   Updated Forge to 2296.\n-   Removed ticking tile entities, every tile entity in RS is non-ticking now.\n\n### Fixed\n\n-   Fixed Crafting Tweaks buttons positioned wrongly.\n-   Fixed Crafting Tweaks keybindings interfering with RS keybindings.\n-   Fixed crash when updating storages.\n-   Fixed no tooltips for fluid filter slots.\n-   Fixed Disk Manipulator in fluid mode not showing fluids.\n-   Fixed dupe bug in the Interface.\n\n## [1.4.4-beta] - 2017-04-27\n\n### Changed\n\n-   Updated Forge to 2284.\n\n### Fixed\n\n-   Fixed Disk Manipulator crashing due to empty stack.\n-   Fixed issue where empty stacks show up in the system.\n-   Fixed Storage Monitor not respecting security settings.\n\n## [1.4.3-beta] - 2017-04-22\n\n### Added\n\n-   Display progress bar on JEI recipes for the Solderer.\n\n### Changed\n\n-   Updated Forge to 2282.\n-   Updated JEI version.\n-   Updated MCMultiPart version.\n-   You can now shift click Grid Filters into a Grid instead of manually inserting them.\n-   You can now use up and down arrows to scroll through Grid search history.\n-   Shift clicking patterns in the Pattern Grid now puts the patterns in the pattern slot.\n-   Storage Monitors don't render any quantity text when no item is specified to monitor anymore.\n-   The Solderer inventory isn't sided anymore.\n-   Small performance improvement: only sort the storages when needed.\n\n### Fixed\n\n-   Fixed bug where disks in Disk Drive didn't respect access type or void excess stacks option.\n-   Fixed crash in Disk Manipulator.\n-   Fixed oredict not working.\n-   Fixed Grid crash.\n-   Fixed Fluid Grid not formatting large quantities correctly.\n\n## [1.4.2-beta] - 2017-04-01\n\n### Added\n\n-   Implemented support for the Forge update JSON system.\n-   Added integration for MCMultiPart, this is an optional dependency.\n-   You can now specify more items to export, import, filter, etc. by inserting the Filter item.\n-   Made the keybinding to focus on the Grid search bar configurable.\n\n### Changed\n\n-   Updated Forge to 2261.\n-   The Detector no longer outputs a strong redstone signal.\n-   Fire event on completion of an autocrafting task.\n-   Fire \"player crafting\" event when shift clicking in the grid.\n\n### Fixed\n\n-   Fixed a crash with the Constructor.\n-   Fixed Crafting Pattern model.\n-   Fixed Quartz Enriched Iron and the block form of it not having an oredictionary entry.\n-   Fixed crash in storage cache.\n-   Fixed slow oredict comparisons causing TPS lag.\n-   Fixed controller model warning during launch.\n-   Fixed not rendering some tooltips correctly.\n-   Fixed crash with External Storage.\n-   Fixed Interface duping items on extract-only storages.\n-   Fixed controls menu showing unlocalized text for Refined Storage keybindings.\n-   Autocrafting bugfixes.\n-   Improved memory usage of some models.\n-   Performance improvements related to storage inserting and extracting.\n\n### Removed\n\n-   Removed support for the Deep Storage Unit API.\n\n## [1.4.1-beta] - 2017-02-19\n\n### Added\n\n-   Added Storage Monitor.\n\n### Changed\n\n-   Updated Forge to 2232.\n\n### Fixed\n\n-   Fixed Processing Pattern Encoder and Security Manager recipes not supporting oredict workbench and chest.\n-   Fixed network nodes not respecting redstone mode.\n-   Fixed \"Clear\" and \"Create Pattern\" buttons not working correctly when using Grid Filter tabs.\n-   Fixed Wrench in Dismantling Mode voiding Storage Block contents.\n-   Fixed OPs not having global permissions on secured storage systems.\n-   Fixed crash when Destructor tries to break secured network block.\n-   Fixed Fluid Interface not dropping inventory contents.\n-   Fixed Disk Manipulator crash.\n\n## [1.4.0-beta] - 2017-02-06\n\n### Added\n\n-   Added Security Manager.\n-   Added Security Card.\n-   Added Wireless Fluid Grid.\n-   Added craft-only toggle to Exporter.\n-   Added Reader.\n-   Added Writer.\n-   Added blocking mode to patterns in autocrafting.\n-   Added Grid size toggle (stretched, small, medium, large).\n-   Added dismantling mode to the Wrench.\n-   Added Block of Quartz Enriched Iron.\n-   Added integration for Collosal Chests for the External Storage, Importer and Exporter improving performance.\n-   Added filtering slots for the Crafting Monitor.\n-   Added way to hide tasks created in an automated way in the Crafting Monitor.\n-   Added Grid sorting by ID.\n-   Added Solderer particles.\n-   Added ore dictionary Grid filter (use `$` as prefix like in JEI).\n\n### Changed\n\n-   You can now bind multiple crafters with the same pattern to machines, to spread or balance out autocrafting.\n-   Fluid Grid now first tries to get buckets from your inventory instead of the storage.\n-   Updated Forge to 2226.\n-   Updated Chinese translation.\n-   Converting blocks instead of ingots to Printed Processors is now a little faster.\n-   The Stack Upgrade in a Constructor in item dropping mode will drop stacks of items at a time.\n-   Ignore damage for damageable items when transferring into crafting grid.\n-   Ignore tags from given items when transferring into crafting grid.\n-   Removed sidedness from fluid interface.\n-   Using tab in a grid that isn't in autoselected mode will focus on the search box.\n-   Exposed the Network Card inventory of the Network Transmitter so other tiles can interact with it.\n-   Increased size of Detector textbox.\n-   Handle breaking and placing blocks better for Constructor and Destructor.\n-   Pressing shift while starting a crafting task will skip the crafting preview.\n\n### Fixed\n\n-   Fixed Regulator mode not working.\n-   Fixed Fluid Interface still being sided.\n-   Fixed Constructor not working on Botania flowers.\n-   Fixed Wireless Transmitter working even if it was disabled with redstone mode.\n-   Fixed Solderer not accepting books created in an Anvil.\n-   Fixed bug where network machines stopped working on chunk borders.\n-   Fixed memes not working.\n-   Fixed External Storage crashes.\n-   Fixed Constructor in liquid mode being able to place fluids &lt;1000 mB.\n-   Fixed Solderer recipe conflicts, allowing for easier automation.\n-   Fixed stack upgrades not working in exporter when stack size is 16.\n-   Fixed crash when rotating External Storage.\n-   Fixed disk textures not working on latest Forge.\n-   Fixed crash when placing head with Constructor.\n-   Autocrafting bugfixes.\n-   Made sure External Storage always has the correct inventory in world.\n\n## [1.3.5-alpha] - 2016-12-14\n\n### Added\n\n-   Added regulator mode to Exporter.\n\n### Changed\n\n-   Updated French translation.\n\n### Fixed\n\n-   Fixed TPS lag on very large crafting tasks.\n-   Fixed not being able to use autocrafting on some EnderIO items.\n-   Fixed server crash with ore dictionary checks.\n-   Fixed Controller not using energy.\n-   Fixed dupe bug when inserting bucket in Fluid Grid.\n-   Fixed not being able to start autocrafting for storage disks.\n-   Fixed oredict button not having the correct position on a small resolution.\n-   Fixed Constructor not using Crafting Upgrade when in item dropping mode.\n\n## [1.3.4-alpha] - 2016-12-10\n\n### Added\n\n-   Added option to check for oredict in the Grid Filter.\n-   Added option to use a mod filter in the Grid Filter.\n-   Added option to use a whitelist or blacklist in the Grid Filter.\n-   Added Grid tabs using Grid Filters.\n-   Added configuration option to enable large fonts in Grid.\n\n### Changed\n\n-   The Grid now resizes based on screen size (max rows can be configured).\n-   Made Solderer tooltip less big.\n-   Made the Interface sideless, you can just insert or extract from any side.\n\n### Fixed\n\n-   Fixed bug with opening a network item with food in offhand.\n-   Fixed not respecting \"Extract only\" option for storages.\n-   Fixed a few autocrafting bugs.\n-   Fixed a crash with the Disk Manipulator.\n\n## [1.3.3-alpha] - 2016-12-06\n\n### Changed\n\n-   Updated Forge to 2188.\n\n### Fixed\n\n-   Fixed not being able to start a crafting task.\n\n## [1.3.2-alpha] - 2016-12-04\n\n### Fixed\n\n-   Fixed being able to exceed max stack size while shift clicking.\n-   Fixed Wrench clearing NBT data when reset causing problems with Morph O Tool.\n-   Fixed client crash when placing network blocks.\n\n## [1.3.1-alpha] - 2016-12-04\n\n### Changed\n\n-   Updated Forge to 2180.\n-   Made Upgrades stackable.\n\n### Fixed\n\n-   Fixed Disk Drive not noticing a Storage Disk being shift clicked out of the GUI.\n\n## [1.3.0-alpha] - 2016-12-03\n\n### Added\n\n-   Port to Minecraft 1.11.\n\n### Removed\n\n-   Removed RF support, use Forge Energy instead.\n-   Removed IC2 support.\n-   Removed MCMultiPart support (will be re-added as soon as MCMultiPart for MC 1.11 is available).\n\n## [1.2.26] - 2017-06-10\n\n### Fixed\n\n-   Fixed Interface duping items on extract-only storages.\n-   Fixed calculating crafting resources for more than 9 unique items, for addon mods.\n\n## [1.2.25] - 2017-03-25\n\n### Changed\n\n-   Fire event on completion of an autocrafting task.\n-   Fire player crafting event when shift clicking in the grid.\n-   Allow INodeNetwork instances to return an ItemStack for display in Controller GUI.\n\n## [1.2.24] - 2017-03-18\n\n### Changed\n\n-   Made the keybinding to focus on the Grid search bar configurable.\n\n### Fixed\n\n-   Autocrafting bugfixes.\n\n## [1.2.23] - 2017-03-11\n\n### Added\n\n-   Implemented support for the Forge update JSON system.\n\n### Changed\n\n-   The Detector no longer outputs a strong redstone signal.\n\n### Fixed\n\n-   Fixed crash in storage cache.\n-   Fixed Crafting Pattern model.\n-   Fixed Constructor not working on Botania flowers.\n-   Fixed Disk Manipulator crash.\n-   Fixed slow oredict comparisons causing TPS lag.\n\n## [1.2.22] - 2017-02-19\n\n### Fixed\n\n-   Fixed recipe for Processing Pattern Encoder not using oredictionary for the workbench.\n-   Fixed Fluid Interface not dropping inventory contents.\n-   Fixed glitchy upgrade recipes in the Solderer.\n\n## [1.2.21] - 2017-02-07\n\n### Fixed\n\n-   Fixed crash when placing head with Constructor.\n\n## [1.2.20] - 2017-02-02\n\n### Added\n\n-   Added Solderer particles.\n-   Added Grid sorting by ID.\n\n### Fixed\n\n-   Fixed client side crash with cables.\n\n## [1.2.19] - 2017-02-01\n\n### Added\n\n-   Added integration for Collosal Chests for the External Storage, Importer and Exporter improving performance.\n\n### Changed\n\n-   Updated cable part back texture and Construction and Destruction Core textures.\n-   Updated Forge to 2221.\n-   Updated Chinese translation.\n-   Exposed the Network Card inventory of the Network Transmitter so other tiles can interact with it.\n-   Increased size of Detector textbox.\n-   Autocrafting bugfixes.\n-   Handle breaking and placing blocks better for Constructor and Destructor.\n\n### Fixed\n\n-   Fixed stack upgrades not working in exporter when stack size is 16.\n-   Fixed crash when rotating External Storage.\n-   Fixed disk textures not working on latest Forge.\n\n## [1.2.18] - 2017-01-22\n\n### Changed\n\n-   Fluid Grid now first tries to get buckets from your inventory instead of the storage.\n-   Performance improvements with oredict autocrafting.\n\n### Fixed\n\n-   Fixed client side crash with cable.\n-   Fixed client side crash with disk drive.\n-   Fixed crash with external storage in fluid mode.\n\n## [1.2.17] - 2017-01-12\n\n### Added\n\n-   Add Ore Dictionary grid filter (use $ as prefix like in JEI).\n\n### Changed\n\n-   Ignore damage for damageable items when transferring into crafting grid.\n-   Ignore tags from given items when transferring into crafting grid.\n-   Removed sidedness from fluid interface.\n-   Using tab in a grid that isn't in autoselected mode will focus on the search box.\n-   The Stack Upgrade in a Constructor in item dropping mode will drop stacks of items at a time.\n\n### Fixed\n\n-   Fixed Constructor in liquid mode being able to place fluids &lt;1000 mB.\n-   Fixed Solderer recipe conflicts, allowing for easier automation.\n-   Fixed machines not connecting with cable after Controller.\n\n## [1.2.16] - 2017-01-04\n\n### Fixed\n\n-   Fixed an autocrafting regression.\n-   Fixed crash with External Storage.\n\n## [1.2.15] - 2017-01-03\n\n### Fixed\n\n-   Fixed Grid Filter hiding everything when 2 or more items are in it.\n-   Fixed External Storage crash when breaking a connected inventory.\n-   Autocrafting bugfixes.\n\n## [1.2.14] - 2016-12-24\n\n### Fixed\n\n-   Fixed server crash.\n\n## [1.2.13] - 2016-12-23\n\n### Fixed\n\n-   Fixed memes not working.\n-   Fixed controller causing network rebuild on every neighbor change.\n-   Fixed Wireless Transmitter working even if it was disabled with redstone mode.\n-   Fixed Solderer not accepting books created in an Anvil.\n-   Autocrafting bugfixes.\n-   Made sure External Storage always has the correct inventory in world.\n\n## [1.2.12] - 2016-12-16\n\n### Changed\n\n-   Updated French translation.\n\n### Fixed\n\n-   Fixed TPS lag on very large crafting tasks.\n-   Fixed not being able to use autocrafting on some EnderIO items.\n-   Fixed not being able to start autocrafting for storage disks.\n-   Fixed oredict button not having the correct position on a small resolution.\n-   Fixed Constructor not using Crafting Upgrade when in item dropping mode.\n\n## [1.2.11] - 2016-12-10\n\n### Added\n\n-   Added configuration option to enable large fonts in Grid.\n\n### Changed\n\n-   The Grid now resizes based on screen size (max rows can be configured).\n-   Made the Interface sideless, you can just insert or extract from any side.\n\n## [1.2.10] - 2016-12-09\n\n### Changed\n\n-   Made Solderer tooltip less big.\n\n### Fixed\n\n-   Fixed a crash with the Disk Manipulator.\n-   Fixed not respecting \"Extract only\" option for storages.\n-   Fixed bug with opening a network item with food in offhand.\n-   Fixed other fluid storages going negative when using void excess fluids option.\n-   A few autocrafting bugfixes.\n\n## [1.2.9] - 2016-12-06\n\n### Changed\n\n-   Updated Forge to 2185.\n\n### Fixed\n\n-   Fixed Wrench clearing NBT data when reset causing problems with Morph O Tool.\n\n## [1.2.8] - 2016-11-30\n\n### Fixed\n\n-   Fixed autocrafting bugs.\n\n## [1.2.7] - 2016-11-29\n\n### Changed\n\n-   Updated German translation.\n\n### Fixed\n\n-   Fixed not being able to place disks in Disk Drives on servers.\n\n## [1.2.6] - 2016-11-26\n\n### Changed\n\n-   Processing patterns can now insert buckets.\n\n### Fixed\n\n-   Fixed crash with Exporters in fluid mode.\n\n### Removed\n\n-   Removed Solderer progress percentage text.\n\n## [1.2.5] - 2016-11-24\n\n### Added\n\n-   Added \"View Recipes\" JEI toggle in Solderer.\n\n### Changed\n\n-   The Constructor can now place fireworks.\n-   Updated Forge to 2151.\n\n### Fixed\n\n-   Fixed a bunch of autocrafting bugs.\n-   Fixed Grid search not working correctly.\n-   Fixed items disappearing from Solderer inventory.\n-   Fixed being able to take fluids that have less than 1000 millibuckets filled in Fluid Grid.\n-   Fixed Constructor being able to place fluids that have less than 1000 millibuckets.\n-   Fixed Exporter and Importer not working properly with fluids.\n-   Fixed inserting new stack type with right click in Grid causing a desync.\n-   Fixed Constructor not calling block place event.\n-   Fixed shift clicking non disk items in the Disk Manipulator voiding them.\n\n## [1.2.4] - 2016-11-10\n\n### Added\n\n-   Added tooltip search with #.\n\n### Changed\n\n-   Mod search can now also take mod name instead of just id.\n\n### Fixed\n\n-   Fixed bug where Disk Manipulator doesn't save disks.\n-   Fixed Disk Drive stored quantity GUI text hovering over other text.\n-   Fixed External Storage being in item and fluid mode at the same time.\n-   Fixed Wrench working when player is not sneaking.\n-   Fixed External Storage cache counting items up when extracting.\n-   Fixed External Storage cache not working properly on Compacting Drawers.\n\n### Removed\n\n-   Removed ability to put External Storages on Refined Storage network blocks.\n\n## [1.2.3] - 2016-11-06\n\n### Fixed\n\n-   Fixed fluid cache updating wrongly.\n-   Fixed Exporter scheduling too many crafting tasks.\n\n## [1.2.2] - 2016-11-05\n\n### Fixed\n\n-   Fixed item voiding when exporting to a chest with a storage in Extract Only mode.\n-   Various autocrafting fixes.\n\n## [1.2.1] - 2016-11-05\n\n### Added\n\n-   Added Wireless Crafting Monitor (with temporary textures).\n-   Added support for JEI R and U keys in Grids.\n\n### Changed\n\n-   You can now decompose storage disks if the item count is below zero by any chance.\n\n### Fixed\n\n-   Fixed crafting upgrade having weird behavior.\n-   Fixed external storage not updating when loading chunk.\n-   Fixed external storage crash.\n-   Fixed weird autocrafting behavior.\n\n### Removed\n\n-   Removed controller explosions when multiple controllers are connected to the same network.\n\n## [1.2.0] - 2016-11-03\n\n### Added\n\n-   Added new autocrafting system.\n-   Added ore dictionary autocrafting.\n-   Added recipe transfer handler for Processing Pattern Encoder.\n-   Added void excess items functionality to storage blocks.\n-   Added config option to configure RS to EU conversion rates.\n-   Added ability to toggle between insert and extract, only insert and only extract mode in storage blocks.\n-   Added Silk Touch Upgrade for Destructor.\n-   Added Fortune Upgrade for Destructor.\n-   Added ore dictionary compare toggle to storage I/O blocks.\n-   Added disk leds to Disk Drive block that shows the disks.\n-   Added disk leds to Disk Manipulator block that shows the disks.\n-   Added Wrench, has two modes: configuration saving / reading mode, and rotation mode.\n-   Stack upgrade in Importer / Exporter in fluid mode and Fluid Interface now transfers 64 buckets at once.\n\n### Changed\n\n-   Changed storage GUIs.\n-   Changed default EU conversion rate to be 1:8 with RS.\n-   The Constructor can now drop items in the world.\n-   The Constructor can now place skulls.\n-   The Destructor can now pick up items in the world.\n-   Storage disks and storage blocks now don't despawn anymore when dropped in the world.\n-   Grid item and fluid quantity now only rounds to 1 digit after comma.\n-   Items count can no longer overflow, and will max out at the maximum integer value.\n-   Updated Storage Drawers API.\n-   Controller sorts by energy usage in GUI (highest to lowest).\n-   Detector without any filter will detect based on total items or fluids stored.\n-   Limited network transmitter usage to 1000 RS/t.\n\n### Fixed\n\n-   Fixed lag issues caused by External Storage.\n-   Fixed resetting a stack of patterns yields 1 blank pattern.\n-   Fixed being able to pipe items in the export slots of the Interface.\n-   Fixed Interface being stuck when item isn't accepted in storage.\n-   Fixed items with colored name being uncolored in Grid.\n-   Fixed fluid rendering bugging out side buttons.\n-   Fixed item count going negative when using the Disk Manipulator.\n-   Fixed Storage Drawer quantities not updating properly on Void Drawers.\n-   Fixed Disk Manipulator blocking items transferring in some cases.\n-   Fixed External Storage crafting recipe not supporting ore dictionary chests.\n-   Fixed when shift clicking crafting recipe and inventory is full items are dropping on the ground instead of going in the system.\n-   Fixed glitchy rendering of cable parts in item form.\n-   Fixed Destructor being able to break bedrock.\n-   Fixed External Storage thinking that items are inserted in Extra Utilities Trash Cans.\n-   Fixed Grid quantities being unreadable when using unicode font.\n-   Fixed disconnecting when Storage Disk or Storage Block is too big.\n\n## [1.2.0-beta.8] - 2016-11-03\n\n### Fixed\n\n-   More autocrafting issues.\n\n## [1.2.0-beta.7] - 2016-11-03\n\n### Fixed\n\n-   More autocrafting issues.\n-   External Storage crashes and TPS lag issues.\n-   Mekanism recipes are autocraftable again.\n\n## [1.2.0-beta.6] - 2016-11-02\n\n### Fixed\n\n-   More autocrafting issues.\n-   Oredict autocrafting has been improved.\n\n## [1.2.0-beta.5] - 2016-10-30\n\n### Fixed\n\n-   More autocrafting issues.\n-   External Storage TPS lag issues.\n\n## [1.2.0-beta.4] - 2016-10-27\n\n### Fixed\n\n-   More autocrafting and TPS issues.\n\n## [1.2.0-beta.3] - 2016-10-25\n\n### Fixed\n\n-   More autocrafting issues.\n\n## [1.2.0-beta.2] - 2016-10-24\n\n### Fixed\n\n-   Extreme TPS issues while crafting.\n-   Laggy disk drive rendering.\n\n## [1.2.0-beta.1] - 2016-10-23\n\n### Changed\n\n-   First beta release for v1.2.0, featuring a new autocrafting system.\n\n## [1.1.3] - 2016-10-07\n\n### Fixed\n\n-   Fixed some clients not starting up due to too many Disk Drive model permutations.\n\n## [1.1.2] - 2016-10-03\n\n### Added\n\n-   Added recipe transfer handler for Solderer.\n\n### Changed\n\n-   It is now possible to start a crafting task even if the crafting preview says you can't.\n\n### Fixed\n\n-   Fixed crash with JEI when changing screens in autocrafting.\n-   Fixed not being able to start autocrafting in other dimensions with Network Transmitter / Network Receivers.\n-   Fixed JEI overlay disappearing now and again.\n-   Fixed Detector hitbox.\n\n## [1.1.1] - 2016-09-28\n\n### Fixed\n\n-   Fixed crash on servers.\n\n## [1.1.0] - 2016-09-28\n\n### Added\n\n-   New art by CyanideX.\n-   Added crafting preview screen.\n-   Added max crafting task depth.\n-   Added helpful tooltips to Solderer and Processing Pattern Encoder.\n\n### Changed\n\n-   Every machine now compares on damage and NBT by default.\n-   Updated JEI, fixes crashes.\n-   Detector amount text field doesn't autoselect anymore.\n\n### Fixed\n\n-   Fixed crash with Disk Manipulator.\n-   Fixed autocrafting not giving back byproducts.\n\n## [1.0.5] - 2016-09-21\n\n### Added\n\n-   Importer now takes a Destruction Core, and Exporter a Construction Core.\n-   Added Disk Manipulator.\n-   Added ingame config.\n-   Added the ability to see the output of a Pattern by holding shift.\n-   Exporter in fluid mode and Fluid Interface no longer duplicates fluids that are less than 1 bucket.\n\n### Changed\n\n-   Changed default Grid sorting type to quantity.\n-   Updated Dutch translation.\n-   Updated Chinese translation.\n-   When a machine is in use by a crafting pattern, inserting of items from other patterns will be avoided.\n\n### Fixed\n\n-   Fixed crafting a complex item causes the process to flow off the Crafting Monitor's GUI.\n-   Fixed shift clicking from Grid when player inventory is full throwing items in the world.\n\n## [1.0.4] - 2016-09-17\n\n### Fixed\n\n-   Fixed lag caused by Crafter.\n\n## [1.0.3] - 2016-09-17\n\n### Added\n\n-   Added integration for Forge energy.\n\n### Changed\n\n-   Solderer now accepts items from any side, allowing easier automation.\n-   Solderer is now intelligent about items in slots, and will only accept an item if it is part of a recipe.\n-   Changed recipe for upgrades in the Solderer, they now just take 1 of the unique item instead of 2, using redstone instead.\n-   Updated to Forge 2088.\n\n### Fixed\n\n-   Fixed item loading issue.\n-   Fixed fluid autocrafting scheduling too much crafting tasks for buckets.\n-   Fixed blocks in hand facing wrong direction.\n\n## [1.0.2] - 2016-09-14\n\n### Changed\n\n-   \\+64 in crafting start GUI now gives 64 from the first time instead of 65.\n\n### Fixed\n\n-   Fixed processing patterns not handling item insertion sometimes.\n\n### Removed\n\n-   Removed crafting task limit in crafting start GUI.\n\n## [1.0.1] - 2016-09-13\n\n### Added\n\n-   Added \"autocrafting mode\" in Detector, to check if an item is being crafted. If no item is specified, it'll emit a signal if anything is crafting.\n-   Added an option for the Crafter to trigger autocrafting with a redstone signal.\n\n### Changed\n\n-   Updated to Forge 2084.\n\n### Fixed\n\n-   Fixed advanced tooltips showing in Grid when not configured to do so.\n-   Optimized crafting pattern loading.\n\n## [1.0.0] - 2016-09-12\n\n### Added\n\n-   Interface now supports Crafting Upgrade.\n-   Implemented multithreaded autocrafting.\n\n### Changed\n\n-   Processing patterns now hold their items back for pushing until all the required items are gathered from the system.\n-   Reworked Crafting Monitor GUI.\n-   When shift clicking a recipe in the Crafting Grid, the player inventory is now leveraged as well.\n-   Updated to Forge 2077.\n-   Due to the new crafting system, all Crafting Patterns made before 1.0 have to be re-made.\n\n### Fixed\n\n-   Fixed item and fluid storage stored count having incorrect values at times.\n-   Fixed problems relating to Crafting Upgrade (scheduling a task wrongly, blocking other tasks, etc).\n-   Fixed machines breaking on long distances.\n-   Fixed Controller rebuilding network graph on energy change.\n-   Fixed fluids not caring about NBT tags.\n-   Fixed fluids that have less than 1 bucket stored render only partly in Fluid Grid.\n-   Fixed Fluid Interface voiding bucket when shift clicking to out slot.\n-   Fixed wrong machine connection logic.\n\n## [0.9.4-beta] - 2016-08-27\n\n### Changed\n\n-   Reduced explosion radius when multiple controllers are connected to the same network.\n\n### Fixed\n\n-   Fixed mod not working without JEI.\n-   Little fixes in German translation.\n-   Reverted network changes that caused buggy behavior.\n\n## [0.9.3-beta] - 2016-08-26\n\n### Added\n\n-   Added Chinese translation.\n-   Added Crafting Tweaks integration.\n\n### Changed\n\n-   Updated German translation for Fluid Storage.\n-   Updated Dutch translation for Fluid Storage.\n-   Reworked storage network code, should fix weird machine disconnection issues.\n\n### Fixed\n\n-   Fixed that the Fluid Storage Disk recipe returns an invalid disk.\n\n## [0.9.2-beta] - 2016-08-25\n\n### Fixed\n\n-   Fixed not being able to take out items from Wireless Grid cross-dimensionally.\n\n## [0.9.1-beta] - 2016-08-24\n\n### Fixed\n\n-   Fixed server crash with Grid.\n\n## [0.9.0-beta] - 2016-08-24\n\n### Added\n\n-   Added fluid storage.\n-   Added Russian translation.\n\n### Changed\n\n-   Energy usage of Wireless Grid is now configurable.\n-   Wireless Transmitters can now only be placed on Cable.\n-   Priority field and detector amount field can now display 4 digits at a time.\n\n### Fixed\n\n-   Fixed crash with Grid.\n-   Fixed Grid Filter only updating the Grid when reopening the GUI.\n-   Fixed Wireless Grid not working cross dimensionally.\n-   Fixed Grid not displaying items after changing redstone mode.\n-   Fixed Wireless Transmitter crashing when it is transmitting to a removed dimension.\n-   Fixed disassembling stacked Storage Blocks only returns 1 set of items.\n\n## [0.8.20-beta] - 2016-08-18\n\n### Fixed\n\n-   Fixed crash with Grid.\n\n## [0.8.19-beta] - 2016-08-13\n\n### Fixed\n\n-   Fixed item duplication bug with External Storage.\n-   Fixed External Storage taking too long to update storage.\n-   Fixed crash with Grid.\n-   Fixed crash when shift clicking unsupported item in a slot.\n\n## [0.8.18-beta] - 2016-08-11\n\n### Fixed\n\n-   Fixed Detector mode not persisting.\n-   Fixed bug where scrollbar didn't scroll correctly and thus hiding some items.\n-   Fixed Network Transmitter not dropping inventory when broken.\n\n## [0.8.17-beta] - 2016-08-09\n\n### Fixed\n\n-   Fixed Grid causing sorting lag on the client.\n\n## [0.8.16-beta] - 2016-08-09\n\n### Added\n\n-   Added German translation by ChillUpX.\n-   Added MCMultiPart integration for Cable Parts.\n\n### Changed\n\n-   You now have to click the actual cable part head in order to get the GUI open.\n-   Grid Filters can now only filter 9 items, but, Grids take 4 filters now instead.\n-   Grid Filters can now be configured to compare on NBT and/ or damage.\n-   It is now possible to shift click items to the Storage Device filters.\n-   Updated to Forge 2046.\n-   Updated Tesla.\n-   Java 8 is now a requirement.\n-   Slight performance increase and network efficiency improvement in all GUI's.\n-   Slight performance increase in Grid GUI.\n-   Improved collisions of Cable parts.\n\n### Fixed\n\n-   Fixed issue with IC2 integration causing console spam.\n-   Fixed not being able to change some configs in blocks.\n-   Fixed serverside configs not syncing up with clientside.\n-   Fixed not being able to move inventory items in Grid GUI's to hotbar via the number keys.\n-   Fixed Relays when being in \"Ignore Redstone\" mode using up energy.\n-   Fixed Crafter facing bottom side on placement.\n\n## [0.8.15-beta] - 2016-08-01\n\n### Fixed\n\n-   Fixed server startup crash.\n\n## [0.8.14-beta] - 2016-08-01\n\n### Added\n\n-   Added Interdimensional Upgrade so the Network Transmitter can work over different dimensions.\n\n## [0.8.13-beta] - 2016-07-31\n\n### Added\n\n-   Added config option to set the base energy usage of the Controller (default is 0).\n-   Added Grid Filter item to filter items in any Grid.\n-   Added support for processing patterns with big stacksizes.\n-   Added Network Transmitter, Network Receiver and Network Cards.\n\n### Changed\n\n-   The slot where the Wireless Grid is in in the Wireless Grid GUI is now disabled, so the item can't be thrown out of the inventory by accident.\n-   Changed Relay recipe to use redstone torch instead of Basic Processor.\n-   Placed machines now face the block they are placed on, like hoppers.\n\n### Fixed\n\n-   Fixed rendering crash with Disk Drive.\n-   Fixed crash when quickly toggling sorting direction in Grid.\n-   Fixed not being able to clear exporter row in interface.\n\n## [0.8.12-beta] - 2016-07-20\n\n### Fixed\n\n-   Fixed dupe bug when shift clicking output slot in grid.\n\n## [0.8.11-beta] - 2016-07-19\n\n### Added\n\n-   Added X button to Processing Pattern Encoder to clear configuration of inputs and outputs.\n-   Added Grid view toggle buttons (regular, craftable items only, no craftable items).\n-   Added ability to shift click items into Importer, Exporter, Constructor, Destructor and Detector to set up whitelist / blacklist configurations easier.\n-   Re-added opposite facing on shift click functionality.\n\n### Changed\n\n-   Solderer upgrades go to upgrades slots first now when shift clicking.\n-   Updated to Forge 2014.\n\n### Fixed\n\n-   Fixed minor dupe bug with JEI transferring.\n-   Fixed exporter crafting upgrades taking priority over other tasks.\n-   Fixed NPE with incorrectly initialized disks.\n-   Fixed not being able to take out items of Grid 2K16.\n-   Fixed not being able to start autocrafting for certain items (most notably IC2 items).\n\n## [0.8.10-beta] - 2016-07-13\n\n### Fixed\n\n-   Fixed not being able to get some items out of Grid.\n-   Fixed slight glitch in Constructor and Destructor model.\n\n## [0.8.9-beta] - 2016-07-10\n\n### Added\n\n-   Added a model for the Constructor.\n-   Added a model for the Destructor.\n\n### Changed\n\n-   Wireless Transmitters next to each other without any cable or without being connected to a machine won't work anymore, they need to be explictly connected to a cable or other machine.\n-   Some models / texture tweaks.\n\n### Fixed\n\n-   Fixed bug where Grid crafting doesn't handle remainder sometimes.\n-   Fixed caching issues with External Storage.\n-   Fixed possible crash with Disk Drives.\n\n## [0.8.8-beta] - 2016-07-10\n\n### Changed\n\n-   Use ore dictionary for recipes with glass.\n-   Texture tweaks.\n\n### Fixed\n\n-   Fixed solderer not working with automation anymore.\n\n## [0.8.7-beta] - 2016-07-09\n\n### Added\n\n-   Added better hitbox for the Solderer.\n\n### Changed\n\n-   Wireless Transmitter is now only bright red when connected.\n-   Improved detector model, add a better hitbox for it.\n-   Improved the Wireless Transmitter texture.\n-   Made the Solderer beams be bright red when they are working.\n\n### Fixed\n\n-   Fixed crash with External Storage.\n-   Fixed Detector not unpowering when disconnected from the network.\n\n## [0.8.6-beta] - 2016-07-09\n\n### Added\n\n-   Re-added Controllers exploding when two of them are connected to the same network.\n-   Added new textures.\n-   Added model for External Storage.\n-   Added model for Importer.\n-   Added model for Exporter.\n-   Added model for Detector.\n\n### Changed\n\n-   Huge performance improvements to large storage networks.\n-   Limited some blocks to only have a direction on the x-axis.\n-   Decreased amount of block updates significantly.\n\n### Fixed\n\n-   Fixed External Storage disconnecting on world reload.\n-   Fixed External Storage not updating correctly.\n-   Fixed wireless signal starting from Controller instead of per Wireless Transmitter individually.\n-   Fixed Controller's redstone state not saving.\n-   Fixed crafting tasks not saving properly.\n\n### Removed\n\n-   Removed opposite facing on placement mechanic.\n-   Removed Quartz Enriched Iron Block.\n\n## [0.8.5-beta] - 2016-07-04\n\n### Fixed\n\n-   Fixed crash when Tesla API is not installed.\n\n## [0.8.4-beta] - 2016-07-04\n\n### Added\n\n-   Added a debug storage disk.\n-   Added tooltip to solderer progress bar that shows progress percentage.\n-   Added support for the Tesla energy system.\n-   Added support for the IC2 (EU) energy system.\n-   Added a Portuguese (Brazilian) translation.\n\n### Changed\n\n-   Performance improvements.\n-   Tweaked grid GUI.\n\n### Removed\n\n-   Removed delay until grid items are visible.\n\n## [0.8.3-beta] - 2016-07-02\n\n### Fixed\n\n-   Fixed drawer controllers not working with external storage.\n-   Fixed right click taking 64 items instead of 32 items.\n\n## [0.8.2-beta] - 2016-07-01\n\n### Changed\n\n-   It is now possible to use middle click multiple times for the same item in grid.\n-   Made the mod configurable with a config file.\n\n### Fixed\n\n-   Fixed not being able to take items sometimes.\n\n## [0.8.1-beta] - 2016-06-30\n\n### Fixed\n\n-   Fixed upgrades from interface not dropping.\n-   Fixed lag caused by constantly rebuilding storage.\n\n## [0.8.0-beta] - 2016-06-25\n\n### Changed\n\n-   Recompile for Minecraft 1.10.\n\n### Fixed\n\n-   Fixed solderer not using extra RF/t with upgrades.\n\n## [0.7.19-beta] - 2016-06-25\n\n### Fixed\n\n-   Fixed controller being buggy with reconnecting.\n-   Fixed controller texture updating too slow when energy changes.\n-   Fixed not being able to take item from grid at times.\n-   Fixed external storage on storage drawer sending an item count of 0 over.\n\n## [0.7.18-beta] - 2016-06-24\n\n### Fixed\n\n-   Fixed cables sending updates when not needed.\n-   Fixed cables not connecting to foreign machines that implement the API.\n\n## [0.7.17-beta] - 2016-06-24\n\n### Changed\n\n-   Updated Forge to 1969.\n-   Updated JEI to 3.6.x.\n-   Introduced new crafting settings GUI.\n-   Tweaked some textures.\n\n### Fixed\n\n-   Fixed getting wrong items back in grid.\n-   Fixed wrong item getting crafted.\n-   Fixed server lag with exporter and importer.\n\n## [0.7.16-beta] - 2016-06-19\n\n### Added\n\n-   Added support for Storage Drawers void upgrade.\n-   Added support for Deep Storage Unit API again.\n\n### Fixed\n\n-   Fixed NPE in machine searching.\n-   Fixed a bug with interface giving negative amounts of items.\n-   Fixed crash when using scroll wheel.\n\n## [0.7.15-beta] - 2016-06-18\n\n### Fixed\n\n-   Fixed not being able to scroll with the scroll wheel using MouseTweaks.\n-   Fixed grid search box mode only changing after reopening GUI.\n\n## [0.7.14-beta] - 2016-06-17\n\n### Added\n\n-   Added shift clicking support to every inventory (for upgrades etc).\n-   Added grid filtering options: @ for searching on mod items, # for searching on tooltips.\n-   Added a way to clear patterns (shift + right click in inventory).\n\n### Changed\n\n-   Updated Forge to build 1965.\n-   Tweaked some recipes.\n-   Tweaked energy usage in some machines.\n\n### Fixed\n\n-   Fixed item overflow bug with storage drawers and external storage.\n\n## [0.7.13-beta] - 2016-06-16\n\n### Added\n\n-   Added ability to triple click in grid.\n\n## [0.7.12-beta] - 2016-06-14\n\n### Fixed\n\n-   Fixed creative storage blocks and disks not working.\n-   Fixed interface overflowing.\n\n## [0.7.11-beta] - 2016-06-12\n\n### Changed\n\n-   Right click on grid search bar clears the search query.\n\n### Fixed\n\n-   Fixed crash with wireless grid.\n-   Fixed high RF/t usage on external storage.\n-   Fixed that requesting crafting processing task yields too many tasks.\n\n## [0.7.10-beta] - 2016-06-11\n\n### Fixed\n\n-   Fixed inventories not saving correctly.\n-   Fixed that the player can't shift-click patterns into the last 3 slots of the Crafter.\n\n## [0.7.9-beta] - 2016-06-11\n\n### Added\n\n-   Added an API.\n-   Added Storage Drawers integration.\n-   Added handling for patterns that return the same item.\n-   Added stack splitting between multiple storages.\n-   Added handling for patterns that give back the same item.\n\n### Changed\n\n-   Increased cable recipe to 12 cables.\n\n### Fixed\n\n-   Fixed not being able to place sugar cane.\n-   Fixed not being able to place seeds.\n-   Fixed stacks not splitting between storages correctly.\n-   Fixed storage not saving ItemStack capabilities.\n-   Fixed dropping items into crafting grid with mouse won't work if your mouse is in between items.\n-   Fixed controller still drawing power even if disabled.\n\n## [0.7.8-beta] - 2016-06-04\n\n### Changed\n\n-   Updated to Forge 1951.\n\n### Fixed\n\n-   Fixed crash on some worlds.\n-   Improved Grid performance when sorting on quantity.\n\n## [0.7.7-beta] - 2016-06-04\n\n### Added\n\n-   Added the Stack Upgrade.\n-   Added Quartz Enriched Iron Block.\n-   Added French translation by Leventovitch.\n\n### Changed\n\n-   New items now go to the first available storage that has items in it already.\n-   Tweaked some recipes.\n\n### Fixed\n\n-   Fixed buggy reequip animation on wireless grid.\n-   Fixed solderer not supporting ore dictionary.\n-   Fixed recipes not supporting ore dictionary.\n-   Fixed destructor not being able to destroy some blocks.\n-   Fixed not being able to place or destroy sugar cane.\n-   Fixed storage blocks not being dismantable.\n-   Fixed getting more items than needed sometimes.\n-   Performance improvements.\n\n## [0.7.6-beta] - 2016-05-29\n\n### Changed\n\n-   Updated to Forge 1932.\n\n### Fixed\n\n-   Fixed not being able to start an autocraft.\n\n## [0.7.5-beta] - 2016-05-29\n\n### Fixed\n\n-   Fixed wrong ascending / descending order in Grid.\n-   Fixed autocrafting not giving back byproducts.\n-   Fixed Solderer causing too many chunk updates.\n-   Fixed Solderer slot sides being weird.\n-   Performance improvements.\n\n## [0.7.4-beta] - 2016-05-27\n\n### Changed\n\n-   Updated to Forge 1922.\n\n### Fixed\n\n-   Performance improvements.\n\n## [0.7.3-beta] - 2016-05-25\n\n### Changed\n\n-   Crafting tasks are now sorted from new to old in the Crafting Monitor.\n-   Broke Interface block inventory compatibility: make sure to take all your items out of your Interface blocks before you apply the update.\n\n### Fixed\n\n-   Fixed grid performance by not sending grid data so often.\n-   Fixed silicon + quartz enriched iron not having oredict names.\n\n## [0.7.2-beta] - 2016-05-24\n\n### Fixed\n\n-   Fixed Importer getting stuck on slot.\n\n## [0.7.1-beta] - 2016-05-24\n\n### Fixed\n\n-   Fixed NPE in some tiles.\n-   Fixed going out of crafting GUI not restoring state (scrollbar and search term).\n-   Fixed not being able to create a pattern in disconnected Pattern Grid.\n-   Fixed not being able to place cake or string.\n-   Performance improvement to Grids.\n\n## [0.7.0-beta] - 2016-05-23\n\n### Added\n\n-   Port to Minecraft 1.9.4.\n\n### Fixed\n\n-   Fixed Crafting Grid / Pattern Grid not throwing items on break.\n\n## [0.6.15-alpha] - 2016-05-29\n\n### Fixed\n\n-   Fixed Solderer sides being weird.\n-   Fixed Solderer causing too many block updates.\n\n## [0.6.14-alpha] - 2016-05-28\n\n### Fixed\n\n-   Fixed wrong ascending / descending order in Grid.\n-   Performance improvements.\n\n## [0.6.13-alpha] - 2016-05-27\n\n### Fixed\n\n-   Performance improvements.\n\n## [0.6.12-alpha] - 2016-05-25\n\n### Changed\n\n-   Crafting tasks are now sorted from new to old in the Crafting Monitor.\n\n### Fixed\n\n-   Fixed Crafting Grid / Pattern Grid not throwing items on break.\n-   Fixed NPE in some tiles.\n-   Fixed going out of crafting GUI not restoring state (scrollbar and search term).\n-   Fixed not being able to place cake or string.\n-   Fixed Importer getting stuck on slot.\n-   Fixed silicon + quartz enriched iron not having oredict names.\n-   Performance improvement to Grids.\n\n## [0.6.11-alpha] - 2016-05-23\n\n### Changed\n\n-   Converted all inventories in the mod to Forge's item handler capability system.\n\n### Fixed\n\n-   Fixed crafting patterns crashing when item of an input or output no longer exists.\n-   Fixed Grid letting the current held item flicker.\n-   Fixed Importer / Exporter / External Storage not being able to push or pull out of the other side of a double chest.\n\n## [0.6.10-alpha] - 2016-05-21\n\n### Changed\n\n-   Increased max crafting request size to 500.\n\n### Fixed\n\n-   Fixed Processing Patterns not working.\n-   Fixed not being able to request more than 1 item at once.\n-   Fixed crash with the Solderer.\n\n## [0.6.9-alpha] - 2016-05-20\n\n### Added\n\n-   Added automation for the Solderer: every side corresponds to a slot (see the wiki).\n\n### Fixed\n\n-   Fixed bug where machines wouldn't disconnect / connect when needed outside of chunk.\n-   Fixed not being able to toggle redstone mode in a Wireless Transmitter.\n-   Fixed same machine being connected to the network multiple times.\n-   Fixed External Storage not working.\n-   Reduced network usage.\n\n## [0.6.8-alpha] - 2016-05-19\n\n### Fixed\n\n-   Fixed CTRL + pick block on machines crashing game.\n-   Performance improvements.\n\n## [0.6.7-alpha] - 2016-05-19\n\n### Fixed\n\n-   Performance improvements.\n\n## [0.6.6-alpha] - 2016-05-18\n\n### Fixed\n\n-   Fixed being able to insert non-allowed items in inventories with hoppers.\n-   Fixed Processing Pattern Encoder not using up a Pattern.\n\n## [0.6.5-alpha] - 2016-05-18\n\n### Changed\n\n-   Updated Forge to build 1907.\n\n### Fixed\n\n-   Performance improvements for servers.\n-   Performance improvements for client scrollbars.\n\n## [0.6.4-alpha] - 2016-05-17\n\n### Fixed\n\n-   Performance improvements.\n\n## [0.6.3-alpha] - 2016-05-17\n\n### Fixed\n\n-   Performance improvements.\n\n## [0.6.2-alpha] - 2016-05-17\n\n### Added\n\n-   Added a max crafting quantity per request cap (hardcoded to 100).\n\n### Changed\n\n-   Upgrades now draw extra energy.\n\n### Fixed\n\n-   Fixed race condition with crafting tasks.\n-   Fixed pressing escape in crafting settings GUI not going back to grid GUI.\n-   Fixed losing autoselection in Grid when clicking on slot with autoselection mode.\n-   Fixed being able to pick up from pattern result slot.\n\n## [0.6.1-alpha] - 2016-05-16\n\n### Fixed\n\n-   Fixed NPE on world load.\n-   Fixed Destructor crashing when removing a connected machine.\n\n## [0.6.0-alpha] - 2016-05-16\n\n### Added\n\n-   Added autocrafting.\n-   Added the Pattern Grid.\n-   Added the Crafting Monitor.\n-   Added the Crafter.\n-   Added the Processing Pattern Encoder.\n-   Added a Pattern item.\n-   Added the Wireless Transmitter.\n-   Added Speed Upgrades which are applicable on a bunch of machines.\n-   Added Range Upgrades for in the Wireless Transmitter.\n-   Added Crafting Upgrades.\n-   Added recipe category -> item JEI integration.\n-   Added Storage Housing.\n\n### Changed\n\n-   Changed Grid modes to have a autoselected option.\n\n### Fixed\n\n-   Fixed Destructor not playing block break sound.\n-   Fixed Constructor not playing block place sound.\n-   Fixed picking up from crafting result slot.\n-   Fixed being able to use right click on crafting result slot.\n-   Fixed item duplication issue with the Interface.\n-   Fixed Importers and Exporters not working when changing facing with a wrench.\n-   Fixed Crafting Grid not respecting remainder in recipes.\n-   Fixed Crafting Grid giving back the wrong amount of items when shift clicking.\n-   Fixed items disappearing in Grid when doing a weird combination of inputs.\n-   Fixed Solderer not stacking items.\n-   Fixed Importer voiding Storage Disks from the Disk Drive.\n-   Fixed Controller not saving energy.\n-   Massive performance improvements which reduces lag and lets machines connect almost instantly.\n\n## [0.5.6-alpha] - 2016-04-29\n\n### Fixed\n\n-   Fixed sorting crash.\n-   Fixed autofocusing on priority field in storage GUIs.\n-   Fixed controller causing lag when energy level changes.\n\n## [0.5.5-alpha] - 2016-04-09\n\n### Changed\n\n-   Updated to Forge 1859.\n\n### Fixed\n\n-   Fixed several crashes.\n-   Energy level on Controller is maintained.\n\n## [0.5.4-alpha] - 2016-04-05\n\n### Changed\n\n-   Shift clicking on placing Constructor and Destructor will have opposite direction.\n\n### Fixed\n\n-   Fixed machines out of the Controller's chunk range only connecting after block break when rejoining the world.\n-   Fixed scrollbar skipping some rows when scrolling with mouse wheel.\n-   Fixed machines from a long distance not being visible in the Controller.\n\n## [0.5.3-alpha] - 2016-04-04\n\n### Added\n\n-   Added a Creative Wireless Grid.\n\n### Changed\n\n-   Changed block hardness levels.\n\n### Fixed\n\n-   Fixed not being able to open a Grid that is 256 blocks away from the Controller.\n-   Made the mod way less network intensive.\n\n## [0.5.2-alpha] - 2016-04-03\n\n### Added\n\n-   Items that don't exist anymore, won't be added to storage again to avoid crashes.\n\n### Fixed\n\n-   Fixed not being able to run the mod without JEI.\n\n## [0.5.1-alpha] - 2016-04-03\n\n### Fixed\n\n-   Fixed Disk Drive crashing with an `AbstractMethodException`.\n\n## [0.5.0-alpha] - 2016-04-03\n\n### Added\n\n-   Deep Storage Unit integration (with this several barrel mods are now supported too!).\n-   When placing Importer, Exporter or External Storage with SHIFT, it will have the opposite direction. This is for easy placement behind other blocks (furnaces for example).\n-   Added mass crafting of items with shift in Crafting Grid.\n-   Added JEI recipe transfering in Crafting Grid.\n-   New textures.\n-   Scrollbar in Grid and Crafting Grid.\n-   Display of connected machines in the Controller GUI.\n-   Nice formatting for items >= 1K (pressing shift while hovering over an item will still display the real item count).\n-   Grid can now synchronize with JEI.\n\n### Changed\n\n-   Updated to the latest Forge and JEI.\n-   Renamed Drives to Disk Drives.\n-   Renamed Storage Cells to Storage Disks.\n-   Wireless Grid is now bound to a Controller instead of a Grid.\n-   Drives have a better interface and there are now blacklist and whitelist filters for the Storage Disks in it too.\n-   Destructors have the ability to whitelist and blacklist certain items now.\n-   Side buttons in machine GUIs are now left, not right.\n-   Shift clicking stuff in the Interface.\n-   Made the normal Grid 1 row larger.\n-   Machines don't need to be connected with cables anymore, they can be next to each other too.\n-   Made the amount text in the Grid for items smaller.\n\n### Fixed\n\n-   Fixed clicking sound in Grid.\n-   Fixed a bunch of crashes.\n-   Fixed Exporter not exporting is some cases.\n-   Fixed Importer not importing in some cases.\n-   Fixed Controller drawing RF every 20 ticks instead of every tick.\n-   Fixed not being able to shift click from Crafting Grid crafting slots.\n-   Fixed new items inserted after crafting in Grid being laggy.\n-   Fixed flickering of items in Grid.\n-   Fixed getting a stack of unstackable items from Grid.\n-   Fixed Cable not having a collision box.\n-   Check if the Constructor can actually place said block in the world.\n\n### Removed\n\n-   Removed Wireless Transmitters.\n\n## [0.4.1-alpha] - 2016-03-24\n\n### Fixed\n\n-   Fixed ID duplication issues.\n\n## [0.4.0-alpha] - 2016-03-21\n\n### Added\n\n-   Relays.\n-   Interfaces.\n\n### Changed\n\n-   Cables now have actual collision.\n\n### Fixed\n\n-   Fix Minecraft reporting that retrieving Grid type fails.\n-   Fullness percentage in Creative Storage Blocks going under 0%.\n-   The Controller shouldn't display the base usage when not working.\n-   Check if item is valid for slot before pushing to inventories.\n\n## [0.3.0-alpha] - 2016-03-20\n\n### Added\n\n-   Initial release for Minecraft 1.9.\n\n## [0.2.1-alpha] - 2016-02-03\n\n### Added\n\n-   Internal test release.\n\n## [0.2.0-alpha] - 2016-01-31\n\n### Added\n\n-   Internal test release.\n\n## [0.1.1-alpha] - 2016-01-31\n\n### Added\n\n-   Internal test release.\n\n## [0.1.0-alpha] - 2016-01-03\n\n### Added\n\n-   Internal test release.\n\n[Unreleased]: https://github.com/refinedmods/refinedstorage/compare/v1.13.0-beta.4...HEAD\n\n[1.13.0-beta.4]: https://github.com/refinedmods/refinedstorage/compare/v1.13.0-beta.3...v1.13.0-beta.4\n\n[1.13.0-beta.3]: https://github.com/refinedmods/refinedstorage/compare/v1.13.0-beta.2...v1.13.0-beta.3\n\n[1.13.0-beta.2]: https://github.com/refinedmods/refinedstorage/compare/v1.13.0-beta.1...v1.13.0-beta.2\n\n[1.13.0-beta.1]: https://github.com/refinedmods/refinedstorage/compare/v1.12.4...v1.13.0-beta.1\n\n[1.12.4]: https://github.com/refinedmods/refinedstorage/compare/v1.12.3...v1.12.4\n\n[1.12.3]: https://github.com/refinedmods/refinedstorage/compare/v1.12.2...v1.12.3\n\n[1.12.2]: https://github.com/refinedmods/refinedstorage/compare/v1.12.1...v1.12.2\n\n[1.12.1]: https://github.com/refinedmods/refinedstorage/compare/v1.12.0...v1.12.1\n\n[1.12.0]: https://github.com/refinedmods/refinedstorage/compare/v1.11.7...v1.12.0\n\n[1.11.7]: https://github.com/refinedmods/refinedstorage/compare/v1.11.6...v1.11.7\n\n[1.11.6]: https://github.com/refinedmods/refinedstorage/compare/v1.11.5...v1.11.6\n\n[1.11.5]: https://github.com/refinedmods/refinedstorage/compare/v1.11.4...v1.11.5\n\n[1.11.4]: https://github.com/refinedmods/refinedstorage/compare/v1.11.3...v1.11.4\n\n[1.11.3]: https://github.com/refinedmods/refinedstorage/compare/v1.11.2...v1.11.3\n\n[1.11.2]: https://github.com/refinedmods/refinedstorage/compare/v1.11.1...v1.11.2\n\n[1.11.1]: https://github.com/refinedmods/refinedstorage/compare/v1.11.0...v1.11.1\n\n[1.11.0]: https://github.com/refinedmods/refinedstorage/compare/v1.10.6...v1.11.0\n\n[1.10.6]: https://github.com/refinedmods/refinedstorage/compare/v1.10.5...v1.10.6\n\n[1.10.5]: https://github.com/refinedmods/refinedstorage/compare/v1.10.4...v1.10.5\n\n[1.10.4]: https://github.com/refinedmods/refinedstorage/compare/v1.10.3...v1.10.4\n\n[1.10.3]: https://github.com/refinedmods/refinedstorage/compare/v1.10.2...v1.10.3\n\n[1.10.2]: https://github.com/refinedmods/refinedstorage/compare/v1.10.1...v1.10.2\n\n[1.10.1]: https://github.com/refinedmods/refinedstorage/compare/v1.10.0...v1.10.1\n\n[1.10.0]: https://github.com/refinedmods/refinedstorage/compare/v1.10.0-beta.4...v1.10.0\n\n[1.10.0-beta.4]: https://github.com/refinedmods/refinedstorage/compare/v1.10.0-beta.3...v1.10.0-beta.4\n\n[1.10.0-beta.3]: https://github.com/refinedmods/refinedstorage/compare/v1.10.0-beta.2...v1.10.0-beta.3\n\n[1.10.0-beta.2]: https://github.com/refinedmods/refinedstorage/compare/v1.10.0-beta.1...v1.10.0-beta.2\n\n[1.10.0-beta.1]: https://github.com/refinedmods/refinedstorage/compare/v1.9.18...v1.10.0-beta.1\n\n[1.9.18]: https://github.com/refinedmods/refinedstorage/compare/v1.9.17...v1.9.18\n\n[1.9.17]: https://github.com/refinedmods/refinedstorage/compare/v1.9.16...v1.9.17\n\n[1.9.16]: https://github.com/refinedmods/refinedstorage/compare/v1.9.15...v1.9.16\n\n[1.9.15]: https://github.com/refinedmods/refinedstorage/compare/v1.9.14...v1.9.15\n\n[1.9.14]: https://github.com/refinedmods/refinedstorage/compare/v1.9.13...v1.9.14\n\n[1.9.13]: https://github.com/refinedmods/refinedstorage/compare/v1.9.12...v1.9.13\n\n[1.9.12]: https://github.com/refinedmods/refinedstorage/compare/v1.9.11...v1.9.12\n\n[1.9.11]: https://github.com/refinedmods/refinedstorage/compare/v1.9.10...v1.9.11\n\n[1.9.10]: https://github.com/refinedmods/refinedstorage/compare/v1.9.9...v1.9.10\n\n[1.9.9]: https://github.com/refinedmods/refinedstorage/compare/v1.9.8...v1.9.9\n\n[1.9.8]: https://github.com/refinedmods/refinedstorage/compare/v1.9.7...v1.9.8\n\n[1.9.7]: https://github.com/refinedmods/refinedstorage/compare/v1.9.6...v1.9.7\n\n[1.9.6]: https://github.com/refinedmods/refinedstorage/compare/v1.9.5...v1.9.6\n\n[1.9.5]: https://github.com/refinedmods/refinedstorage/compare/v1.9.4...v1.9.5\n\n[1.9.4]: https://github.com/refinedmods/refinedstorage/compare/v1.9.3-beta...v1.9.4\n\n[1.9.3-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.9.2-beta.2...v1.9.3-beta\n\n[1.9.2-beta.2]: https://github.com/refinedmods/refinedstorage/compare/v1.9.2-beta.1...v1.9.2-beta.2\n\n[1.9.2-beta.1]: https://github.com/refinedmods/refinedstorage/compare/v1.9.1-beta...v1.9.2-beta.1\n\n[1.9.1-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.9.0-beta...v1.9.1-beta\n\n[1.9.0-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.8.8...v1.9.0-beta\n\n[1.8.8]: https://github.com/refinedmods/refinedstorage/compare/v1.8.7...v1.8.8\n\n[1.8.7]: https://github.com/refinedmods/refinedstorage/compare/v1.8.6-beta...v1.8.7\n\n[1.8.6-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.8.5-beta...v1.8.6-beta\n\n[1.8.5-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.8.4-beta...v1.8.5-beta\n\n[1.8.4-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.8.3-beta...v1.8.4-beta\n\n[1.8.3-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.8.2-beta...v1.8.3-beta\n\n[1.8.2-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.8.1-beta...v1.8.2-beta\n\n[1.8.1-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.8.0-beta...v1.8.1-beta\n\n[1.8.0-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.7.3-beta...v1.8.0-beta\n\n[1.7.3-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.7.2-beta...v1.7.3-beta\n\n[1.7.2-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.7.1-alpha...v1.7.2-beta\n\n[1.7.1-alpha]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0-alpha...v1.7.1-alpha\n\n[1.7.0-alpha]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0+10...v1.7.0-alpha\n\n[1.7.0+10]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0+9...v1.7.0+10\n\n[1.7.0+9]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0+8...v1.7.0+9\n\n[1.7.0+8]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0+7...v1.7.0+8\n\n[1.7.0+7]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0+6...v1.7.0+7\n\n[1.7.0+6]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0+5...v1.7.0+6\n\n[1.7.0+5]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0+4...v1.7.0+5\n\n[1.7.0+4]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0+3...v1.7.0+4\n\n[1.7.0+3]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0+2...v1.7.0+3\n\n[1.7.0+2]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0+1...v1.7.0+2\n\n[1.7.0+1]: https://github.com/refinedmods/refinedstorage/compare/v1.6.16...v1.7.0+1\n\n[1.6.16]: https://github.com/refinedmods/refinedstorage/compare/v1.6.15...v1.6.16\n\n[1.6.15]: https://github.com/refinedmods/refinedstorage/compare/v1.6.14...v1.6.15\n\n[1.6.14]: https://github.com/refinedmods/refinedstorage/compare/v1.6.13...v1.6.14\n\n[1.6.13]: https://github.com/refinedmods/refinedstorage/compare/v1.6.12...v1.6.13\n\n[1.6.12]: https://github.com/refinedmods/refinedstorage/compare/v1.6.11...v1.6.12\n\n[1.6.11]: https://github.com/refinedmods/refinedstorage/compare/v1.6.10...v1.6.11\n\n[1.6.10]: https://github.com/refinedmods/refinedstorage/compare/v1.6.9...v1.6.10\n\n[1.6.9]: https://github.com/refinedmods/refinedstorage/compare/v1.6.8...v1.6.9\n\n[1.6.8]: https://github.com/refinedmods/refinedstorage/compare/v1.6.7...v1.6.8\n\n[1.6.7]: https://github.com/refinedmods/refinedstorage/compare/v1.6.6...v1.6.7\n\n[1.6.6]: https://github.com/refinedmods/refinedstorage/compare/v1.6.5...v1.6.6\n\n[1.6.5]: https://github.com/refinedmods/refinedstorage/compare/v1.6.4...v1.6.5\n\n[1.6.4]: https://github.com/refinedmods/refinedstorage/compare/v1.6.3...v1.6.4\n\n[1.6.3]: https://github.com/refinedmods/refinedstorage/compare/v1.6.2...v1.6.3\n\n[1.6.2]: https://github.com/refinedmods/refinedstorage/compare/v1.6.1...v1.6.2\n\n[1.6.1]: https://github.com/refinedmods/refinedstorage/compare/v1.6.0...v1.6.1\n\n[1.6.0]: https://github.com/refinedmods/refinedstorage/compare/v1.5.34...v1.6.0\n\n[1.5.34]: https://github.com/refinedmods/refinedstorage/compare/v1.5.33...v1.5.34\n\n[1.5.33]: https://github.com/refinedmods/refinedstorage/compare/v1.5.32...v1.5.33\n\n[1.5.32]: https://github.com/refinedmods/refinedstorage/compare/v1.5.31...v1.5.32\n\n[1.5.31]: https://github.com/refinedmods/refinedstorage/compare/v1.5.30...v1.5.31\n\n[1.5.30]: https://github.com/refinedmods/refinedstorage/compare/v1.5.29...v1.5.30\n\n[1.5.29]: https://github.com/refinedmods/refinedstorage/compare/v1.5.28...v1.5.29\n\n[1.5.28]: https://github.com/refinedmods/refinedstorage/compare/v1.5.27-beta...v1.5.28\n\n[1.5.27-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.5.26-beta...v1.5.27-beta\n\n[1.5.26-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.5.25...v1.5.26-beta\n\n[1.5.25]: https://github.com/refinedmods/refinedstorage/compare/v1.5.24...v1.5.25\n\n[1.5.24]: https://github.com/refinedmods/refinedstorage/compare/v1.5.23...v1.5.24\n\n[1.5.23]: https://github.com/refinedmods/refinedstorage/compare/v1.5.22...v1.5.23\n\n[1.5.22]: https://github.com/refinedmods/refinedstorage/compare/v1.5.21...v1.5.22\n\n[1.5.21]: https://github.com/refinedmods/refinedstorage/compare/v1.5.20...v1.5.21\n\n[1.5.20]: https://github.com/refinedmods/refinedstorage/compare/v1.5.19...v1.5.20\n\n[1.5.19]: https://github.com/refinedmods/refinedstorage/compare/v1.5.18...v1.5.19\n\n[1.5.18]: https://github.com/refinedmods/refinedstorage/compare/v1.5.17...v1.5.18\n\n[1.5.17]: https://github.com/refinedmods/refinedstorage/compare/v1.5.16...v1.5.17\n\n[1.5.16]: https://github.com/refinedmods/refinedstorage/compare/v1.5.15...v1.5.16\n\n[1.5.15]: https://github.com/refinedmods/refinedstorage/compare/v1.5.14...v1.5.15\n\n[1.5.14]: https://github.com/refinedmods/refinedstorage/compare/v1.5.13...v1.5.14\n\n[1.5.13]: https://github.com/refinedmods/refinedstorage/compare/v1.5.12...v1.5.13\n\n[1.5.12]: https://github.com/refinedmods/refinedstorage/compare/v1.5.11...v1.5.12\n\n[1.5.11]: https://github.com/refinedmods/refinedstorage/compare/v1.5.10...v1.5.11\n\n[1.5.10]: https://github.com/refinedmods/refinedstorage/compare/v1.5.9...v1.5.10\n\n[1.5.9]: https://github.com/refinedmods/refinedstorage/compare/v1.5.8...v1.5.9\n\n[1.5.8]: https://github.com/refinedmods/refinedstorage/compare/v1.5.7...v1.5.8\n\n[1.5.7]: https://github.com/refinedmods/refinedstorage/compare/v1.5.6...v1.5.7\n\n[1.5.6]: https://github.com/refinedmods/refinedstorage/compare/v1.5.5-beta...v1.5.6\n\n[1.5.5-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.5.4-beta...v1.5.5-beta\n\n[1.5.4-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.5.3-beta...v1.5.4-beta\n\n[1.5.3-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.5.2-beta...v1.5.3-beta\n\n[1.5.2-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.5.1-beta...v1.5.2-beta\n\n[1.5.1-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.5.0-alpha...v1.5.1-beta\n\n[1.5.0-alpha]: https://github.com/refinedmods/refinedstorage/compare/v1.4.20...v1.5.0-alpha\n\n[1.4.20]: https://github.com/refinedmods/refinedstorage/compare/v1.4.19...v1.4.20\n\n[1.4.19]: https://github.com/refinedmods/refinedstorage/compare/v1.4.18...v1.4.19\n\n[1.4.18]: https://github.com/refinedmods/refinedstorage/compare/v1.4.17...v1.4.18\n\n[1.4.17]: https://github.com/refinedmods/refinedstorage/compare/v1.4.16...v1.4.17\n\n[1.4.16]: https://github.com/refinedmods/refinedstorage/compare/v1.4.15...v1.4.16\n\n[1.4.15]: https://github.com/refinedmods/refinedstorage/compare/v1.4.14...v1.4.15\n\n[1.4.14]: https://github.com/refinedmods/refinedstorage/compare/v1.4.13...v1.4.14\n\n[1.4.13]: https://github.com/refinedmods/refinedstorage/compare/v1.4.12...v1.4.13\n\n[1.4.12]: https://github.com/refinedmods/refinedstorage/compare/v1.4.11...v1.4.12\n\n[1.4.11]: https://github.com/refinedmods/refinedstorage/compare/v1.4.10-beta...v1.4.11\n\n[1.4.10-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.4.9-beta...v1.4.10-beta\n\n[1.4.9-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.4.8-beta...v1.4.9-beta\n\n[1.4.8-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.4.7-beta...v1.4.8-beta\n\n[1.4.7-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.4.6-beta...v1.4.7-beta\n\n[1.4.6-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.4.5-beta...v1.4.6-beta\n\n[1.4.5-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.4.4-beta...v1.4.5-beta\n\n[1.4.4-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.4.3-beta...v1.4.4-beta\n\n[1.4.3-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.4.2-beta...v1.4.3-beta\n\n[1.4.2-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.4.1-beta...v1.4.2-beta\n\n[1.4.1-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.4.0-beta...v1.4.1-beta\n\n[1.4.0-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.3.5-alpha...v1.4.0-beta\n\n[1.3.5-alpha]: https://github.com/refinedmods/refinedstorage/compare/v1.3.4-alpha...v1.3.5-alpha\n\n[1.3.4-alpha]: https://github.com/refinedmods/refinedstorage/compare/v1.3.3-alpha...v1.3.4-alpha\n\n[1.3.3-alpha]: https://github.com/refinedmods/refinedstorage/compare/v1.3.2-alpha...v1.3.3-alpha\n\n[1.3.2-alpha]: https://github.com/refinedmods/refinedstorage/compare/v1.3.1-alpha...v1.3.2-alpha\n\n[1.3.1-alpha]: https://github.com/refinedmods/refinedstorage/compare/v1.3.0-alpha...v1.3.1-alpha\n\n[1.3.0-alpha]: https://github.com/refinedmods/refinedstorage/compare/v1.2.26...v1.3.0-alpha\n\n[1.2.26]: https://github.com/refinedmods/refinedstorage/compare/v1.2.25...v1.2.26\n\n[1.2.25]: https://github.com/refinedmods/refinedstorage/compare/v1.2.24...v1.2.25\n\n[1.2.24]: https://github.com/refinedmods/refinedstorage/compare/v1.2.23...v1.2.24\n\n[1.2.23]: https://github.com/refinedmods/refinedstorage/compare/v1.2.22...v1.2.23\n\n[1.2.22]: https://github.com/refinedmods/refinedstorage/compare/v1.2.21...v1.2.22\n\n[1.2.21]: https://github.com/refinedmods/refinedstorage/compare/v1.2.20...v1.2.21\n\n[1.2.20]: https://github.com/refinedmods/refinedstorage/compare/v1.2.19...v1.2.20\n\n[1.2.19]: https://github.com/refinedmods/refinedstorage/compare/v1.2.18...v1.2.19\n\n[1.2.18]: https://github.com/refinedmods/refinedstorage/compare/v1.2.17...v1.2.18\n\n[1.2.17]: https://github.com/refinedmods/refinedstorage/compare/v1.2.16...v1.2.17\n\n[1.2.16]: https://github.com/refinedmods/refinedstorage/compare/v1.2.15...v1.2.16\n\n[1.2.15]: https://github.com/refinedmods/refinedstorage/compare/v1.2.14...v1.2.15\n\n[1.2.14]: https://github.com/refinedmods/refinedstorage/compare/v1.2.13...v1.2.14\n\n[1.2.13]: https://github.com/refinedmods/refinedstorage/compare/v1.2.12...v1.2.13\n\n[1.2.12]: https://github.com/refinedmods/refinedstorage/compare/v1.2.11...v1.2.12\n\n[1.2.11]: https://github.com/refinedmods/refinedstorage/compare/v1.2.10...v1.2.11\n\n[1.2.10]: https://github.com/refinedmods/refinedstorage/compare/v1.2.9...v1.2.10\n\n[1.2.9]: https://github.com/refinedmods/refinedstorage/compare/v1.2.8...v1.2.9\n\n[1.2.8]: https://github.com/refinedmods/refinedstorage/compare/v1.2.7...v1.2.8\n\n[1.2.7]: https://github.com/refinedmods/refinedstorage/compare/v1.2.6...v1.2.7\n\n[1.2.6]: https://github.com/refinedmods/refinedstorage/compare/v1.2.5...v1.2.6\n\n[1.2.5]: https://github.com/refinedmods/refinedstorage/compare/v1.2.4...v1.2.5\n\n[1.2.4]: https://github.com/refinedmods/refinedstorage/compare/v1.2.3...v1.2.4\n\n[1.2.3]: https://github.com/refinedmods/refinedstorage/compare/v1.2.2...v1.2.3\n\n[1.2.2]: https://github.com/refinedmods/refinedstorage/compare/v1.2.1...v1.2.2\n\n[1.2.1]: https://github.com/refinedmods/refinedstorage/compare/v1.2.0...v1.2.1\n\n[1.2.0]: https://github.com/refinedmods/refinedstorage/compare/v1.2.0-beta.8...v1.2.0\n\n[1.2.0-beta.8]: https://github.com/refinedmods/refinedstorage/compare/v1.2.0-beta.7...v1.2.0-beta.8\n\n[1.2.0-beta.7]: https://github.com/refinedmods/refinedstorage/compare/v1.2.0-beta.6...v1.2.0-beta.7\n\n[1.2.0-beta.6]: https://github.com/refinedmods/refinedstorage/compare/v1.2.0-beta.5...v1.2.0-beta.6\n\n[1.2.0-beta.5]: https://github.com/refinedmods/refinedstorage/compare/v1.2.0-beta.4...v1.2.0-beta.5\n\n[1.2.0-beta.4]: https://github.com/refinedmods/refinedstorage/compare/v1.2.0-beta.3...v1.2.0-beta.4\n\n[1.2.0-beta.3]: https://github.com/refinedmods/refinedstorage/compare/v1.2.0-beta.2...v1.2.0-beta.3\n\n[1.2.0-beta.2]: https://github.com/refinedmods/refinedstorage/compare/v1.2.0-beta.1...v1.2.0-beta.2\n\n[1.2.0-beta.1]: https://github.com/refinedmods/refinedstorage/compare/v1.1.3...v1.2.0-beta.1\n\n[1.1.3]: https://github.com/refinedmods/refinedstorage/compare/v1.1.2...v1.1.3\n\n[1.1.2]: https://github.com/refinedmods/refinedstorage/compare/v1.1.1...v1.1.2\n\n[1.1.1]: https://github.com/refinedmods/refinedstorage/compare/v1.1.0...v1.1.1\n\n[1.1.0]: https://github.com/refinedmods/refinedstorage/compare/v1.0.5...v1.1.0\n\n[1.0.5]: https://github.com/refinedmods/refinedstorage/compare/v1.0.4...v1.0.5\n\n[1.0.4]: https://github.com/refinedmods/refinedstorage/compare/v1.0.3...v1.0.4\n\n[1.0.3]: https://github.com/refinedmods/refinedstorage/compare/v1.0.2...v1.0.3\n\n[1.0.2]: https://github.com/refinedmods/refinedstorage/compare/v1.0.1...v1.0.2\n\n[1.0.1]: https://github.com/refinedmods/refinedstorage/compare/v1.0.0...v1.0.1\n\n[1.0.0]: https://github.com/refinedmods/refinedstorage/compare/v0.9.4-beta...v1.0.0\n\n[0.9.4-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.9.3-beta...v0.9.4-beta\n\n[0.9.3-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.9.2-beta...v0.9.3-beta\n\n[0.9.2-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.9.1-beta...v0.9.2-beta\n\n[0.9.1-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.9.0-beta...v0.9.1-beta\n\n[0.9.0-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.20-beta...v0.9.0-beta\n\n[0.8.20-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.19-beta...v0.8.20-beta\n\n[0.8.19-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.18-beta...v0.8.19-beta\n\n[0.8.18-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.17-beta...v0.8.18-beta\n\n[0.8.17-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.16-beta...v0.8.17-beta\n\n[0.8.16-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.15-beta...v0.8.16-beta\n\n[0.8.15-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.14-beta...v0.8.15-beta\n\n[0.8.14-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.13-beta...v0.8.14-beta\n\n[0.8.13-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.12-beta...v0.8.13-beta\n\n[0.8.12-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.11-beta...v0.8.12-beta\n\n[0.8.11-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.10-beta...v0.8.11-beta\n\n[0.8.10-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.9-beta...v0.8.10-beta\n\n[0.8.9-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.8-beta...v0.8.9-beta\n\n[0.8.8-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.7-beta...v0.8.8-beta\n\n[0.8.7-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.6-beta...v0.8.7-beta\n\n[0.8.6-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.5-beta...v0.8.6-beta\n\n[0.8.5-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.4-beta...v0.8.5-beta\n\n[0.8.4-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.3-beta...v0.8.4-beta\n\n[0.8.3-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.2-beta...v0.8.3-beta\n\n[0.8.2-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.1-beta...v0.8.2-beta\n\n[0.8.1-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.0-beta...v0.8.1-beta\n\n[0.8.0-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.19-beta...v0.8.0-beta\n\n[0.7.19-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.18-beta...v0.7.19-beta\n\n[0.7.18-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.17-beta...v0.7.18-beta\n\n[0.7.17-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.16-beta...v0.7.17-beta\n\n[0.7.16-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.15-beta...v0.7.16-beta\n\n[0.7.15-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.14-beta...v0.7.15-beta\n\n[0.7.14-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.13-beta...v0.7.14-beta\n\n[0.7.13-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.12-beta...v0.7.13-beta\n\n[0.7.12-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.11-beta...v0.7.12-beta\n\n[0.7.11-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.10-beta...v0.7.11-beta\n\n[0.7.10-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.9-beta...v0.7.10-beta\n\n[0.7.9-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.8-beta...v0.7.9-beta\n\n[0.7.8-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.7-beta...v0.7.8-beta\n\n[0.7.7-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.6-beta...v0.7.7-beta\n\n[0.7.6-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.5-beta...v0.7.6-beta\n\n[0.7.5-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.4-beta...v0.7.5-beta\n\n[0.7.4-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.3-beta...v0.7.4-beta\n\n[0.7.3-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.2-beta...v0.7.3-beta\n\n[0.7.2-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.1-beta...v0.7.2-beta\n\n[0.7.1-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.0-beta...v0.7.1-beta\n\n[0.7.0-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.6.15-alpha...v0.7.0-beta\n\n[0.6.15-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.14-alpha...v0.6.15-alpha\n\n[0.6.14-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.13-alpha...v0.6.14-alpha\n\n[0.6.13-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.12-alpha...v0.6.13-alpha\n\n[0.6.12-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.11-alpha...v0.6.12-alpha\n\n[0.6.11-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.10-alpha...v0.6.11-alpha\n\n[0.6.10-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.9-alpha...v0.6.10-alpha\n\n[0.6.9-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.8-alpha...v0.6.9-alpha\n\n[0.6.8-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.7-alpha...v0.6.8-alpha\n\n[0.6.7-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.6-alpha...v0.6.7-alpha\n\n[0.6.6-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.5-alpha...v0.6.6-alpha\n\n[0.6.5-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.4-alpha...v0.6.5-alpha\n\n[0.6.4-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.3-alpha...v0.6.4-alpha\n\n[0.6.3-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.2-alpha...v0.6.3-alpha\n\n[0.6.2-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.1-alpha...v0.6.2-alpha\n\n[0.6.1-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.0-alpha...v0.6.1-alpha\n\n[0.6.0-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.5.6-alpha...v0.6.0-alpha\n\n[0.5.6-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.5.5-alpha...v0.5.6-alpha\n\n[0.5.5-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.5.4-alpha...v0.5.5-alpha\n\n[0.5.4-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.5.3-alpha...v0.5.4-alpha\n\n[0.5.3-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.5.2-alpha...v0.5.3-alpha\n\n[0.5.2-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.5.1-alpha...v0.5.2-alpha\n\n[0.5.1-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.5.0-alpha...v0.5.1-alpha\n\n[0.5.0-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.4.1-alpha...v0.5.0-alpha\n\n[0.4.1-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.4.0-alpha...v0.4.1-alpha\n\n[0.4.0-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.3.0-alpha...v0.4.0-alpha\n\n[0.3.0-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.2.1-alpha...v0.3.0-alpha\n\n[0.2.1-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.2.0-alpha...v0.2.1-alpha\n\n[0.2.0-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.1.1-alpha...v0.2.0-alpha\n\n[0.1.1-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.1.0-alpha...v0.1.1-alpha\n\n[0.1.0-alpha]: https://github.com/refinedmods/refinedstorage/releases/tag/v0.1.0-alpha\n"
  },
  {
    "path": "LICENSE.md",
    "content": "# The MIT License (MIT)\n\nCopyright © 2015 - 2025 Refined Mods\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the “Software”), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<div align=\"center\">\n  <h2>⚠️ IMPORTANT NOTICE ⚠️</h2>\n  <p><strong>This repository is for <em>Refined Storage v1.x</em>.</strong></p>\n  <p>🚫 <strong>v1.x is no longer maintained, and we do not accept issues for it.</strong></p>\n  <p>\n    🛠 Please report all bugs, issues, and suggestions for <strong>Refined Storage v2.x</strong> in the<br>\n    <a href=\"https://github.com/refinedmods/refinedstorage2/issues\">Refined Storage 2 issue tracker</a>.\n  </p>\n</div>\n\n<div align=\"center\">\n  <img width=\"280\" alt=\"Refined Storage logo\" src=\"https://raw.githubusercontent.com/refinedmods/refinedstorage/develop/images/logo.png\" />\n  <h1 style=\"margin-top: 0\">Refined Storage</h1>\n  <p>Refined Storage is a mass storage mod for Minecraft that offers the player a network-based storage system, allowing\nthem to store items and fluids on a massively expandable device network.</p>\n\n[![Build Status](https://github.com/refinedmods/refinedstorage/actions/workflows/build.yml/badge.svg?branch=develop)](https://github.com/refinedmods/refinedstorage/actions/workflows/build.yml) [![Downloads on CurseForge](http://cf.way2muchnoise.eu/full_243076_downloads.svg)](http://minecraft.curseforge.com/projects/refined-storage) [![Downloads on Modrinth](https://img.shields.io/modrinth/dt/refined-storage?logo=modrinth)](https://modrinth.com/mod/refined-storage) [![Discord](https://img.shields.io/discord/342942776494653441)](https://discordapp.com/invite/VYzsydb) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE.md)\n</div>\n\n## About\n\nItems and fluids can be stored in one of the many storage capabilities that the mod offers. Any storage devices\nconnected to the same network are accessible to the player through one simple Grid interface, allowing the player to\naccess the inventories of many devices through a single unified GUI.\n\nThis mod not only adds storage solutions, but also devices that can be used to manipulate items and blocks in the world\nand from within the system, such as importers, exporters, constructors, destructors, and more! There are also devices in\nthis mod that allow the player to setup auto-crafting, allowing the crafting of complex recipes in a few simple clicks.\n\n## Links\n\n- [GitHub](https://github.com/refinedmods/refinedstorage)\n    - [Releases](https://github.com/refinedmods/refinedstorage/releases)\n    - [Packages](https://github.com/refinedmods/refinedstorage/packages)\n    - [Issues](https://github.com/refinedmods/refinedstorage/issues)\n    - [Refined Mods on GitHub](https://github.com/refinedmods)\n- [CurseForge](https://curseforge.com/minecraft/mc-mods/refined-storage)\n- [Modrinth](https://modrinth.com/mod/refined-storage)\n- [Wiki](https://refinedmods.com/refined-storage/)\n- [Javadoc](https://refinedmods.com/javadoc/refinedstorage)\n- [Discord](https://discordapp.com/invite/VYzsydb)\n\n## Building\n\nClone the repository and import the Gradle project.\n\n## Contributing\n\nSee [CONTRIBUTING.md](.github/CONTRIBUTING.md).\n\n## Support\n\nSee [SUPPORT.md](.github/SUPPORT.md).\n\n## Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md).\n"
  },
  {
    "path": "build.gradle",
    "content": "apply from: \"https://raw.githubusercontent.com/refinedmods/refinedarchitect/v0.11.4/helper.gradle\"\r\n\r\nrepositories {\r\n    maven {\r\n        name = 'JEI'\r\n        url = \"https://maven.blamejared.com/\"\r\n    }\r\n    maven {\r\n        url \"https://www.cursemaven.com\"\r\n        content {\r\n            includeGroup \"curse.maven\"\r\n        }\r\n    }\r\n    maven {\r\n        name = 'Curios'\r\n        url = \"https://maven.theillusivec4.top/\"\r\n    }\r\n}\r\n\r\ngroup = 'com.refinedmods'\r\n\r\nforgeProject(\"refinedstorage\")\r\n\r\narchivesBaseName = 'refinedstorage'\r\n\r\nenablePublishing()\r\nenableCurseForge(243076)\r\nenableModrinth(\"KDvYkUg3\")\r\nenableJavadoc()\r\n\r\ndependencies {\r\n    compileOnly \"mezz.jei:jei-1.20.4-common-api:17.3.0.43\"\r\n    compileOnly \"mezz.jei:jei-1.20.4-neoforge-api:17.3.0.43\"\r\n    runtimeOnly \"mezz.jei:jei-1.20.4-neoforge:17.3.0.43\"\r\n\r\n    compileOnly \"curse.maven:mouse-tweaks-60089:4776995\"\r\n\r\n    compileOnly 'curse.maven:crafting-tweaks-233071:4991559'\r\n\r\n    implementation \"top.theillusivec4.curios:curios-neoforge:7.2.0+1.20.4\"\r\n}\r\n"
  },
  {
    "path": "config/checkstyle/checkstyle.xml",
    "content": "<?xml version=\"1.0\"?>\n<!DOCTYPE module PUBLIC\n        \"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN\"\n        \"https://checkstyle.org/dtds/configuration_1_3.dtd\">\n<module name=\"Checker\">\n    <property name=\"charset\" value=\"UTF-8\"/>\n    <property name=\"fileExtensions\" value=\"java, properties, xml\"/>\n</module>\n"
  },
  {
    "path": "docs/nav.json",
    "content": "[\n  {\n    \"title\": \"Home\",\n    \"ref\": \"index.adoc\",\n    \"icon\": \"bi-house-fill\"\n  },\n  {\n    \"title\": \"News\",\n    \"ref\": \"news/index.adoc\",\n    \"icon\": \"bi bi-newspaper\"\n  },\n  {\n    \"title\": \"Release notes\",\n    \"ref\": \"release-notes.adoc\",\n    \"icon\": \"bi bi-file-earmark-text\"\n  },\n  {\n    \"title\": \"Getting started\",\n    \"ref\": \"getting-started.adoc\",\n    \"icon\": \"bi-book\"\n  },\n  {\n    \"title\": \"FAQ\",\n    \"ref\": \"faq.adoc\",\n    \"icon\": \"bi-question-circle-fill\"\n  },\n  {\n    \"title\": \"Need help?\",\n    \"ref\": \"need-help.adoc\",\n    \"icon\": \"bi-person-raised-hand\"\n  },\n  {\n    \"title\": \"Networking\",\n    \"ref\": \"networking/index.adoc\",\n    \"children\": [\n      {\n        \"ref\": \"networking/controller.adoc\"\n      },\n      {\n        \"ref\": \"networking/creative-controller.adoc\"\n      },\n      {\n        \"ref\": \"networking/cable.adoc\"\n      },\n      {\n        \"ref\": \"networking/detector.adoc\"\n      },\n      {\n        \"ref\": \"networking/relay.adoc\"\n      }\n    ]\n  },\n  {\n    \"title\": \"Storage\",\n    \"ref\": \"storage/index.adoc\",\n    \"children\": [\n      {\n        \"ref\": \"storage/storing-externally.adoc\"\n      },\n      {\n        \"ref\": \"storage/storing-fluids.adoc\"\n      },\n      {\n        \"ref\": \"storage/disk-drive.adoc\"\n      },\n      {\n        \"ref\": \"storage/external-storage.adoc\"\n      },\n      {\n        \"ref\": \"storage/1k-storage-part.adoc\"\n      },\n      {\n        \"ref\": \"storage/4k-storage-part.adoc\"\n      },\n      {\n        \"ref\": \"storage/16k-storage-part.adoc\"\n      },\n      {\n        \"ref\": \"storage/64k-storage-part.adoc\"\n      },\n      {\n        \"ref\": \"storage/storage-housing.adoc\"\n      },\n      {\n        \"ref\": \"storage/1k-storage-disk.adoc\"\n      },\n      {\n        \"ref\": \"storage/4k-storage-disk.adoc\"\n      },\n      {\n        \"ref\": \"storage/16k-storage-disk.adoc\"\n      },\n      {\n        \"ref\": \"storage/64k-storage-disk.adoc\"\n      },\n      {\n        \"ref\": \"storage/creative-storage-disk.adoc\"\n      },\n      {\n        \"ref\": \"storage/1k-storage-block.adoc\"\n      },\n      {\n        \"ref\": \"storage/4k-storage-block.adoc\"\n      },\n      {\n        \"ref\": \"storage/16k-storage-block.adoc\"\n      },\n      {\n        \"ref\": \"storage/64k-storage-block.adoc\"\n      },\n      {\n        \"ref\": \"storage/creative-storage-block.adoc\"\n      },\n      {\n        \"ref\": \"storage/64k-fluid-storage-part.adoc\"\n      },\n      {\n        \"ref\": \"storage/256k-fluid-storage-part.adoc\"\n      },\n      {\n        \"ref\": \"storage/1024k-fluid-storage-part.adoc\"\n      },\n      {\n        \"ref\": \"storage/4096k-fluid-storage-part.adoc\"\n      },\n      {\n        \"ref\": \"storage/64k-fluid-storage-disk.adoc\"\n      },\n      {\n        \"ref\": \"storage/256k-fluid-storage-disk.adoc\"\n      },\n      {\n        \"ref\": \"storage/1024k-fluid-storage-disk.adoc\"\n      },\n      {\n        \"ref\": \"storage/4096k-fluid-storage-disk.adoc\"\n      },\n      {\n        \"ref\": \"storage/creative-fluid-storage-disk.adoc\"\n      },\n      {\n        \"ref\": \"storage/64k-fluid-storage-block.adoc\"\n      },\n      {\n        \"ref\": \"storage/256k-fluid-storage-block.adoc\"\n      },\n      {\n        \"ref\": \"storage/1024k-fluid-storage-block.adoc\"\n      },\n      {\n        \"ref\": \"storage/4096k-fluid-storage-block.adoc\"\n      },\n      {\n        \"ref\": \"storage/creative-fluid-storage-block.adoc\"\n      }\n    ]\n  },\n  {\n    \"title\": \"Viewing resources\",\n    \"ref\": \"viewing-resources/index.adoc\",\n    \"children\": [\n      {\n        \"ref\": \"viewing-resources/how-to-view-resources.adoc\"\n      },\n      {\n        \"ref\": \"viewing-resources/grid.adoc\"\n      },\n      {\n        \"ref\": \"viewing-resources/crafting-grid.adoc\"\n      },\n      {\n        \"ref\": \"viewing-resources/fluid-grid.adoc\"\n      },\n      {\n        \"ref\": \"viewing-resources/storage-monitor.adoc\"\n      },\n      {\n        \"ref\": \"viewing-resources/portable-grid.adoc\"\n      }\n    ]\n  },\n  {\n    \"title\": \"Input and output\",\n    \"ref\": \"input-and-output/index.adoc\",\n    \"children\": [\n      {\n        \"ref\": \"input-and-output/getting-items-in-and-out.adoc\"\n      },\n      {\n        \"ref\": \"input-and-output/importer.adoc\"\n      },\n      {\n        \"ref\": \"input-and-output/exporter.adoc\"\n      },\n      {\n        \"ref\": \"input-and-output/constructor.adoc\"\n      },\n      {\n        \"ref\": \"input-and-output/destructor.adoc\"\n      },\n      {\n        \"ref\": \"input-and-output/interface.adoc\"\n      },\n      {\n        \"ref\": \"input-and-output/fluid-interface.adoc\"\n      },\n      {\n        \"ref\": \"input-and-output/disk-manipulator.adoc\"\n      },\n      {\n        \"ref\": \"input-and-output/reader.adoc\"\n      },\n      {\n        \"ref\": \"input-and-output/writer.adoc\"\n      }\n    ]\n  },\n  {\n    \"title\": \"Wireless networking\",\n    \"ref\": \"wireless-networking/index.adoc\",\n    \"children\": [\n      {\n        \"ref\": \"wireless-networking/networks-over-long-distances.adoc\"\n      },\n      {\n        \"ref\": \"wireless-networking/wireless-transmitter.adoc\"\n      },\n      {\n        \"ref\": \"wireless-networking/wireless-grid.adoc\"\n      },\n      {\n        \"ref\": \"wireless-networking/wireless-crafting-grid.adoc\"\n      },\n      {\n        \"ref\": \"wireless-networking/creative-wireless-grid.adoc\"\n      },\n      {\n        \"ref\": \"wireless-networking/wireless-fluid-grid.adoc\"\n      },\n      {\n        \"ref\": \"wireless-networking/creative-wireless-fluid-grid.adoc\"\n      },\n      {\n        \"ref\": \"wireless-networking/wireless-crafting-monitor.adoc\"\n      },\n      {\n        \"ref\": \"wireless-networking/creative-wireless-crafting-monitor.adoc\"\n      },\n      {\n        \"ref\": \"wireless-networking/network-card.adoc\"\n      },\n      {\n        \"ref\": \"wireless-networking/network-receiver.adoc\"\n      },\n      {\n        \"ref\": \"wireless-networking/network-transmitter.adoc\"\n      }\n    ]\n  },\n  {\n    \"title\": \"Autocrafting\",\n    \"ref\": \"autocrafting/index.adoc\",\n    \"children\": [\n      {\n        \"ref\": \"autocrafting/getting-started-with-autocrafting.adoc\"\n      },\n      {\n        \"ref\": \"autocrafting/processing-recipes.adoc\"\n      },\n      {\n        \"ref\": \"autocrafting/keeping-items-in-stock.adoc\"\n      },\n      {\n        \"ref\": \"autocrafting/fluid-autocrafting.adoc\"\n      },\n      {\n        \"ref\": \"autocrafting/keeping-fluids-in-stock.adoc\"\n      },\n      {\n        \"ref\": \"autocrafting/autocrafting-with-filled-buckets.adoc\"\n      },\n      {\n        \"ref\": \"autocrafting/locking-and-unlocking.adoc\"\n      },\n      {\n        \"ref\": \"autocrafting/pattern-grid.adoc\"\n      },\n      {\n        \"ref\": \"autocrafting/pattern.adoc\"\n      },\n      {\n        \"ref\": \"autocrafting/crafter.adoc\"\n      },\n      {\n        \"ref\": \"autocrafting/crafting-monitor.adoc\"\n      },\n      {\n        \"ref\": \"autocrafting/crafter-manager.adoc\"\n      },\n      {\n        \"ref\": \"autocrafting/processing-pattern-encoder.adoc\"\n      }\n    ]\n  },\n  {\n    \"title\": \"Security\",\n    \"ref\": \"security/index.adoc\",\n    \"children\": [\n      {\n        \"ref\": \"security/security-manager.adoc\"\n      },\n      {\n        \"ref\": \"security/security-card.adoc\"\n      }\n    ]\n  },\n  {\n    \"title\": \"Upgrades\",\n    \"ref\": \"upgrades/index.adoc\",\n    \"children\": [\n      {\n        \"ref\": \"upgrades/upgrade.adoc\"\n      },\n      {\n        \"ref\": \"upgrades/range-upgrade.adoc\"\n      },\n      {\n        \"ref\": \"upgrades/speed-upgrade.adoc\"\n      },\n      {\n        \"ref\": \"upgrades/stack-upgrade.adoc\"\n      },\n      {\n        \"ref\": \"upgrades/crafting-upgrade.adoc\"\n      },\n      {\n        \"ref\": \"upgrades/regulator-upgrade.adoc\"\n      },\n      {\n        \"ref\": \"upgrades/fortune-upgrade.adoc\"\n      },\n      {\n        \"ref\": \"upgrades/silk-touch-upgrade.adoc\"\n      },\n      {\n        \"ref\": \"upgrades/interdimensional-upgrade.adoc\"\n      }\n    ]\n  },\n  {\n    \"title\": \"Utility\",\n    \"ref\": \"utility/index.adoc\",\n    \"children\": [\n      {\n        \"ref\": \"utility/quartz-enriched-iron.adoc\"\n      },\n      {\n        \"ref\": \"utility/block-of-quartz-enriched-iron.adoc\"\n      },\n      {\n        \"ref\": \"utility/silicon.adoc\"\n      },\n      {\n        \"ref\": \"utility/cut-silicon.adoc\"\n      },\n      {\n        \"ref\": \"utility/wrench.adoc\"\n      },\n      {\n        \"ref\": \"utility/cutting-tool.adoc\"\n      },\n      {\n        \"ref\": \"utility/filter.adoc\"\n      },\n      {\n        \"ref\": \"utility/processor-binding.adoc\"\n      },\n      {\n        \"ref\": \"utility/raw-basic-processor.adoc\"\n      },\n      {\n        \"ref\": \"utility/raw-improved-processor.adoc\"\n      },\n      {\n        \"ref\": \"utility/raw-advanced-processor.adoc\"\n      },\n      {\n        \"ref\": \"utility/basic-processor.adoc\"\n      },\n      {\n        \"ref\": \"utility/improved-processor.adoc\"\n      },\n      {\n        \"ref\": \"utility/advanced-processor.adoc\"\n      },\n      {\n        \"ref\": \"utility/construction-core.adoc\"\n      },\n      {\n        \"ref\": \"utility/destruction-core.adoc\"\n      },\n      {\n        \"ref\": \"utility/machine-casing.adoc\"\n      },\n      {\n        \"ref\": \"utility/solderer.adoc\"\n      },\n      {\n        \"ref\": \"utility/cover.adoc\"\n      },\n      {\n        \"ref\": \"utility/hollow-cover.adoc\"\n      }\n    ]\n  },\n  {\n    \"title\": \"Advanced usage\",\n    \"ref\": \"advanced-usage/index.adoc\",\n    \"children\": [\n      {\n        \"ref\": \"advanced-usage/commands.adoc\"\n      },\n      {\n        \"ref\": \"advanced-usage/profiling.adoc\"\n      },\n      {\n        \"ref\": \"advanced-usage/resource-packs.adoc\"\n      },\n      {\n        \"ref\": \"advanced-usage/translating-refined-storage.adoc\"\n      },\n      {\n        \"ref\": \"advanced-usage/using-development-builds.adoc\"\n      },\n      {\n        \"ref\": \"advanced-usage/using-the-api.adoc\"\n      }\n    ]\n  }\n]"
  },
  {
    "path": "docs/pages/advanced-usage/commands.adoc",
    "content": "= Commands\n\n[cols=\"1,1\"]\n|===\n|Refined Storage version|Command      |Explanation\n\n|v1.9.5 or higher        |`/refinedstorage disk create <player> <id>`|Creates a disk for a player by disk ID.\n|v1.9.5 or higher        |`/refinedstorage disk list`|Lists all disks on the server.\n|v1.9.5 or higher        |`/refinedstorage disk list <player>`|Lists all disks on the server, that the given player created.\n|v1.9.5 or higher        |`/refinedstorage network list <dimension>`|Lists all networks in a dimension, sorted by highest tick time first.\n|v1.9.5 or higher        |`/refinedstorage network get <dimension> <pos>`|Gets information about a network in a dimension and position.\n|v1.9.5 or higher        |`/refinedstorage network get <dimension> <pos> autocrafting list`|Gets all autocrafting tasks for a network.\n|v1.9.5 or higher        |`/refinedstorage network get <dimension> <pos> autocrafting get <id>`|Gets a specific autocrafting task in a network.\n|v1.9.5 or higher        |`/refinedstorage network get <dimension> <pos> autocrafting cancel`|Cancels all autocrafting tasks in a network.\n|v1.9.5 or higher        |`/refinedstorage network get <dimension> <pos> autocrafting cancel <id>`|Cancels a specific autocrafting task in a network.\n|v1.9.5 or higher        |`/refinedstorage pattern dump`|Dumps information about the currently held xref:../autocrafting/pattern.adoc[]. Meant for debugging purposes.\n|v1.6.x                  |`/createdisk`|See <<_createdisk>>.\n|===\n\n[#_createdisk]\n== `/createdisk`\n\n[.alert.alert-info]\n****\nThis command is only available for Minecraft 1.12.2 on Refined Storage version v1.6.x.\n****\n\nUse the `/createdisk` command to spawn in a disk with a given ID.\n\n=== Usage\n\n`/createdisk <player> <item> <metadata> <id>`\n\n==== Player\n\nThe player name to give the disk to.\n\n==== Item\n\nThe item ID of the storage disk.\nFor Refined Storage this would be `refinedstorage:storage_disk` (or `refinedstorage:fluid_storage_disk` for fluid disks).\n\n==== Metadata\n\nThe metadata value signifies the type of disk.\n\n**Items**\n\n[cols=\"1,1\"]\n|===\n|Disk type|Metadata value\n\n|1k|0\n|4k|1\n|16k|2\n|64k|3\n|Creative|4\n|===\n\n**Fluids**\n\n[cols=\"1,1\"]\n|===\n|Disk type|Metadata value\n\n|64k|0\n|256k|1\n|1024k|2\n|4096k|3\n|Creative|4\n|===\n\n==== ID\n\nThe ID parameter is the ID of the disk.\nA disk ID can be found by turning on advanced tooltips and checking the tooltip of the disk."
  },
  {
    "path": "docs/pages/advanced-usage/index.adoc",
    "content": "= Advanced usage\n\n- xref:commands.adoc[]\n- xref:profiling.adoc[]\n- xref:resource-packs.adoc[]\n- xref:translating-refined-storage.adoc[]\n- xref:using-development-builds.adoc[]\n- xref:using-the-api.adoc[]\n"
  },
  {
    "path": "docs/pages/advanced-usage/profiling.adoc",
    "content": "= Profiling\n\nIf you have a performance, it's best to make a `.nps` file that you can send to the developers so that they can investigate further.\n\n== Installing Sampler\n\nSampler is a mod by Player that generates .nps files.\nYou can download it from link:https://forum.industrial-craft.net/thread/10820[here].\n\n=== For Minecraft 1.12\n\nlink:http://files.player.to/sampler-1.73.jar[http://files.player.to/sampler-1.73.jar]\n\n=== For Minecraft 1.11\n\nlink:http://files.player.to/sampler-1.72.1.jar[http://files.player.to/sampler-1.72.1.jar]\n\n=== For Minecraft 1.10\n\nlink:http://files.player.to/sampler-1.69.3.jar[http://files.player.to/sampler-1.69.3.jar]\n\n== Running Sampler\n\nThen you can `/sampler start` and `/sampler stop` while it's lagging.\n\nThen a simple `/sampler export [name of exported nps file here]` will write out the .nps file that can be read by the developers in VisualVM.\n\n== Where to run Sampler?\n\n- Is it a performance on the server, like tick lag?\nRun Sampler *on the server*, NOT on your client!\n- Is it a performance on the client, like FPS lag?\nRun Sampler *on the client*, NOT on your server!\n"
  },
  {
    "path": "docs/pages/advanced-usage/resource-packs.adoc",
    "content": "= Resource packs\n\n== Color settings\n\nYou can change the text colors that Refined Storage uses in its GUIs by changing the `pack.mcmeta` file.\n\nExample:\n\n[source,json]\n----\n{\n  \"pack\": {\n    \"pack_format\": 4,\n    \"description\": \"An example\"\n  },\n  \"refinedstorage\": {\n    \"primary_color\": 11184810,\n    \"secondary_color\": 11184810\n  }\n}\n----\n\n`primary_color` is used for the GUI titles, `secondary_color` is used for all the rest.\n\nThe color is an integer representation of an RGBA color."
  },
  {
    "path": "docs/pages/advanced-usage/translating-refined-storage.adoc",
    "content": "= Translating Refined Storage\n\n== How to create a translation\n\nCopy link:https://github.com/refinedmods/refinedstorage/blob/develop/src/main/resources/assets/refinedstorage/lang/en_us.json[en_us.json] from Refined Storage GitHub repository to a text file on your computer and replace the texts with your language.\n\n== How to submit your translation\n\n* If you know Git well enough, you can contribute new language files via a pull request.\n* If you do not know how to use Git/GitHub, upload the translation file to Pastebin or Gist and send it to me through a link:https://github.com/refinedmods/refinedstorage/issues[GitHub issue].\n\n== Updating existing translations\n\nYou can compare the new and removed translation keys yourself, link:https://github.com/refinedmods/refinedstorage/blob/develop/tools/missing-translation-keys.sh[or use a Bash script] that outputs a diff between `en_US` and the version specified.\n\nYou can, of course, always diff manually using another tool, like the `diff` utility or an online diffing tool.\n"
  },
  {
    "path": "docs/pages/advanced-usage/using-development-builds.adoc",
    "content": "= Using development builds\n\nYou can use development builds straight from GitHub.\n\nFollow the following steps:\n\n- Head to the link:https://github.com/refinedmods/refinedstorage/actions/workflows/build.yml[list of builds].\n- Click on the commit that you want a build of.\n- Download \"Artifacts\".\n\n== Disclaimer\n\n- Using development builds is a risk!\n- It may contain untested code, bugs and crashes.\n- Remember to take backups."
  },
  {
    "path": "docs/pages/advanced-usage/using-the-api.adoc",
    "content": "= Using the API\n\n== For Minecraft 1.18.2 or later\n\nStarting from Minecraft 1.18, you can include the Refined Storage API in your development environment from 2 sources:\n\n=== GitHub packages\n\nAdd the following repository to your `build.gradle`:\n\n[source,groovy]\n----\nrepositories {\n    maven {\n        url = uri(\"https://maven.pkg.github.com/refinedmods/refinedstorage\")\n        credentials {\n            username = \"anything\"\n            password = \"\\u0067hp_oGjcDFCn8jeTzIj4Ke9pLoEVtpnZMP4VQgaX\"\n        }\n    }\n}\n----\n\nThe credentials are necessary because as of December 2021, GitHub packages still requires authentication for public packages.\nThe password used is a personal access token that has read access to the Refined Mods repositories.\nIt can be reused in other projects.\n\nSee:\n\n* https://github.community/t/download-from-github-package-registry-without-authentication/14407/38\n* https://github.community/t/download-from-github-package-registry-without-authentication/14407/44\n\nYou can find a list of versions on link:https://github.com/orgs/refinedmods/packages[GitHub packages].\n\n=== CreeperHost Maven\n\nAdd the following repository to your `build.gradle`:\n\n[source,groovy]\n----\nrepositories {\n    maven {\n        url = uri(\"https://maven.creeperhost.net\")\n    }\n}\n----\n\nYou can find a list of versions on the link:https://maven.creeperhost.net/com/refinedmods/refinedstorage[Maven index].\n\n**Warning:** Due to a bug in the Maven index on CreeperHost, new versions aren't included in the index.\nHowever, you can use them in your Gradle dependency.\n\nFor example, version `1.10.2` isn't included in the Maven index, but you can use `1.10.2` in your Gradle dependency when using CreeperHost Maven.\n\n== For older Minecraft versions\n\nSome Refined Storage API versions for older Minecraft versions are available on the link:https://maven.creeperhost.net/com/refinedmods/refinedstorage[CreeperHost Maven].\n\nHowever, not all of them are available.\nIf you need a specific version, build Refined Storage yourself and include the API manually.\n\n== Including the API\n\n[source,groovy]\n----\nimplementation fg.deobf(\"com.refinedmods:refinedstorage:VERSION_HERE\") {\n    transitive false\n}\n----\n\n== Using the API\n\nUse the `@RSAPIInject` annotation to get access to the API facade.\n\n[source,java]\n----\npublic class MyMod {\n    @RSAPIInject\n    public static IRSAPI RSAPI;\n}\n----\n\n== Javadoc\n\nUpdated Javadoc is available after every release link:https://refinedmods.com/javadoc/refinedstorage[here].\n"
  },
  {
    "path": "docs/pages/autocrafting/autocrafting-with-filled-buckets.adoc",
    "content": "= Autocrafting with filled buckets\n\nSome crafting recipes may require a filled fluid bucket.\nTo use fluids from your fluid storage to fill buckets, you can set up a xref:pattern.adoc#_processing[processing pattern] that has following inputs:\n\n- 1 empty bucket\n- 1000 mB of the fluid of your choice\n\nFor the output:\n\n- 1 filled bucket\n\nPut that in a xref:crafter.adoc[] that faces a bucket filling machine (link:https://teamcofh.com/docs/thermal-expansion/fluid-transposer/[that for example Thermal Expansion has]).\nRefined Storage will output the fluid from your fluid storage, and, an empty bucket.\nIt is up to the external machine to fill it."
  },
  {
    "path": "docs/pages/autocrafting/crafter-manager.adoc",
    "content": "= Crafter Manager\n:icon: crafter-manager.png\n:from: v1.5.33\n\nThe Crafter Manager is a block that allows you to see all your xref:pattern.adoc[patterns] in one GUI.\n\n== Naming\n\nAll the xref:pattern.adoc[patterns] are listed and categorized per xref:crafter.adoc[].\nThe categorization is based on the name of the xref:crafter.adoc[].\n\nTo decide which name a xref:crafter.adoc[] gets, the following rules (in order) are used:\n\n1. If the xref:crafter.adoc[] is renamed with a Minecraft link:https://minecraft.gamepedia.com/Anvil[Anvil], use that name\n2. If the xref:crafter.adoc[] is connected to a machine in the world, use the name of that machine\n3. Use \"Crafter\" as name\n\n== Sizes\n\nOne can configure the Crafter Manager size:\n\n- Stretched (default)\n- Small\n- Medium\n- Large\n\nWhen choosing the stretched size, the Crafter Manager will take up all the vertical screen space.\nThis can be limited through the `maxRowsStretch` config option.\n\ninclude::../../partials/search-box.adoc[]\n\ninclude::../../partials/recoloring.adoc[]"
  },
  {
    "path": "docs/pages/autocrafting/crafter.adoc",
    "content": "= Crafter\n:icon: crafter.png\n:from: v0.6.0-alpha\n\nThe {doctitle} is a block that crafts items with xref:pattern.adoc[patterns].\nIt can take xref:../upgrades/speed-upgrade.adoc[speed upgrades] to increase the crafting speed.\n\nWith processing xref:pattern.adoc[patterns], the {doctitle} has to face the correct input side of the machine.\n\n[#_chaining]\n== Chaining\n\nA {doctitle} can be chained by letting them face each other.\n\nThis is useful when connecting a {doctitle} to a single machine.\nWhen you run out of slots in your first {doctitle}, the one facing the machine, you can put another {doctitle} behind the first {doctitle} to get additional xref:pattern.adoc[] slots.\n\n== {doctitle} modes\n\nThe {doctitle} has 4 modes:\n\n- Ignore redstone signal (default)\n- Redstone signal unlocks autocrafting\n- Redstone signal locks autocrafting\n- Redstone pulse inserts next set\n\nThe (un)locking mechanism is used to block the {doctitle}, so it can't insert items or fluids into the connected inventory.\n\n\"Blocking mode\" can be achieved with the \"Redstone pulse inserts next set\" mode.\n\nSee xref:locking-and-unlocking.adoc[] for more details.\n\ninclude::../../partials/recoloring.adoc[]\n\n== Applicable upgrades\n\n- xref:../upgrades/speed-upgrade.adoc[]"
  },
  {
    "path": "docs/pages/autocrafting/crafting-monitor.adoc",
    "content": "= Crafting Monitor\n:icon: crafting-monitor.png\n:from: v0.6.0-alpha\n\nThe {doctitle} is a block that shows all the current running crafting tasks and how long they have been running.\n\nEach crafting task can be cancelled manually.\nIt is also possible to cancel all crafting tasks at once.\n\nPer task, it shows a grid of cells, each containing information about how an item or fluid is used in the crafting task.\nThis is what the terminology in those cells mean:\n\n- Stored: the item or fluid is stored in the internal inventory of the crafting task, and will be used later on\n- Missing: the crafting task cannot continue without this item or fluid as it's missing\n- Processing: the item or fluid displayed is currently inserted into an external machine and is processing\n- Scheduled: the item or fluid is scheduled to be made by inserting it's ingredients in an external machine later\n- Crafting: this item is being crafted (regular crafting, not processing)\n\n== Sizes\n\nThe size of any {doctitle} can be configured as well:\n\n- Stretched (default)\n- Small\n- Medium\n- Large\n\nWhen choosing the stretched size, the {doctitle} will take up all the vertical screen space.\nThis can be limited through the `maxRowsStretch` config option.\n\ninclude::../../partials/recoloring.adoc[]\n"
  },
  {
    "path": "docs/pages/autocrafting/fluid-autocrafting.adoc",
    "content": "= Fluid autocrafting\n\nSo far you've set up autocrafting for items.\nSince Refined Storage has support for xref:../storage/storing-fluids.adoc[storing fluids] as well, it speaks for itself that Refined Storage can also autocraft with fluids.\n\nEvery autocrafting pattern that uses fluids is a processing pattern.\nIf you forgot, a processing pattern is a xref:pattern.adoc[] that outputs items to an external inventory and expects an output back, as declared in the xref:pattern.adoc[].\n\nWith fluid autocrafting, you get the ability to make the xref:crafter.adoc[] output fluids (or items), and when the \"result\" fluid (or item) is back in the storage network, Refined Storage will detect the task and mark it as finished.\n\nThis means that you can also declare fluids as an output in the processing pattern.\nIt also means that you can request fluids from the xref:../viewing-resources/fluid-grid.adoc[].\n\nYou can mix fluid and item inputs/outputs freely.\n\n== Creation of the mixed pattern\n\nTo make a mixed (fluid or item) processing pattern, toggle the xref:pattern-grid.adoc[] in fluid or item mode.\n\nYou can then use link:https://minecraft.curseforge.com/projects/jei[JEI (Just Enough Items)] transfer to transfer item and fluid ingredients.\nYou can also use a filled fluid container (like a bucket) to specify the fluid.\n\nUse left or right click on the fluid slot to modify the millibuckets (mB).\n\n== Other resources\n\n- link:https://www.youtube.com/watch?v=6v-e_NdLEnI[Demo video]"
  },
  {
    "path": "docs/pages/autocrafting/getting-started-with-autocrafting.adoc",
    "content": "= Getting started with autocrafting\n\n== What is autocrafting?\n\nAutocrafting is automated crafting through Refined Storage.\n\nYou can already craft items manually using items from your storage network with the xref:../viewing-resources/crafting-grid.adoc[], but autocrafting makes it a tad bit easier and automated.\n\nInstead of manually moving items in the crafting matrix, you can make Refined Storage do all the work.\n\n== Patterns\n\nTo teach Refined Storage a recipe to craft we use a xref:pattern-grid.adoc[].\nThis xref:pattern-grid.adoc[] creates xref:pattern.adoc[patterns].\n\nA xref:pattern.adoc[] contains the recipe of the item you want to craft.\n\n== Pattern dependencies\n\nYou need to create a xref:pattern.adoc[] for each sub-item you want automatically crafted.\n\nRefined Storage will first try to extract the sub-item from your storage, but if it isn't available, it will fall back to the xref:pattern.adoc[] of the sub-item to know how to create it.\nIf there is no xref:pattern.adoc[] for the sub-item, the sub-item will be displayed as \"missing\" and the autocrafting task can't run.\n\n== Example\n\nYou want to autocraft link:https://minecraft.gamepedia.com/Chest[chests].\n\n- Create a xref:pattern.adoc[] for the chest\n- Create a xref:pattern.adoc[] for the wooden planks that are used to craft the chest\n- If you don't create the pattern, and you have wooden planks, than Refined Storage will be able to use those\n- If you run out of planks, Refined Storage will not know what to do\n- If you don't create the pattern, and you don't have wooden planks, than Refined Storage will not know how to craft this item and the crafting task can't\n\n== Exact mode\n\nExact mode is turned on by default which means every xref:pattern.adoc[] is an \"exact pattern\".\nThis means Refined Storage takes items exactly as defined in the xref:pattern.adoc[]\n\nWhen Exact mode is turned off it will also match for other acceptable inputs for that crafting recipe (other types of wood, etc).\n\n== Crafters\n\nOnce you created your xref:pattern.adoc[patterns], craft a xref:crafter.adoc[] and connect it to your storage network.\n\nIn those xref:crafter.adoc[crafters] you'll store all your xref:pattern.adoc[patterns].\n\n== Requesting an item\n\nAs soon as the relevant xref:pattern.adoc[patterns] to craft an item are stored in a xref:crafter.adoc[], you will be able to request the item through any xref:../viewing-resources/grid.adoc[].\n\nYou can do this by clicking on the item you want to autocraft.\nIf the item is already available and you want to request more of that item, you can use the CTRL + SHIFT key combination to open the crafting window.\n\nWhen requesting an item, Refined Storage will first ask how many of that item you want to craft.\nThen, it will show you what items it will take or craft.\n\nYou can't start an autocrafting task if you have insufficient resources, unless you have the ability to autocraft those resources.\n\n== How autocrafting works internally\n\nInitially, when the autocrafting task is started, all the \"initial\" needed items and fluids are extracted from the storage network and inserted into the internal storage of the autocrafting task (crafting storage).\n\nAll further actions to those items are performed in the internal storage, so the network doesn't \"see\" any changes while the task is running.\n\nBecause all the subcrafts are done in the internal storage, the storage network can not \"steal\" items from autocrafting tasks.\n\nWhen an item is inserted through an xref:../input-and-output/importer.adoc[] or xref:../input-and-output/interface.adoc[], it will first go through the internal storage of autocrafting.\nThat is prioritized.\nIf the autocrafting task deems the item or fluid as necessary, it will be intercepted and the storage network will receive nothing.\n\n== Monitoring your crafting tasks\n\nCraft a xref:crafting-monitor.adoc[] and connect it to your storage network to see how the crafting task is progressing.\n\nYou can also cancel autocrafting tasks from there.\n\nYou can also use a xref:../wireless-networking/wireless-crafting-monitor.adoc[] to see the running crafting tasks remotely from your inventory.\n\n== Managing your patterns in a convenient way\n\nWant a convenient way to access all your xref:pattern.adoc[patterns] in the xref:crafter.adoc[crafters] of your storage network?\nUse the xref:crafter-manager.adoc[].\n\n== Speeding up your crafting tasks\n\nInsert xref:../upgrades/speed-upgrade.adoc[speed upgrades] in the xref:crafter.adoc[crafters]."
  },
  {
    "path": "docs/pages/autocrafting/index.adoc",
    "content": "= Autocrafting\n\n- xref:getting-started-with-autocrafting.adoc[]\n- xref:processing-recipes.adoc[]\n- xref:keeping-items-in-stock.adoc[]\n- xref:fluid-autocrafting.adoc[]\n- xref:keeping-fluids-in-stock.adoc[]\n- xref:autocrafting-with-filled-buckets.adoc[]\n- xref:locking-and-unlocking.adoc[]\n- xref:pattern-grid.adoc[]\n- xref:pattern.adoc[]\n- xref:crafter.adoc[]\n- xref:crafting-monitor.adoc[]\n- xref:crafter-manager.adoc[]\n- xref:processing-pattern-encoder.adoc[]\n"
  },
  {
    "path": "docs/pages/autocrafting/keeping-fluids-in-stock.adoc",
    "content": "= Keeping fluids in stock\n\nKeeping fluids in stock work the same way as xref:keeping-items-in-stock.adoc[keeping items in stock].\n\nCreate a xref:../input-and-output/fluid-interface.adoc[] with a xref:../upgrades/crafting-upgrade.adoc[] in it.\nThen, specify the fluid that you want to keep in stock by clicking a fluid container (like a bucket) in the \"out\" slot.\nYou can change the amount by left or right clicking on the fluid.\nThe fluids will now be autocrafted if needed.\n\nTo make the stocked fluids available to your storage network, create an xref:../storage/external-storage.adoc[] and put it on the xref:../input-and-output/fluid-interface.adoc[].\nPut the xref:../storage/external-storage.adoc[] in fluid mode.\n\nMake sure the xref:../storage/external-storage.adoc[] is in \"extract-only\" mode.\nThat way, Refined Storage won't attempt to insert fluids in the xref:../input-and-output/fluid-interface.adoc[] that is meant for keeping in stock.\n"
  },
  {
    "path": "docs/pages/autocrafting/keeping-items-in-stock.adoc",
    "content": "= Keeping items in stock\n\nCreate an xref:../input-and-output/interface.adoc[] with a xref:../upgrades/crafting-upgrade.adoc[] in it.\nThen, specify the items that you want to keep in stock.\nThe items will now be autocrafted if needed.\n\nTo make the stocked items available to your storage network, create an xref:../storage/external-storage.adoc[] and put it on the xref:../input-and-output/interface.adoc[].\n\nMake sure the xref:../storage/external-storage.adoc[] is in \"extract-only\" mode.\nThat way, Refined Storage won't attempt to insert items in the xref:../input-and-output/interface.adoc[] that is meant for keeping in stock.\n"
  },
  {
    "path": "docs/pages/autocrafting/locking-and-unlocking.adoc",
    "content": "= Locking and unlocking\n:from: v1.6.6\n\nThe xref:crafter.adoc[] in Refined Storage supports locking mechanisms.\n\nLocking and unlocking a xref:crafter.adoc[] only applies to processing recipes.\n\nThe locking and unlocking functionality also has to be enabled by configuring the xref:crafter.adoc[] mode.\n\n== Crafter modes\n\n=== Ignore redstone signal (default)\n\nIgnores redstone signals.\nThis is the default.\n\n=== Redstone signal locks autocrafting\n\n- If a xref:crafter.adoc[] is locked, it can't insert items or fluids to the connected inventory.\n- If a xref:crafter.adoc[] is unlocked, it can insert items or fluids to the connected inventory.\n\n=== Redstone signal unlocks autocrafting\n\nThis is the opposite of the \"Redstone signal locks autocrafting\" mode.\n\n=== Redstone pulse inserts next set\n\nThis mode was primarily introduced to support a concept called \"blocking mode\".\n\nBlocking mode is primarily utilised for processing recipes, where the machine that does the processing can only handle 1 recipe at a time.\n\nIf the xref:crafter.adoc[] is in \"Redstone pulse inserts next set\" mode, this is the flow:\n\n- The xref:crafter.adoc[] will automatically go in an unlocked state\n- As soon as you request a recipe in this xref:crafter.adoc[], it will send out 1 set of items and fluids defined in the xref:pattern.adoc[]\n- The xref:crafter.adoc[] now goes in a locked state, and it won't push out any more items and fluids\n- The xref:crafter.adoc[] will stay locked until it receives a redstone pulse\n\nWhen you apply a redstone pulse:\n\n- The xref:crafter.adoc[] will unlock itself\n- The xref:crafter.adoc[] pushes the next set of items and fluids, if any\n- If there were any items and fluids to push, the xref:crafter.adoc[] will lock itself again\n\nGenerally, you'd apply a redstone signal if the recipe you're processing has completed.\nIt is up to the player to handle that.\n\n== Common mistakes with \"Redstone pulse inserts next set\"\n\n- Wrong redstone flow causes the xref:crafter.adoc[] to lock when it is supposed to unlock\n- When testing your contraption, accidentally locking the xref:crafter.adoc[] and then wondering why your xref:crafter.adoc[] doesn't process anything next time you request something\n\n=== Crafter deadlock\n\nIf you use an xref:../input-and-output/importer.adoc[] on a chest to import the final processed item, and also using a comparator to send the redstone signal to the xref:crafter.adoc[] to unlock again:\n\n- If the xref:../input-and-output/importer.adoc[] imports too fast AND\n- the comparator doesn't pick up the item being in the chest AND\n- by not picking up the item, thus, not sending out a redstone signal\n\nYou'd cause a deadlock because the xref:crafter.adoc[] doesn't receive a redstone pulse, and the xref:crafter.adoc[] would keep waiting forever.\n\nThe solution for this is to only enable the xref:../input-and-output/importer.adoc[] AFTER the redstone pulse is sent to the xref:crafter.adoc[].\nUse the xref:../input-and-output/importer.adoc[] redstone settings to achieve this.\n\n== Other resources\n\n- link:https://www.youtube.com/watch?v=c9s-IfDPKxw[Demo video]"
  },
  {
    "path": "docs/pages/autocrafting/pattern-grid.adoc",
    "content": "= Pattern Grid\n:icon: pattern-grid.png\n:from: v0.6.0-alpha\n\nThe {doctitle} is the same as a regular xref:../viewing-resources/grid.adoc[], but also allows for the creation of xref:pattern.adoc[patterns].\n\n== Mode\n\nBy default, the {doctitle} creates regular crafting xref:pattern.adoc[patterns].\n\nTo create processing xref:pattern.adoc[patterns], toggle the \"processing\" checkbox.\n\n== Allowed tags\n\nThe allowed tags system in Refined Storage allows the player to decide which items or fluids can be used as alternatives when the specified item or fluid isn't found in the storage network.\n\nThese tags are retrieved from link:https://minecraft.gamepedia.com/Tag[Minecraft's tag system].\nYou can specify the allowed tags in the {doctitle}.\n\nTo define valid alternatives for an item or fluid, use CTRL + click on the input slot and specify the allowed tags that can be used during autocrafting.\nItems or fluids from that tag are then marked as valid alternatives if the original item or fluid can't be found in the storage network.\n\nYou can also define valid alternatives by clicking on the item or fluid and then clicking on \"Alternatives\".\n\n== Ore dictionary (Refined Storage v1.6.x or lower only)\n\nTo create ore dictionary sensitive xref:pattern.adoc[patterns], toggle the \"oredict\" checkbox.\n\n== Modifying a pattern\n\nYou can re-insert a xref:pattern.adoc[] in the output slot to modify and (possibly) override it.\n\n== Recipe transferring\n\nThe {doctitle} integrates with link:https://minecraft.curseforge.com/projects/jei[JEI (Just Enough Items)] so the player can use recipe transferring.\n\nYou don't necessarily need the actual items in your storage network to create a xref:pattern.adoc[] for it.\n\nRefined Storage will notify you when you have a xref:pattern.adoc[] for an item configured when transferring a recipe.\n\n== Manual input/output configuration\n\nClick an item or fluid in the slots to configure the xref:pattern.adoc[].\n\nClick on the item or fluid to change the quantity.\n\nUse CTRL + click to modify the allowed tags for the input slot (Minecraft 1.14.4 and above).\n\nUse shift to clear the slot.\n\ninclude::../../partials/recoloring.adoc[]"
  },
  {
    "path": "docs/pages/autocrafting/pattern.adoc",
    "content": "= Pattern\n:icon: pattern.png\n:from: v0.6.0-alpha\n\nA {doctitle} is an item that is used in autocrafting.\nIt stores the recipe that should be autocrafted.\n\nA recipe can be assigned with the xref:pattern-grid.adoc[] and the {doctitle} is stored in a xref:crafter.adoc[].\n\n[#_processing]\n== Processing\n\nIf the {doctitle} is in processing mode, it will push the inputs to the connected inventory of the xref:crafter.adoc[].\n\n== Exact mode (patterns in crafting mode)\n\nExact mode is turned on by default which means every {doctitle} is an \"exact pattern\".\nThis means Refined Storage takes items exactly as defined in the {doctitle}.\n\nWhen Exact mode is turned off it will also match for other acceptable inputs for that crafting recipe.\n\nExact mode can't be set for patterns in processing mode.\nFor processing mode, see the section about allowed tags.\n\n== Allowed tags (patterns in processing mode)\n\nThe allowed tags system in Refined Storage allows the player to decide which items or fluids can be used as alternatives when the original specified item or fluid isn't found in the storage network.\n\nThese tags are retrieved from link:https://minecraft.gamepedia.com/Tag[Minecraft's tag system].\nYou can specify the allowed tags in the xref:pattern-grid.adoc[].\n\n== Ore dictionary mode (Refined Storage v1.6.x or lower only)\n\nThe {doctitle} can be configured to be an ore dictionary pattern.\nInstead of extracting the exact item, it'll try to extract equivalent items according to the ore dictionary as well.\n\n== Clearing\n\nUse SHIFT + right click in your inventory while holding the {doctitle} to clear it.\nYou can also override the {doctitle} in the xref:pattern-grid.adoc[].\n\n== Modifying\n\nYou can re-insert a {doctitle} in the output slot of the xref:pattern-grid.adoc[] to modify and (possibly) override it."
  },
  {
    "path": "docs/pages/autocrafting/processing-pattern-encoder.adoc",
    "content": "= Processing Pattern Encoder\n:icon: processing-pattern-encoder.png\n:from: v0.6.0-alpha\n:to: v1.5.6\n\n[.alert.alert-warning]\n****\nThe {doctitle} has been removed in v1.5.6 and its functionality has been moved to the xref:pattern-grid.adoc[].\n****\n\nA {doctitle} is used to create xref:pattern.adoc[patterns] meant for machine automation.\n\nIt takes up to 9 inputs and 9 outputs, so the storage network knows what to take and what to expect.\n\nThis block can't be connected to a storage network.\n\n== Recipe transferring\n\nThe {doctitle} integrates with link:https://minecraft.curseforge.com/projects/jei[JEI (Just Enough Items)] so the player can use recipe transferring.\n\nWhen using this, Refined Storage will use the inputs and outputs that the link:https://minecraft.curseforge.com/projects/jei[JEI] recipe has."
  },
  {
    "path": "docs/pages/autocrafting/processing-recipes.adoc",
    "content": "= Processing recipes\n\n== What are processing recipes?\n\nSo far, in xref:getting-started-with-autocrafting.adoc[] you learnt how to automate regular crafting recipes.\n\nWhat if you want to automate the creation of items that don't involve a crafting recipe, like ores to ingots in a furnace?\n\nFor this you use processing xref:pattern.adoc[patterns].\n\n== Processing patterns\n\nYou can create processing xref:pattern.adoc[patterns] in the xref:pattern-grid.adoc[] by toggling the \"processing\" checkbox.\n\nThe GUI will change and it'll allow you to define up to 9 inputs and outputs.\n\n- Inputs is what Refined Storage will extract from your storage network.\n- Outputs are what Refined Storage expects back in the network when the item has processed.\n\n== Example\n\nLet's say you want to automate link:https://minecraft.gamepedia.com/Iron_Ore[Iron Ore] to link:https://minecraft.gamepedia.com/Iron_Ingot[Iron Ingot].\n\n- In the input section you put 1 link:https://minecraft.gamepedia.com/Iron_Ore[Iron Ore].\n- In the output section you put 1 link:https://minecraft.gamepedia.com/Iron_Ingot[Iron Ingot].\n\n== Inserting the pattern\n\nMake a xref:crafter.adoc[] and let it face the machine in a way it can input it in the correct slot.\n\nInsert the processing xref:pattern.adoc[] you just created in the xref:crafter.adoc[] facing the machine.\n\nWhen you now request the item, Refined Storage will insert the inputs in the machine.\n\nYou do need to get the item manually back in the storage network so Refined Storage knows that the item has been processed.\nYou can use any device to get the item back in the storage network, like an xref:../input-and-output/interface.adoc[] or xref:../input-and-output/importer.adoc[].\n\n== Allowed tags\n\nThe allowed tags system in Refined Storage allows the player to decide which items or fluids can be used as alternatives when the original specified item or fluid isn't found in the storage network.\n\nThese tags are retrieved from Minecraft's tag system.\nYou can specify the allowed tags in the xref:pattern-grid.adoc[].\n\n== Chaining crafters\n\nYou can xref:crafter.adoc#_chaining[chain crafters] to connect multiple xref:crafter.adoc[crafters] to the same machine."
  },
  {
    "path": "docs/pages/faq.adoc",
    "content": "= Frequently asked questions (FAQ)\n\n== I have an idea for a feature that can be toggled on or off with an config option!\n\nRefined Storage doesn't do config options for features or things that change behavior in general.\nWhy not?\n\n- The experience players have with Refined Storage can differ between modpacks and that can be confusing\n- Issues will be created by players wondering why their favorite feature doesn't work in modpack A, but does in modpack B\n- Putting features or behaviors behind a config option makes it harder to maintain\n- With bug reports we'd have to ask if the feature is toggled on or off in the config\n- Bugs might get noticed later since it's behind a config option and thus less visible\n\n== Not including \"X\" in Refined Storage makes this mod useless when mods like \"Y\" aren't installed!\n\nThe philosophy of the mod is to have as less overlap with other mods and to only focus on the storage network part of the mod.\nIf other mods are required to achieve something, that isn't a problem.\n\nExamples:\n\n- Autocrafting needs an external bucket filling machine in order to convert fluids to buckets\n- Energy that Refined Storage uses needs to be generated with another mod\n\n== What is the difference between Refined Storage and Applied Energistics?\n\nRefined Storage is the simpler of the two and was heavily based off of AE1.\n\nAE2 has been around for years and was a direct descendent of AE1, while RS is much younger and started mostly scratch with AE (both versions) as inspiration.\n\nA lot of people prefer the simplicity of RS, while a similarly large portion of people prefer AE2's complexity due to enjoying the puzzle aspects.\n\n== Can I use this mod in my private/public mod pack?\n\nYes, you don't need to ask permission.\n\n== Can I connect Refined Storage to my Applied Energistics 2 system, or vice-versa?\n\nNo, you can't.\n\nYou might've found an issue on our issue tracker that says you can, but no, you can't.\n\n== Is there a Refined Storage for MC 1.7.10?\n\nNo, there isn't.\n\n== Will you make a Refined Storage for MC 1.7.10?\n\nNo, I won't.\n\n== Is there a way to have infinite Wireless Transmitter range?\n\nIt's not possible if you're using the base Refined Storage mod, or Refined Storage Addons.\nYou'll have to find an addon mod which does add such functionality.\n\nAlternatively, you can increase the range in the Refined Storage config file to be infinite.\n\n== Is there a way to request autocrafting in the Grid if I already have the item or fluid?\n\nYes!\nThere are many helpful key and mouse bindings for the xref:viewing-resources/grid.adoc#_controls[grid].\n\n== I found an issue/bug with Refined Storage!\n\nHead over to our link:https://github.com/refinedmods/refinedstorage/issues[issue tracker on GitHub] and report it there."
  },
  {
    "path": "docs/pages/getting-started.adoc",
    "content": "= Getting started\n\n== Core concepts\n\nRefined Storage is a storage mod where you can build a storage network made up of devices.\nThose devices manipulate your storage.\n\nIn this tutorial:\n\n- You'll craft a xref:storage/disk-drive.adoc[].\nA xref:storage/disk-drive.adoc[] can contain item or fluid storage disks.\nThose disks will provide your storage network with storage.\nIf you insert or extract an item, it will use the data on your disks.\n- You'll craft a xref:viewing-resources/grid.adoc[].\nThrough that block, you can modify your storage (which will modify the data on your disks).\n- Before crafting any of these devices, you'll first craft a xref:networking/controller.adoc[], which ties the entire network together.\n\n== A minimal setup\n\n=== Step 0: Install Refined Storage (if necessary)\n\nEnsure that the modpack that you are playing contains Refined Storage.\nYou can validate this by checking the modlist of your modpack.\n\nIf your modpack doesn't have Refined Storage installed, or you are creating your own modpack, xref:how-to-install.adoc[check the installation instructions here].\n\nIt might also be helpful to know that Refined Storage xref:how-to-install.adoc#_optional_dependencies[has integration with various other mods].\n\n=== Step 1: The Controller\n\nCraft the xref:networking/controller.adoc[].\nThe xref:networking/controller.adoc[] is the \"core\" of your storage network.\nYou'll be connecting all the Refined Storage devices to this block.\n\nThe xref:networking/controller.adoc[] needs energy.\nMore specifically, Forge Energy or RF.\nLots of mods that generate energy support this.\n\n=== Step 2: Storage and accessing your items\n\nCraft a xref:storage/disk-drive.adoc[] and a xref:storage/1k-storage-disk.adoc[] to store your items.\n\nYou can craft a higher tier of xref:storage/index.adoc#_storage_disks[storage disk], but for simplicity sake we're going for a 1k, which can store 1.000 items.\n\nPut the xref:storage/1k-storage-disk.adoc[] in the xref:storage/disk-drive.adoc[] and craft a xref:viewing-resources/grid.adoc[] to access your items.\n\nConnect those blocks to the xref:networking/controller.adoc[] with xref:networking/cable.adoc[], but you can also just place them next to each other in any direction.\n\n=== Step 3: Viewing your storage\n\nYou are now able to insert and extract items in the xref:viewing-resources/grid.adoc[].\n\n== Disks in block form\n\nYou can also use the various xref:storage/index.adoc#_storage_blocks[storage blocks] instead of xref:storage/index.adoc#_storage_disks[storage disks]."
  },
  {
    "path": "docs/pages/how-to-install.adoc",
    "content": "= How to install\n\nInstalling Refined Storage is the same as for any other Forge mod.\n\n== Setting up Forge\n\nYou'll need a working Forge instance to use Refined Storage.\nYou can use launchers like MultiMC or even the vanilla launcher to do this.\n\nInstructions for setting up a Forge instance are plenty online and are out of scope for this wiki.\n\n== Downloading the mod\n\nDownload a Refined Storage `.jar` file for your Minecraft version from official sources:\n\n- link:https://www.curseforge.com/minecraft/mc-mods/refined-storage[CurseForge]\n- link:https://modrinth.com/mod/refined-storage[Modrinth]\n- link:https://github.com/refinedmods/refinedstorage/releases[GitHub]\n\n== Installing the mod\n\nOnce you have the `.jar` file, place it in the `mods/` directory of your Forge instance.\nYou may have to start up your instance at least once so Forge can autogenerate the `mods/` directory.\n\n== CurseForge/Twitch launcher\n\nWhen you're using a launcher like the CurseForge/Twitch launcher, you can install Refined Storage in an instance with one click without having to copy over `.jar` files.\n\n== Configuring the mod\n\nChanging the configuration isn't needed in most cases.\nIf you need to do this, you can:\n\n- Change server-specific configuration in `saves/<your-world-name>/serverconfig/refinedstorage-server.toml`\n- Change client-specific configuration in `config/refinedstorage-client.toml`\n\nNote that server-specific configuration also applies to single player worlds.\nThat is because when you're playing single player, Minecraft uses an internal server.\n\n[#_optional_dependencies]\n== Optional dependencies\n\nRefined Storage can work perfectly by itself without any additional mods, but it's helpful to install a few other mods alongside it.\n\n- **link:https://minecraft.curseforge.com/projects/jei[JEI (Just Enough Items)]:** This mod will help you view the recipes of the various items and blocks in the mod.\n- **A mod that can generate Forge Energy (also known as FE or RF):** A Refined Storage network requires energy to run.\nIf you do not want to generate energy, you can disable energy usage in the Refined Storage server-side config (see section above \"Configuring the mod\").\nChange `useEnergy` under `[controller]` to `false`.\n- **link:https://www.curseforge.com/minecraft/mc-mods/crafting-tweaks[Crafting Tweaks]**\n- **link:https://www.curseforge.com/minecraft/mc-mods/curios[Curios]**\n- **link:https://www.curseforge.com/minecraft/mc-mods/inventory-sorter[Inventory Sorter]**\n\nUntil Minecraft 1.14, xref:opencomputers-api.adoc[Refined Storage had integration with OpenComputers].\n\n"
  },
  {
    "path": "docs/pages/index.adoc",
    "content": "= Refined Storage\n"
  },
  {
    "path": "docs/pages/index.html",
    "content": "<!DOCTYPE html>\n<html layout:decorate=\"~{layout.html}\">\n<head>\n    <title th:utext=\"${title}\"></title>\n</head>\n<body>\n<div layout:fragment=\"content\">\n    <main>\n        <div class=\"bg-body-tertiary mb-4 p-5 rounded-3 sect1\">\n            <h2>Refined Storage is a mass storage mod for Minecraft that offers the player a network-based storage\n                system, allowing them to store items and fluids on a massively expandable device network.</h2>\n            <hr>\n            <p>Items and fluids can be stored in one of the many storage capabilities that\n                the mod offers. Any storage devices connected to the same network are accessible to the player\n                through one simple Grid interface, allowing the player to access the inventories of many devices\n                through a single unified GUI.</p>\n            <p>This mod not only adds storage solutions, but also devices that can be used to\n                manipulate items and blocks in the world and from within the system, such as importers, exporters,\n                constructors, destructors, and more! There are also devices in this mod that allow the player to\n                setup auto-crafting, allowing the crafting of complex recipes in a few simple clicks.</p>\n            <a class=\"btn btn-primary btn-lg\"\n               th:href=\"@{'./' + ${currentComponent.slug} + '/' + ${currentComponent.latest ? '' : currentComponent.version.friendlyName() + '/'} + 'getting-started.html'}\"\n               role=\"button\">Get started</a>\n        </div>\n    </main>\n\n    <div class=\"btn-group btn-group-lg w-100\" role=\"group\" aria-label=\"Download\">\n        <a href=\"https://www.curseforge.com/minecraft/mc-mods/refined-storage\" class=\"btn btn-primary\">\n            <svg class=\"distribution-platform-logo\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"-2017 853 43 23\">\n                <path d=\"M-2005.7,853l0.7,3c-3.5,0-12,0-12,0s0.2,0.9,0.3,1c0.3,0.5,0.6,1.1,1,1.5c1.9,2.2,5.2,3.1,7.9,3.6 c1.9,0.4,3.8,0.5,5.7,0.6l2.2,5.9h1.2l0.7,1.9h-1l-1.7,5.5h16.7l-1.7-5.5h-1l0.7-1.9h1.2c0,0,1-6.1,4.1-8.9c3-2.8,6.7-3.2,6.7-3.2 V853H-2005.7z M-1988.9,868.1c-0.8,0.5-1.7,0.5-2.3,0.9c-0.4,0.2-0.6,0.8-0.6,0.8c-0.4-0.9-0.9-1.2-1.5-1.4 c-0.6-0.2-1.7-0.1-3.2-1.4c-1-0.9-1.1-2.1-1-2.7v-0.1c0-0.1,0-0.1,0-0.2s0-0.2,0.1-0.3l0,0l0,0c0.2-0.6,0.7-1.2,1.7-1.6 c0,0-0.7,1,0,2c0.4,0.6,1.2,0.9,1.9,0.5c0.3-0.2,0.5-0.6,0.6-0.9c0.2-0.7,0.2-1.4-0.4-1.9c-0.9-0.8-1.1-1.9-0.5-2.6 c0,0,0.2,0.9,1.1,0.8c0.6,0,0.6-0.2,0.4-0.4c-0.1-0.3-1.4-2.2,0.5-3.6c0,0,1.2-0.8,2.6-0.7c-0.8,0.1-1.7,0.6-2,1.4c0,0,0,0,0,0.1 c-0.3,0.8-0.1,1.7,0.5,2.5c0.4,0.6,0.9,1.1,1.1,1.9c-0.3-0.1-0.5,0-0.7,0.2c-0.2,0.2-0.3,0.6-0.2,0.9c0.1,0.2,0.3,0.4,0.5,0.4 c0.1,0,0.1,0,0.2,0h0.1c0.3-0.1,0.5-0.5,0.4-0.8c0.2,0.2,0.3,0.7,0.2,1c0,0.3-0.2,0.6-0.3,0.8c-0.1,0.2-0.3,0.4-0.4,0.6 s-0.2,0.4-0.2,0.6c0,0.2,0,0.5,0.1,0.7c0.4,0.6,1.2,0,1.4-0.5c0.3-0.6,0.2-1.3-0.2-1.9c0,0,0.7,0.4,1.2,1.8 C-1987.4,866.2-1988.1,867.6-1988.9,868.1z\"></path>\n            </svg>\n            <span class=\"d-none d-lg-inline\"> Download on</span> CurseForge\n        </a>\n        <a href=\"https://modrinth.com/mod/refined-storage\" class=\"btn btn-primary\">\n            <svg class=\"distribution-platform-logo\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 514\">\n                <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n                      d=\"M503.16 323.56C514.55 281.47 515.32 235.91 503.2 190.76C466.57 54.2299 326.04 -26.8001 189.33 9.77991C83.8101 38.0199 11.3899 128.07 0.689941 230.47H43.99C54.29 147.33 113.74 74.7298 199.75 51.7098C306.05 23.2598 415.13 80.6699 453.17 181.38L411.03 192.65C391.64 145.8 352.57 111.45 306.3 96.8198L298.56 140.66C335.09 154.13 364.72 184.5 375.56 224.91C391.36 283.8 361.94 344.14 308.56 369.17L320.09 412.16C390.25 383.21 432.4 310.3 422.43 235.14L464.41 223.91C468.91 252.62 467.35 281.16 460.55 308.07L503.16 323.56Z\"/>\n                <path d=\"M321.99 504.22C185.27 540.8 44.7501 459.77 8.11011 323.24C3.84011 307.31 1.17 291.33 0 275.46H43.27C44.36 287.37 46.4699 299.35 49.6799 311.29C53.0399 323.8 57.45 335.75 62.79 347.07L101.38 323.92C98.1299 316.42 95.39 308.6 93.21 300.47C69.17 210.87 122.41 118.77 212.13 94.7601C229.13 90.2101 246.23 88.4401 262.93 89.1501L255.19 133C244.73 133.05 234.11 134.42 223.53 137.25C157.31 154.98 118.01 222.95 135.75 289.09C136.85 293.16 138.13 297.13 139.59 300.99L188.94 271.38L174.07 231.95L220.67 184.08L279.57 171.39L296.62 192.38L269.47 219.88L245.79 227.33L228.87 244.72L237.16 267.79C237.16 267.79 253.95 285.63 253.98 285.64L277.7 279.33L294.58 260.79L331.44 249.12L342.42 273.82L304.39 320.45L240.66 340.63L212.08 308.81L162.26 338.7C187.8 367.78 226.2 383.93 266.01 380.56L277.54 423.55C218.13 431.41 160.1 406.82 124.05 361.64L85.6399 384.68C136.25 451.17 223.84 484.11 309.61 461.16C371.35 444.64 419.4 402.56 445.42 349.38L488.06 364.88C457.17 431.16 398.22 483.82 321.99 504.22Z\"/>\n            </svg>\n            <span class=\"d-none d-lg-inline\"> Download on</span> Modrinth\n        </a>\n        <a href=\"https://github.com/refinedmods/refinedstorage/releases\" class=\"btn btn-primary\">\n            <i class=\"bi bi-github\"></i>\n            <span class=\"d-none d-lg-inline\"> Download on</span> GitHub\n        </a>\n    </div>\n\n    <div class=\"card-group mt-4\">\n        <div class=\"card\"\n             th:each=\"article, articleStat : ${articles}\"\n             th:if=\"${articleStat.index < 3}\">\n            <div class=\"card-body\">\n                <h5 class=\"card-title\" th:text=\"${article.title}\"></h5>\n                <p class=\"card-text\" th:text=\"${article.description}\"></p>\n                <a class=\"btn btn-primary\"\n                   th:href=\"@{'./' + ${currentComponent.slug} + '/' + ${currentComponent.latest ? '' : currentComponent.version.friendlyName() + '/'} + ${article.url}}\">\n                    Read more <i class=\"bi bi-chevron-right\"></i>\n                </a>\n            </div>\n            <div class=\"card-footer bg-body-tertiary\">\n                <small class=\"text-body-secondary\">\n                    <i class=\"bi bi-clock\"></i> <span th:text=\"${#temporals.format(article.date, 'yyyy-MM-dd')}\"></span>\n                </small>\n            </div>\n        </div>\n    </div>\n\n    <div class=\"container bg-body-tertiary rounded-3 my-5 mt-4 pt-4\">\n        <div class=\"row g-4 p-5 row-cols-1 row-cols-lg-3\">\n            <div class=\"col\">\n                <h2 class=\"h4\"><i class=\"bi bi-discord\"></i> Need help?</h2>\n                <p>Join our Discord server for community support.</p>\n                <a href=\"https://discordapp.com/invite/VYzsydb\" class=\"icon-link d-inline-flex align-items-center\">\n                    Join our Discord server\n                    <i class=\"bi bi-chevron-right\"></i>\n                </a>\n            </div>\n            <div class=\"col\">\n                <h2 class=\"h4\"><i class=\"bi bi-bug-fill\"></i> Found a problem?</h2>\n                <p>Issues can be reported on our issue tracker.</p>\n                <a href=\"https://github.com/refinedmods/refinedstorage/issues\"\n                   class=\"icon-link d-inline-flex align-items-center\">\n                    Refined Storage on GitHub\n                    <i class=\"bi bi-chevron-right\"></i>\n                </a>\n            </div>\n            <div class=\"col\">\n                <h2 class=\"h4\"><i class=\"bi bi-rss-fill\"></i> Want to stay up to date?</h2>\n                <p>Follow us on X to stay up to date with Refined Mods news and releases.</p>\n                <a href=\"https://x.com/refinedmods\" class=\"icon-link d-inline-flex align-items-center\">\n                    Follow @refinedmods on X\n                    <i class=\"bi bi-chevron-right\"></i>\n                </a>\n            </div>\n        </div>\n    </div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "docs/pages/input-and-output/constructor.adoc",
    "content": "= Constructor\n:icon: constructor.png\n:from: v0.3.0-alpha\n\nThe {doctitle} places items or fluids from the storage network in the world.\n\nNo other blocks can be in front of the {doctitle} (except fluids) and it should be possible for the block to be placed (for example: saplings need dirt).\n\nThe {doctitle} can also drop items in the world instead of placing actual blocks.\nWhen provided with a xref:../upgrades/stack-upgrade.adoc[], it'll drop stacks of items at a time.\n\n== Applicable upgrades\n\n- xref:../upgrades/speed-upgrade.adoc[]\n- xref:../upgrades/stack-upgrade.adoc[]\n- xref:../upgrades/crafting-upgrade.adoc[]\n"
  },
  {
    "path": "docs/pages/input-and-output/destructor.adoc",
    "content": "= Destructor\n:icon: destructor.png\n:from: v0.3.0-alpha\n\nThe {doctitle} destroys blocks or fluids in front of it and puts the drops in the storage network.\n\nThe {doctitle} has the ability to only break certain blocks or fluids, with the whitelist and blacklist option.\nSaid whitelist and blacklist can be NBT or damage sensitive.\n\nThe {doctitle} can also pick up items in the world instead of destroying blocks.\n\n== Applicable upgrades\n\n- xref:../upgrades/speed-upgrade.adoc[]\n- xref:../upgrades/fortune-upgrade.adoc[]\n- xref:../upgrades/silk-touch-upgrade.adoc[]\n"
  },
  {
    "path": "docs/pages/input-and-output/disk-manipulator.adoc",
    "content": "= Disk Manipulator\n:icon: disk-manipulator.png\n:from: v1.0.5\n\nThe {doctitle} is a block that adds a fast way of transferring items between xref:../storage/index.adoc#_storage_disks[storage disks] or xref:../storage/index.adoc#_fluid_storage_disks[fluid storage disks] and the storage network.\n\n== Whitelist or blacklist\n\nThe player can configure the {doctitle} to have a certain whitelist or blacklist of items that can be transferred.\n\nThe whitelist or blacklist can be configured to be NBT or damage sensitive.\n\n== Mode\n\nThe player can also choose whether to insert items to the storage network or extract items from the storage network.\n\ninclude::../../partials/recoloring.adoc[]\n\n== Applicable upgrades\n\n- xref:../upgrades/speed-upgrade.adoc[]\n- xref:../upgrades/stack-upgrade.adoc[]"
  },
  {
    "path": "docs/pages/input-and-output/exporter.adoc",
    "content": "= Exporter\n:icon: exporter.png\n:from: v0.3.0-alpha\n\nThe {doctitle} extracts items or fluids from the storage network and inserts it in the inventory or tank in front of it.\n\nBefore being able to export anything, the player has to choose the items or fluids to export.\n\nThe chosen items can be configured to be NBT or damage sensitive.\n\nThe {doctitle} should face the block it's exporting to in a way that the wanted slot or fluid tank is possible to reach from that side.\n\n== Applicable upgrades\n\n- xref:../upgrades/speed-upgrade.adoc[]\n- xref:../upgrades/stack-upgrade.adoc[]\n- xref:../upgrades/crafting-upgrade.adoc[]\n- xref:../upgrades/regulator-upgrade.adoc[]\n"
  },
  {
    "path": "docs/pages/input-and-output/fluid-interface.adoc",
    "content": "= Fluid Interface\n:icon: fluid-interface.png\n:from: v0.9.0-beta\n\nThe {doctitle} is the same as an xref:interface.adoc[] but for fluids.\n\nIt has 2 internal tanks, one for input and one for output.\n\n== Input slot\n\nThe {doctitle} has an input slot to import the contents of fluid containers (like a filled bucket).\n\nYou can also interact with the input tank by using pipes from other mods.\n\n== Output configuration\n\n- Click a fluid container (like a filled bucket) in the \"Out\" slot to configure the output fluid.\n- Use left or right click on the fluid to change the mB amount.\n- Use shift to clear the fluid slot.\n- You can also interact with the output tank by using pipes from other mods.\n\n== Applicable upgrades\n\n- xref:../upgrades/speed-upgrade.adoc[]\n- xref:../upgrades/stack-upgrade.adoc[]\n- xref:../upgrades/crafting-upgrade.adoc[]"
  },
  {
    "path": "docs/pages/input-and-output/getting-items-in-and-out.adoc",
    "content": "= Getting items in and out\n\nSo far, you know xref:../getting-started.adoc[how to add storage disks to your network and view them].\nBut how do you get those items in and out in an automated way?\n\nThis is a quick overview of all the devices that manipulate your storage.\n\n== Exporter\n\nIf you want to get items out of your storage network, use an xref:exporter.adoc[] and connect it to an inventory where you want to export to.\n\nConfigure the filter slots of the xref:exporter.adoc[] to the items you want to export.\n\n== Importer\n\nIf you want to get items in your storage network, use an xref:importer.adoc[] and connect it to an inventory where you want to import from.\n\n== Interface\n\nWant the best of both worlds?\nUse an xref:interface.adoc[] to get importing and exporting functionality in one block.\n\n== Constructor\n\nTo place blocks from your storage network in the world, use an xref:constructor.adoc[].\n\nConfigure the filter slots of the xref:constructor.adoc[] to the block you want to place.\n\n== Destructor\n\nTo destroy and insert blocks from the world into your storage, use an xref:destructor.adoc[].\n\nYou can configure a whitelist or blacklist of blocks to destroy.\n\n== Disk Manipulator\n\nIf you want to import from disks or export to a disk from the network, use a xref:disk-manipulator.adoc[]."
  },
  {
    "path": "docs/pages/input-and-output/importer.adoc",
    "content": "= Importer\n:icon: importer.png\n:from: v0.3.0-alpha\n\nThe {doctitle} imports items or fluids from an inventory in front of the block and inserts it in the storage network (if there is space).\n\nBy default, it will import all accessible slots (place the {doctitle} on the correct side, where the slot or fluid tank is reachable) but the player can use the whitelist or blacklist as well.\n\n== Whitelist and blacklist\n\nThere is also a whitelist and blacklist option to only allow or forbid some items from entering the storage network.\n\nThe whitelist or blacklist can be configured to be NBT or damage sensitive.\n\n== Applicable upgrades\n\n- xref:../upgrades/speed-upgrade.adoc[]\n- xref:../upgrades/stack-upgrade.adoc[]"
  },
  {
    "path": "docs/pages/input-and-output/index.adoc",
    "content": "= Input and output\n\n- xref:getting-items-in-and-out.adoc[]\n- xref:importer.adoc[]\n- xref:exporter.adoc[]\n- xref:constructor.adoc[]\n- xref:destructor.adoc[]\n- xref:interface.adoc[]\n- xref:fluid-interface.adoc[]\n- xref:disk-manipulator.adoc[]\n- xref:reader.adoc[]\n- xref:writer.adoc[]"
  },
  {
    "path": "docs/pages/input-and-output/interface.adoc",
    "content": "= Interface\n:icon: interface.png\n:from: v0.4.0-alpha\n\nThe Interface is a block that acts as a combination of the xref:importer.adoc[] and the xref:exporter.adoc[].\n\n== Importing\n\nLet's talk about the difference between an xref:importer.adoc[] and the Interface for importing.\n\nThe xref:importer.adoc[] needs to be connected to an inventory to import items or fluids.\nIt has no internal inventory and you can't insert items directly to the xref:importer.adoc[.\n\nIn comparison with the xref:importer.adoc[] the Interface has an internal inventory to receive items and import them (through piping, hoppers, etc).\nThat internal inventory is accessible by opening the GUI and looking at the slots under \"Interface Import\").\n\nThe Interface does NOT extract items from adjacent inventories automatically, you have to actually insert them in the Interface through piping, hoppers, etc.\n\n== Exporting\n\nThere is also an option for exporting items from the system.\nThese items can be piped out through a piping system from another mod, hoppers, etc.\n\nIt can be configured to be NBT or damage sensitive.\n\n== Output configuration\n\n- Click an item in the export slots to configure that to be exported.\n- Use left or right click on the item to change the amount.\n- Use shift to clear the slot.\n\n== Applicable upgrades\n\n- xref:../upgrades/speed-upgrade.adoc[]\n- xref:../upgrades/stack-upgrade.adoc[]\n- xref:../upgrades/crafting-upgrade.adoc[]"
  },
  {
    "path": "docs/pages/input-and-output/reader.adoc",
    "content": "= Reader\n:icon: reader.png\n:from: v1.4.0-beta\n:to: v1.7.0-alpha\n\n[.alert.alert-warning]\n****\nThe {doctitle} has been removed in version v1.7.0-alpha.\n****\n\nA Reader has the ability to manage {doctitle} / xref:writer.adoc[] channels on a network.\n\nThe {doctitle} is a block that takes items, fluids, energy and / or a redstone signal.\nThe data will be transmitted to the configured channel and can be read out with a xref:writer.adoc[].\n\nThe {doctitle} doesn't auto-extract any of the supported types (with an exception to redstone signals).\nYou have to insert it manually.\n\n== Supported types\n\n- Items\n- Fluids\n- Energy\n- Redstone"
  },
  {
    "path": "docs/pages/input-and-output/writer.adoc",
    "content": "= Writer\n:icon: writer.png\n:from: v1.4.0-beta\n:to: v1.7.0-alpha\n\n[.alert.alert-warning]\n****\nThe {doctitle} has been removed in version v1.7.0-alpha.\n****\n\nA {doctitle} has the ability to manage xref:reader.adoc[] / {doctitle} channels on a network.\n\nThe {doctitle} is a block that exposes items, fluids, energy and / or a redstone signal from the bound channel.\nThe data that is received is sent from the xref:reader.adoc[].\n\nThe {doctitle} doesn't auto-push any of the supported types (with an exception to redstone signals).\nYou have to extract it manually.\n\n== Supported types\n\n- Items\n- Fluids\n- Energy\n- Redstone"
  },
  {
    "path": "docs/pages/need-help.adoc",
    "content": "= Need help?\n\n== Supported versions\n\nBefore creating an issue on our issue tracker, ensure that your version is still supported.\n\n[cols=\"1,1,1,1,1\"]\n|===\n|Minecraft version|Refined Storage version range|State|New features|Bugfixes\n\n|Minecraft 1.20.x|v1.12.x - v1.13.x|Maintained|❌|✔️\n|Minecraft 1.19.x|v1.11.x|Maintained|❌|✔️\n|Minecraft 1.18.x|v1.10.x|Maintained|❌|✔️\n|Minecraft 1.17.x|-|Never available|❌|❌\n|Minecraft 1.16.x|v1.9.x|Unmaintained|❌|❌\n|Minecraft 1.15.x|v1.8.x|Unmaintained|❌|❌\n|Minecraft 1.14.x|v1.7.x |Unmaintained|❌|❌\n|Minecraft 1.13.x|-|Never available|❌|❌\n|Minecraft 1.12.x|v1.5.x - v1.6.x|Unmaintained|❌|❌\n|Minecraft 1.11.x|v1.3.x - v1.4.x|Unmaintained|❌|❌\n|Minecraft 1.10.x|v0.8.x - v1.2.x|Unmaintained|❌|❌\n|Minecraft 1.9.x|v0.3.x - v0.7.x|Unmaintained|❌|❌\n|Minecraft 1.8.x|-|Never available|❌|❌\n|Minecraft 1.7.x|-|Never available|❌|❌\n|===\n\nRefined Storage v1.x will not be gaining new features as we are building link:https://github.com/refinedmods/refinedstorage2[Refined Storage 2].\n"
  },
  {
    "path": "docs/pages/need-help.html",
    "content": "<!DOCTYPE html>\n<html layout:decorate=\"~{layout.html}\">\n<head>\n    <title th:utext=\"${title}\"></title>\n</head>\n<body>\n<div layout:fragment=\"content\">\n    <main>\n        <div class=\"container bg-body-tertiary rounded-3 mb-4 mt-4 pt-4\">\n            <div class=\"row g-4 p-5 row-cols-1 row-cols-lg-3\">\n                <div class=\"col\">\n                    <h2 class=\"h4\"><i class=\"bi bi-discord\"></i> Have a question?</h2>\n                    <p>Join our Discord server for community support.</p>\n                    <a href=\"https://discordapp.com/invite/VYzsydb\" class=\"icon-link d-inline-flex align-items-center\">\n                        Join our Discord server\n                        <i class=\"bi bi-chevron-right\"></i>\n                    </a>\n                </div>\n                <div class=\"col\">\n                    <h2 class=\"h4\"><i class=\"bi bi-bug-fill\"></i> Found a bug, crash or other problem?</h2>\n                    <p>Issues can be reported on our issue tracker.</p>\n                    <a href=\"https://github.com/refinedmods/refinedstorage/issues\"\n                       class=\"icon-link d-inline-flex align-items-center\">\n                        Refined Storage on GitHub\n                        <i class=\"bi bi-chevron-right\"></i>\n                    </a>\n                </div>\n                <div class=\"col\">\n                    <h2 class=\"h4\"><i class=\"bi bi-rss-fill\"></i> Want to stay up to date?</h2>\n                    <p>Follow us on X to stay up to date with Refined Mods news and releases.</p>\n                    <a href=\"https://x.com/refinedmods\" class=\"icon-link d-inline-flex align-items-center\">\n                        Follow @refinedmods on X\n                        <i class=\"bi bi-chevron-right\"></i>\n                    </a>\n                </div>\n            </div>\n        </div>\n\n        <div th:utext=\"${content}\" th:remove=\"tag\">\n        </div>\n    </main>\n</div>\n</body>\n</html>"
  },
  {
    "path": "docs/pages/networking/cable.adoc",
    "content": "= Cable\n:from: v0.3.0-alpha\n:icon: cable.png\n\n{doctitle} is used to connect devices to the xref:controller.adoc[].\n\nThey are not always necessary, as long as the devices are next to each other in any direction a connection will be established as well.\n"
  },
  {
    "path": "docs/pages/networking/controller.adoc",
    "content": "= Controller\n:from: v0.3.0-alpha\n:icon: controller.png\n\nThe {doctitle} is the core of the Refined Storage network.\nYou need to connect all the Refined Storage devices to this block.\n\n== Connecting devices\n\nYou are supposed to connect every device that depends on the storage network connection to the {doctitle}.\n\nYou can connect devices with xref:cable.adoc[cables].\n\nxref:cable.adoc[Cables] are not always necessary, as long as the devices are next to each other in any direction a connection will be established as well.\n\n== Energy\n\nThe {doctitle} accepts and consumes Forge Energy (FE).\nMost mods have a way to generate energy, therefore Refined Storage doesn't come by itself with a way to generate energy.\n\n- The energy is extracted per tick.\n- The amount of energy that is extracted depends on the amount of devices, and which devices.\n- Every device type consumes another amount of energy.\n- You can see how many energy each device consumes by right clicking the {doctitle}.\n\nIf the {doctitle} runs out of energy, the network will be turned off until there is sufficient energy provided again.\n\nWhen the {doctitle} is broken, it will maintain its energy.\n\n== Limits\n\nEach Refined Storage network can only have a single {doctitle}.\nIt doesn't make sense to connect multiple controllers on the same network.\n\nIf you connect another {doctitle} to an already existing network, the {doctitle} will break as an item in the world.\n\ninclude::../../partials/recoloring.adoc[]"
  },
  {
    "path": "docs/pages/networking/creative-controller.adoc",
    "content": "= Creative Controller\n:from: v0.3.0-alpha\n:icon: controller.png\n\nThe {doctitle} is the same as a regular xref:controller.adoc[] but has infinite energy.\n\nIt can only be obtained in creative mode.\n\ninclude::../../partials/recoloring.adoc[]\n"
  },
  {
    "path": "docs/pages/networking/detector.adoc",
    "content": "= Detector\n:icon: detector.png\n:from: v0.3.0-alpha\n\nThe {doctitle} is a block that emits a redstone signal if an item, or fluid count matches a given amount.\n\nIt is also possible to be NBT or damage sensitive.\n\n== Types of criteria\n\n[cols=\"1,1\"]\n|===\n|Criteria|Explanation\n\n|<|Emits a signal when lower than the given amount\n|>|Emits a signal when higher than the given amount\n|=|Emits a signal when equal to the given amount\n|===\n\n== Checking the total count in the storage\n\nWhen no item/fluid, is specified, the criteria won't care about the count of a specific item/fluid, but rather the count of all items/fluids, in the storage.\n\n== Amounts in fluid mode\n\nWhen the {doctitle} is in fluid mode, the amount given is in millibuckets (mB).\n\nIf you want to check for 1 bucket of a fluid, use 1000, not 1.\n\ninclude::../../partials/recoloring.adoc[]\n"
  },
  {
    "path": "docs/pages/networking/index.adoc",
    "content": "= Networking\n\n- xref:controller.adoc[]\n- xref:creative-controller.adoc[]\n- xref:cable.adoc[]\n- xref:detector.adoc[]\n- xref:relay.adoc[]"
  },
  {
    "path": "docs/pages/networking/relay.adoc",
    "content": "= Relay\n:from: v0.4.0-alpha\n:icon: relay.png\n\nThe Relay acts as xref:cable.adoc[], but can be turned on or off depending on the redstone configuration.\n\nDevices connected after the Relay will be on or off depending if the {doctitle} is on.\n\ninclude::../../partials/recoloring.adoc[]"
  },
  {
    "path": "docs/pages/news/20210518-announcing-refined-storage-2.adoc",
    "content": "= Announcing Refined Storage 2\n:type: article\n:description: A new major version of Refined Storage is in the works.\n:date: 2021-05-18\n\nSince October 2020 I've silently been working on and off on a new major version of Refined Storage. This version is a complete rewrite with an extra focus on quality.\n\nThe mod is over 5 years old at this point and the code is starting to show its age. I don't think that there is any original code remaining from 2015 as it has been refactored constantly over the years, but now feels like a good moment to start over.\n\nThe biggest problem with the current version of the mod is that while it works, the code quality isn't that good. There are no tests and the structure/architecture isn't that sane. That makes it hard to keep adding features and to support the mod on the long term, due to regressions and bugs.\n\nI've learned a lot the past few years. I started Refined Storage when I was a kid in high school, now I'm a software engineer by trade. I want the code to be as good as possible so that I can keep enjoying working on it.\n\nRewriting a mod the size of Refined Storage can be a huge trap and could very well fail due to the effort required, but I feel like this is required to secure the future of the mod.\n\nThe mod is being rewritten with an enhanced focus on quality (that's why it is taking so long!) and to be modloader independent.\n\nIn terms of features the mod will largely stay the same. There will be some subtle differences here and there, but nothing too huge. See it as a new coat of paint.\n\nBecause I'm working full-time, I have to divide my time better. Time is the most precious thing in life and in my free time I want to work on things that I enjoy the most. Working on Refined Storage 2 gives me the most enjoyment, so most time will be going to that.\n"
  },
  {
    "path": "docs/pages/news/20220704-a-big-milestone-for-refined-storage-2.adoc",
    "content": "= A big milestone for Refined Storage 2\n:type: article\n:description: The first milestone for Refined Storage 2 has been completed.\n:date: 2022-07-04\n\nAfter almost 2 years of development, link:https://github.com/refinedmods/refinedstorage2/milestone/1?closed=1[the first milestone for Refined Storage 2 has been completed].\n\nFinishing the first milestone is a big deal. Important architectural decisions have been made to lay a solid foundation for further milestones and content.\n\nYou can track the progress in the following locations:\n\n* link:https://github.com/orgs/refinedmods/projects/6[The project board]\n* link:https://github.com/refinedmods/refinedstorage2/milestones[The list of milestones]\n* link:https://github.com/refinedmods/refinedstorage2[The GitHub repository]\n"
  },
  {
    "path": "docs/pages/news/20230707-a-week-of-modding.adoc",
    "content": "= A week of modding\n:type: article\n:description: A week of modding for Refined Storage 1.x, Refined Storage Addons, and Ranged Pumps.\n:date: 2023-07-07\n\nThis week was an important one for Refined Storage 1.x, Refined Storage Addons, and Ranged Pumps:\n\n* They got ported to Minecraft 1.20.1\n* link:https://modrinth.com/user/raoulvdberge[They are now available on Modrinth as well]\n* After a successful trial run on Refined Storage 2, link:https://github.com/refinedmods/refinedarchitect[the Refined Architect build infrastructure] is used instead of the custom solution per mod (yay, unification!)\n* link:https://github.com/refinedmods/refinedstorage/blob/develop/CHANGELOG.md[The historical changelogs got updated to the Keep A Changelog format]\n* link:https://github.com/refinedmods/refinedstorage/tags[The historical versions all got a tag on Git] and a link:https://github.com/refinedmods/refinedstorage/releases[corresponding release on GitHub]\n\nActually using Refined Architect on our projects only took a week, but the planning, pre-work, and testing with Refined Storage 2 took many weeks.\n\nAlong with that, link:https://github.com/refinedmods/refinedstorage2/releases/tag/v2.0.0-milestone.2.11[Refined Storage 2 has also been ported to Minecraft 1.20.1].\n\nThe next plans are:\n\n* Release a Fabric port of Ranged Pumps\n* Potentially port Refined Pipes to Minecraft 1.20.1\n* Keep on working on Refined Storage 2, link:https://github.com/orgs/refinedmods/projects/6/views/7[in which Milestone 2 is nearing completion]\n"
  },
  {
    "path": "docs/pages/news/20230819-refined-storage-2-milestone-2-completed.adoc",
    "content": "= Refined Storage 2 - milestone 2 completed!\n:type: article\n:description: Milestone 2 for Refined Storage 2 has been completed.\n:date: 2023-08-19\n\nToday, *milestone 2* for Refined Storage 2 has been completed!\n\nimage::../../assets/news/20230819-refined-storage-2-milestone-2-completed.png[Screenshot showing how milestone 2 is completed on GitHub]\n\nlink:https://github.com/refinedmods/refinedstorage2/wiki/FAQ[_If you don't know what Refined Storage 2 is, please read the FAQ first._]\n\n[.underline.bold]#Milestone 2 brings a lot of essential features:#\n\n* Importer\n* Exporter\n* Upgrades\n* Interface\n* External Storage\n* Support for multiple resource types in a single Grid\n* Colored cables\n* Crafting Grid\n* Detector\n* Constructor\n* Destructor\n* Additional JEI/REI integrations\n\nAdditionally, some features have been reworked or improved in comparison with Refined Storage 1.x.\n\nSome statistics:\n\n* Milestone 2 was in development from June 22nd, 2022 to August 19th, 2023.\n+ That is little over a year! _(milestone 1 was in development from October 24th, 2020 to June 22nd, 2022 - almost 2 years)_\n* Milestone 2 had 63 closed issues _(milestone 1 had 61 closed issues)_\n* Milestone 2 had 15 releases _(milestone 1 had 5 releases)_\n\n[.underline.bold]#What's next?#\n\nNow that milestone 2 is completed, I can focus on *milestone 3*.\n\nlink:https://github.com/refinedmods/refinedstorage2/milestone/3[Milestone 3 brings more networking and wireless access tools.]\n\nAfter that, the last milestone, link:https://github.com/refinedmods/refinedstorage2/milestone/4[milestone 4] is on the horizon, which will bring autocrafting.\n\n[.underline.bold]#Want to try out Refined Storage 2 yourself?#\n\n* link:https://github.com/refinedmods/refinedstorage2/releases/tag/v2.0.0-milestone.2.14[Find the latest version for milestone 2 here.]\n* link:https://github.com/refinedmods/refinedstorage2/wiki/Getting-started[Find the getting started guide here.]\n* link:https://discordapp.com/invite/VYzsydb[Join our Discord and let me know what your findings are!]\n"
  },
  {
    "path": "docs/pages/news/20240319-refined-storage-2-status-update-march.adoc",
    "content": "= Refined Storage 2 status update - March 2024\n:type: article\n:description: A status update on the development of Refined Storage 2.\n:date: 2024-03-19\n\nI'm starting a regular series of Refined Storage 2 status updates.\n\nlink:https://github.com/refinedmods/refinedstorage2/wiki/FAQ[If you don't know what Refined Storage 2 is, please read the FAQ first.]\n\nAs you might know, Refined Storage 2 development is very intensive:\n\n* Refined Storage is being completely rewritten;\n* Support for the Fabric modloader is being added;\n* Every feature that is re-added is thought out again and changes are being made at every step of the way;\n* Next to being a rewrite, Refined Storage 2 also contains a bunch of new features!\n\n*... and while all this work is in progress, Refined Storage 1.x still needs maintenance and regular Minecraft ports!*\n\n[.underline.bold]#What has been going on with Refined Storage 2 since milestone 2?#\n\nRefined Storage 2 is now in the final stages of milestone 3:\n\n* The mod got ported to Minecraft 1.20.4 and the NeoForge modloader.\n* Support for Forge has been dropped.\n* The Portable Grid has been added.\n* Custom disk models have been added.\n* Fluid disks have a different in-world model now.\n* The Configuration Card has been added.\n* A new item, copies configuration to other devices.\n* Network Receiver / Network Transmitter / Network Card has been added.\n* The Storage Monitor has been added.\n* Wireless Grid / Wireless Transmitter / Range Upgrade has been added.\n* Creative Range Upgrade has been added: infinite range upgrade (not craftable).\n* Curios and Trinkets integration for the wireless items.\n* \"Void excess\" mode on the storages has been added.\n* An old, loved, removed feature from Refined Storage 1.x, now re-added for Refined Storage 2.\n* I've added Refined Storage 2 to link:https://crowdin.com/project/refined-storage-2[Crowdin] and integrated it with our code repository. Now everyone can contribute translations more easily!\n* Thanks to all the early testers, link:https://github.com/refinedmods/refinedstorage2/issues?q=is%3Aissue+label%3Abug+milestone%3Av2.0.0-milestone.3+is%3Aclosed[a lot of bugs have been fixed].\n* Code quality improvements:\n* Test hardening (increasing mutation test coverage)\n* SonarQube fixes\n* Major refactoring to the storage API:\n* Simplifying and improving the API\n* Mixed storages are now possible (for example: a single disk that stores both items and fluids)\n\n[.underline.bold]#What is planned in the coming weeks?#\n\n* link:https://github.com/orgs/refinedmods/projects/6/views/8[Milestone 3 is in the process of being completed.]\n* The Security Card and Security Manager are being implemented.\n* Other remaining features to be implemented are:\n* Disk Manipulator\n* Relay\n* Covers\n\n[.underline.bold]#Want to try out Refined Storage 2 yourself?#\n\n* link:https://github.com/refinedmods/refinedstorage2/releases/tag/v2.0.0-milestone.3.4[Find the latest version for milestone 3 here.]\n* link:https://github.com/refinedmods/refinedstorage2/wiki/Getting-started[Find the getting started guide here.]\n* link:https://discordapp.com/invite/VYzsydb[Join our Discord and let me know what your findings are!]\n"
  },
  {
    "path": "docs/pages/news/20240628-refined-storage-2-milestone-3-completed.adoc",
    "content": "= Refined Storage 2 - milestone 3 completed!\n:type: article\n:description: Milestone 3 for Refined Storage 2 has been completed.\n:date: 2024-06-28\n\nimage::../../assets/news/20240628-refined-storage-2-milestone-3-completed-header.png[Screenshot showing some in-game features that were finished for milestone 3]\n\nToday, *milestone 3* for Refined Storage 2 has been completed!\n\nimage::../../assets/news/20240628-refined-storage-2-milestone-3-completed.png[Screenshot showing how milestone 3 is completed on GitHub]\n\nlink:https://github.com/refinedmods/refinedstorage2/wiki/FAQ[If you don't know what Refined Storage 2 is, please read the FAQ first.]\n\n*Milestone 3 brings a lot of new features:*\n\n* The mod got ported to Minecraft 1.20.4 and the NeoForge modloader.\n** Support for Forge has been dropped.\n* link:https://github.com/refinedmods/refinedstorage-curios-integration[Curios] and link:https://github.com/refinedmods/refinedstorage-trinkets-integration[Trinkets] integration mods have been created for the wireless items.\n* link:https://github.com/refinedmods/refinedstorage-jei-integration[JEI] and link:https://github.com/refinedmods/refinedstorage-rei-integration[REI] integrations have been extracted into separate integration mods.\n* link:https://github.com/refinedmods/refinedstorage-emi-integration[EMI] integration has been added.\n* The Relay has been added with support for subnetworks.\n** Watch a video about subnetworking in Refined Storage 2 link:https://www.youtube.com/watch?v=fRGH4ZUAnhQ[here].\n* \"Void excess\" mode on the storages has been added.\n** An old, loved, removed feature from Refined Storage 1.x, now re-added for Refined Storage 2.\n* The Portable Grid has been added.\n** Custom disk models have been added.\n** Fluid disks have a different in-world model now.\n* The Configuration Card has been added.\n** A new item, copies configuration to other devices.\n* Network Receiver / Network Transmitter / Network Card has been added.\n* The Storage Monitor has been added.\n* Wireless Grid / Wireless Transmitter / Range Upgrade has been added.\n** Creative Range Upgrade has been added: infinite range upgrade (not craftable)\n* The Security Card and Security Manager has been added.\n** The security system has been slightly reworked and a Fallback Security Card has been added.\n* The Disk Interface (formerly known as \"Disk Manipulator\") has been added.\n* I've added Refined Storage 2 to link:https://crowdin.com/project/refined-storage-2[Crowdin] and integrated it with our code repository. Now everyone can contribute translations more easily!\n* Thanks to all the early testers, link:https://github.com/refinedmods/refinedstorage2/issues?q=is%3Aissue+label%3Abug+is%3Aclosed+milestone%3Av2.0.0-milestone.3[a lot of bugs have been fixed].\n\nSome statistics:\n\n* Milestone 3 was in development from August 20th, 2023 to June 28th, 2024: about 10 months! _(milestone 2 was in development from June 22th, 2022 to August 19th, 2023, that is little over a year)_\n* Milestone 3 had 39 closed issues _(milestone 2 had 63 closed issues)_\n* Milestone 3 had 15 releases _(milestone 2 had 15 releases too)_\n\n*What's next?*\n\nlink:https://github.com/refinedmods/refinedstorage2/milestone/3?closed=1[Now that milestone 3 is completed], I can focus on the last milestone, *milestone 4*!\n\nlink:https://github.com/refinedmods/refinedstorage2/milestone/4[Milestone 4 brings support for Minecraft 1.21, autocrafting and Mekanism chemical integration.]\n\nAfter that, Refined Storage 2 will be ready and will replace Refined Storage 1.\n\n*Want to try out Refined Storage 2 yourself?*\n\n* link:https://github.com/refinedmods/refinedstorage2/releases/tag/v2.0.0-milestone.3.14[Find the latest version for milestone 3 here.]\n* link:https://github.com/refinedmods/refinedstorage2/wiki/Getting-started[Find the getting started guide here.]\n* link:https://discordapp.com/invite/VYzsydb[Join our Discord and let me know what your findings are!]\n"
  },
  {
    "path": "docs/pages/news/index.adoc",
    "content": "= News"
  },
  {
    "path": "docs/pages/news/index.html",
    "content": "<!DOCTYPE html>\n<html layout:decorate=\"~{layout.html}\">\n<head>\n    <title th:utext=\"${title}\"></title>\n</head>\n<body>\n<div layout:fragment=\"content\">\n    <div class=\"d-flex justify-content-end mb-3\">\n        <a th:href=\"@{'./' + ${currentComponent.slug} + '/' + ${currentComponent.latest ? '' : currentComponent.version.friendlyName() + '/'} + 'rss.xml'}\"\n           class=\"btn btn-primary btn-sm\">\n            <i class=\"bi bi-rss\"></i> RSS\n        </a>\n    </div>\n    <main class=\"list-group\">\n        <a th:href=\"@{'./' + ${currentComponent.slug} + '/' + ${currentComponent.latest ? '' : currentComponent.version.friendlyName() + '/'} + ${article.url}}\"\n           class=\"list-group-item list-group-item-action d-flex gap-3 py-3\"\n           th:each=\"article : ${articles}\">\n            <div class=\"d-flex gap-2 w-100 justify-content-between\">\n                <div>\n                    <h6 class=\"mb-0\" th:text=\"${article.title}\"></h6>\n                    <p class=\"mb-0 opacity-75\" th:text=\"${article.description}\"></p>\n                </div>\n                <small class=\"opacity-50 text-nowrap\">\n                    <i class=\"bi bi-clock\"></i> <span th:text=\"${#temporals.format(article.date, 'yyyy-MM-dd')}\"></span>\n                </small>\n            </div>\n        </a>\n    </main>\n</div>\n</body>\n</html>"
  },
  {
    "path": "docs/pages/opencomputers-api.adoc",
    "content": "= OpenComputers API\n\n[cols=\"1,1\"]\n|===\n|Method|Description|\n\n|`isConnected():boolean`|Whether the node is connected.\n|`getEnergyUsage():number`|Gets the energy usage of this network.|\n|`getTasks():table`|Gets the crafting tasks of this network.\n|`getPattern(stack:table):table`|Get one pattern of this network.\n|`getFluidPattern(stack:table):table`|Get one fluid pattern of this network.\n|`getPatterns():table`|Gets the patterns of this network.\n|`getFluidPatterns():table`|Gets the fluid patterns of this network.\n|`hasPattern(stack:table):boolean`|Whether a crafting pattern exists for this item.\n|`hasFluidPattern(stack:table):boolean`|Whether a crafting pattern exists for this fluid.\n|`scheduleTask(stack:table[,count: number[, canSchedule: boolean]]):table`|Schedules a crafting task.\n|`scheduleFluidTask(stack:table[,count: number[, canSchedule: boolean]]):table`|Schedules a fluid crafting task.\n|`cancelTask(stack:table):number`|Cancels a task and returns the amount of tasks cancelled.\n|`cancelFluidTask(stack:table):number`|Cancels a fluid task and returns the amount of tasks cancelled.\n|`extractFluid(stack:table[,amount:number[, direction:number]]):table`|Extracts a fluid from the network.\n|`getFluid(stack:table):table`|Gets a fluid from the network.\n|`getFluids():table`|Gets a list of all fluids in this network.\n|`extractItem(stack:table[,count:number[, direction:number]]):table`|Extracts an item from the network.\n|`getItem(stack:table[,compareMeta:boolean[, compareNBT:boolean]]):table`|Gets an item from the network.\n|`getItems():table`|Gets a list of all items in this network.\n|`getStorages():table`|Gets a list of all connected storage disks and blocks in this network.\n|==="
  },
  {
    "path": "docs/pages/release-notes.adoc",
    "content": "= Release notes\n"
  },
  {
    "path": "docs/pages/release-notes.html",
    "content": "<!DOCTYPE html>\n<html layout:decorate=\"~{layout.html}\">\n<head>\n    <title th:utext=\"${title}\"></title>\n</head>\n<body>\n<div layout:fragment=\"content\">\n    <main>\n        <div th:if=\"${currentRelease != null}\" class=\"card\">\n            <div class=\"card-body\">\n                <h2 class=\"card-title\">\n                    In version <span th:text=\"${currentRelease.release.getName()}\" th:remove=\"tag\"></span>\n\n                    <span class=\"badge bg-primary\" th:if=\"${currentRelease.release.type.name() == 'BETA'}\">Beta</span>\n                    <span class=\"badge bg-warning text-dark\"\n                          th:if=\"${currentRelease.release.type.name() == 'ALPHA'}\">Alpha</span>\n                </h2>\n\n                <div class=\"text-muted d-flex gap-3 mb-2\">\n                <span>\n                    <i class=\"bi bi-calendar\"></i>\n                    <span\n                            th:text=\"${#dates.format(currentRelease.release.createdAt, 'yyyy-MM-dd')}\"\n                            th:remove=\"tag\"></span>\n                </span>\n                    <span>\n                    <i class=\"bi bi-download\"></i>\n                    <span th:remove=\"tag\"\n                          th:text=\"${currentRelease.release.stats.totalDownloads}\"></span>\n                </span>\n                </div>\n\n                <div th:utext=\"${currentRelease.changelogHtml}\"></div>\n\n                <div class=\"d-flex flex-wrap gap-1\">\n                    <a th:href=\"${currentRelease.curseforgeUrl}\" th:if=\"${currentRelease.curseforgeUrl != null}\"\n                       class=\"btn btn-primary\">\n                        <svg class=\"distribution-platform-logo\" xmlns=\"http://www.w3.org/2000/svg\"\n                             viewBox=\"-2017 853 43 23\">\n                            <path d=\"M-2005.7,853l0.7,3c-3.5,0-12,0-12,0s0.2,0.9,0.3,1c0.3,0.5,0.6,1.1,1,1.5c1.9,2.2,5.2,3.1,7.9,3.6 c1.9,0.4,3.8,0.5,5.7,0.6l2.2,5.9h1.2l0.7,1.9h-1l-1.7,5.5h16.7l-1.7-5.5h-1l0.7-1.9h1.2c0,0,1-6.1,4.1-8.9c3-2.8,6.7-3.2,6.7-3.2 V853H-2005.7z M-1988.9,868.1c-0.8,0.5-1.7,0.5-2.3,0.9c-0.4,0.2-0.6,0.8-0.6,0.8c-0.4-0.9-0.9-1.2-1.5-1.4 c-0.6-0.2-1.7-0.1-3.2-1.4c-1-0.9-1.1-2.1-1-2.7v-0.1c0-0.1,0-0.1,0-0.2s0-0.2,0.1-0.3l0,0l0,0c0.2-0.6,0.7-1.2,1.7-1.6 c0,0-0.7,1,0,2c0.4,0.6,1.2,0.9,1.9,0.5c0.3-0.2,0.5-0.6,0.6-0.9c0.2-0.7,0.2-1.4-0.4-1.9c-0.9-0.8-1.1-1.9-0.5-2.6 c0,0,0.2,0.9,1.1,0.8c0.6,0,0.6-0.2,0.4-0.4c-0.1-0.3-1.4-2.2,0.5-3.6c0,0,1.2-0.8,2.6-0.7c-0.8,0.1-1.7,0.6-2,1.4c0,0,0,0,0,0.1 c-0.3,0.8-0.1,1.7,0.5,2.5c0.4,0.6,0.9,1.1,1.1,1.9c-0.3-0.1-0.5,0-0.7,0.2c-0.2,0.2-0.3,0.6-0.2,0.9c0.1,0.2,0.3,0.4,0.5,0.4 c0.1,0,0.1,0,0.2,0h0.1c0.3-0.1,0.5-0.5,0.4-0.8c0.2,0.2,0.3,0.7,0.2,1c0,0.3-0.2,0.6-0.3,0.8c-0.1,0.2-0.3,0.4-0.4,0.6 s-0.2,0.4-0.2,0.6c0,0.2,0,0.5,0.1,0.7c0.4,0.6,1.2,0,1.4-0.5c0.3-0.6,0.2-1.3-0.2-1.9c0,0,0.7,0.4,1.2,1.8 C-1987.4,866.2-1988.1,867.6-1988.9,868.1z\"></path>\n                        </svg>\n                        Download on CurseForge\n                    </a>\n                    <a th:href=\"${currentRelease.modrinthUrl}\" th:if=\"${currentRelease.modrinthUrl != null}\"\n                       class=\"btn btn-primary\">\n                        <svg class=\"distribution-platform-logo\" xmlns=\"http://www.w3.org/2000/svg\"\n                             viewBox=\"0 0 512 514\">\n                            <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n                                  d=\"M503.16 323.56C514.55 281.47 515.32 235.91 503.2 190.76C466.57 54.2299 326.04 -26.8001 189.33 9.77991C83.8101 38.0199 11.3899 128.07 0.689941 230.47H43.99C54.29 147.33 113.74 74.7298 199.75 51.7098C306.05 23.2598 415.13 80.6699 453.17 181.38L411.03 192.65C391.64 145.8 352.57 111.45 306.3 96.8198L298.56 140.66C335.09 154.13 364.72 184.5 375.56 224.91C391.36 283.8 361.94 344.14 308.56 369.17L320.09 412.16C390.25 383.21 432.4 310.3 422.43 235.14L464.41 223.91C468.91 252.62 467.35 281.16 460.55 308.07L503.16 323.56Z\"/>\n                            <path d=\"M321.99 504.22C185.27 540.8 44.7501 459.77 8.11011 323.24C3.84011 307.31 1.17 291.33 0 275.46H43.27C44.36 287.37 46.4699 299.35 49.6799 311.29C53.0399 323.8 57.45 335.75 62.79 347.07L101.38 323.92C98.1299 316.42 95.39 308.6 93.21 300.47C69.17 210.87 122.41 118.77 212.13 94.7601C229.13 90.2101 246.23 88.4401 262.93 89.1501L255.19 133C244.73 133.05 234.11 134.42 223.53 137.25C157.31 154.98 118.01 222.95 135.75 289.09C136.85 293.16 138.13 297.13 139.59 300.99L188.94 271.38L174.07 231.95L220.67 184.08L279.57 171.39L296.62 192.38L269.47 219.88L245.79 227.33L228.87 244.72L237.16 267.79C237.16 267.79 253.95 285.63 253.98 285.64L277.7 279.33L294.58 260.79L331.44 249.12L342.42 273.82L304.39 320.45L240.66 340.63L212.08 308.81L162.26 338.7C187.8 367.78 226.2 383.93 266.01 380.56L277.54 423.55C218.13 431.41 160.1 406.82 124.05 361.64L85.6399 384.68C136.25 451.17 223.84 484.11 309.61 461.16C371.35 444.64 419.4 402.56 445.42 349.38L488.06 364.88C457.17 431.16 398.22 483.82 321.99 504.22Z\"/>\n                        </svg>\n                        Download on Modrinth\n                    </a>\n                    <a th:href=\"${currentRelease.githubUrl}\" th:if=\"${currentRelease.githubUrl != null}\"\n                       class=\"btn btn-primary\">\n                        <i class=\"bi bi-github\"></i>\n                        Download on GitHub\n                    </a>\n                </div>\n            </div>\n        </div>\n    </main>\n\n    <h3 class=\"mt-2 mb-2\">Other releases</h3>\n\n    <div class=\"accordion\" id=\"other-releases\">\n        <div class=\"accordion-item\" th:each=\"otherRelease : ${otherReleases}\">\n            <h2 class=\"accordion-header\">\n                <button class=\"accordion-button d-flex gap-2 collapsed\"\n                        type=\"button\"\n                        data-bs-toggle=\"collapse\"\n                        th:attr=\"data-bs-target='#collapse-' + ${otherRelease.slug}, aria-controls='collapse-' + ${otherRelease.slug}\">\n                    <span th:text=\"${otherRelease.release.name}\"></span>\n                    <span class=\"badge bg-primary\" th:if=\"${otherRelease.release.type.name() == 'BETA'}\">Beta</span>\n                    <span class=\"badge bg-warning text-dark\"\n                          th:if=\"${otherRelease.release.type.name() == 'ALPHA'}\">Alpha</span>\n                </button>\n            </h2>\n            <div th:id=\"'collapse-' + ${otherRelease.slug}\"\n                 class=\"accordion-collapse collapse\"\n                 data-bs-parent=\"#other-releases\">\n                <div class=\"accordion-body\">\n                    <h2 class=\"card-title\">\n                        In version <span th:text=\"${otherRelease.release.getName()}\" th:remove=\"tag\"></span>\n                    </h2>\n\n                    <div class=\"text-muted d-flex gap-3 mb-2\">\n                        <span>\n                            <i class=\"bi bi-calendar\"></i>\n                            <span\n                                    th:text=\"${#dates.format(otherRelease.release.createdAt, 'yyyy-MM-dd')}\"\n                                    th:remove=\"tag\"></span>\n                        </span>\n                        <span>\n                            <i class=\"bi bi-download\"></i>\n                            <span th:remove=\"tag\"\n                                  th:text=\"${otherRelease.release.stats.totalDownloads}\"></span>\n                        </span>\n                    </div>\n\n                    <div th:utext=\"${otherRelease.changelogHtml}\"></div>\n\n                    <div class=\"d-flex flex-wrap gap-1\">\n                        <a th:href=\"${otherRelease.curseforgeUrl}\" th:if=\"${otherRelease.curseforgeUrl != null}\"\n                           class=\"btn btn-primary\">\n                            <svg class=\"distribution-platform-logo\" xmlns=\"http://www.w3.org/2000/svg\"\n                                 viewBox=\"-2017 853 43 23\">\n                                <path d=\"M-2005.7,853l0.7,3c-3.5,0-12,0-12,0s0.2,0.9,0.3,1c0.3,0.5,0.6,1.1,1,1.5c1.9,2.2,5.2,3.1,7.9,3.6 c1.9,0.4,3.8,0.5,5.7,0.6l2.2,5.9h1.2l0.7,1.9h-1l-1.7,5.5h16.7l-1.7-5.5h-1l0.7-1.9h1.2c0,0,1-6.1,4.1-8.9c3-2.8,6.7-3.2,6.7-3.2 V853H-2005.7z M-1988.9,868.1c-0.8,0.5-1.7,0.5-2.3,0.9c-0.4,0.2-0.6,0.8-0.6,0.8c-0.4-0.9-0.9-1.2-1.5-1.4 c-0.6-0.2-1.7-0.1-3.2-1.4c-1-0.9-1.1-2.1-1-2.7v-0.1c0-0.1,0-0.1,0-0.2s0-0.2,0.1-0.3l0,0l0,0c0.2-0.6,0.7-1.2,1.7-1.6 c0,0-0.7,1,0,2c0.4,0.6,1.2,0.9,1.9,0.5c0.3-0.2,0.5-0.6,0.6-0.9c0.2-0.7,0.2-1.4-0.4-1.9c-0.9-0.8-1.1-1.9-0.5-2.6 c0,0,0.2,0.9,1.1,0.8c0.6,0,0.6-0.2,0.4-0.4c-0.1-0.3-1.4-2.2,0.5-3.6c0,0,1.2-0.8,2.6-0.7c-0.8,0.1-1.7,0.6-2,1.4c0,0,0,0,0,0.1 c-0.3,0.8-0.1,1.7,0.5,2.5c0.4,0.6,0.9,1.1,1.1,1.9c-0.3-0.1-0.5,0-0.7,0.2c-0.2,0.2-0.3,0.6-0.2,0.9c0.1,0.2,0.3,0.4,0.5,0.4 c0.1,0,0.1,0,0.2,0h0.1c0.3-0.1,0.5-0.5,0.4-0.8c0.2,0.2,0.3,0.7,0.2,1c0,0.3-0.2,0.6-0.3,0.8c-0.1,0.2-0.3,0.4-0.4,0.6 s-0.2,0.4-0.2,0.6c0,0.2,0,0.5,0.1,0.7c0.4,0.6,1.2,0,1.4-0.5c0.3-0.6,0.2-1.3-0.2-1.9c0,0,0.7,0.4,1.2,1.8 C-1987.4,866.2-1988.1,867.6-1988.9,868.1z\"></path>\n                            </svg>\n                            Download on CurseForge\n                        </a>\n                        <a th:href=\"${otherRelease.modrinthUrl}\" th:if=\"${otherRelease.modrinthUrl != null}\"\n                           class=\"btn btn-primary\">\n                            <svg class=\"distribution-platform-logo\" xmlns=\"http://www.w3.org/2000/svg\"\n                                 viewBox=\"0 0 512 514\">\n                                <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n                                      d=\"M503.16 323.56C514.55 281.47 515.32 235.91 503.2 190.76C466.57 54.2299 326.04 -26.8001 189.33 9.77991C83.8101 38.0199 11.3899 128.07 0.689941 230.47H43.99C54.29 147.33 113.74 74.7298 199.75 51.7098C306.05 23.2598 415.13 80.6699 453.17 181.38L411.03 192.65C391.64 145.8 352.57 111.45 306.3 96.8198L298.56 140.66C335.09 154.13 364.72 184.5 375.56 224.91C391.36 283.8 361.94 344.14 308.56 369.17L320.09 412.16C390.25 383.21 432.4 310.3 422.43 235.14L464.41 223.91C468.91 252.62 467.35 281.16 460.55 308.07L503.16 323.56Z\"/>\n                                <path d=\"M321.99 504.22C185.27 540.8 44.7501 459.77 8.11011 323.24C3.84011 307.31 1.17 291.33 0 275.46H43.27C44.36 287.37 46.4699 299.35 49.6799 311.29C53.0399 323.8 57.45 335.75 62.79 347.07L101.38 323.92C98.1299 316.42 95.39 308.6 93.21 300.47C69.17 210.87 122.41 118.77 212.13 94.7601C229.13 90.2101 246.23 88.4401 262.93 89.1501L255.19 133C244.73 133.05 234.11 134.42 223.53 137.25C157.31 154.98 118.01 222.95 135.75 289.09C136.85 293.16 138.13 297.13 139.59 300.99L188.94 271.38L174.07 231.95L220.67 184.08L279.57 171.39L296.62 192.38L269.47 219.88L245.79 227.33L228.87 244.72L237.16 267.79C237.16 267.79 253.95 285.63 253.98 285.64L277.7 279.33L294.58 260.79L331.44 249.12L342.42 273.82L304.39 320.45L240.66 340.63L212.08 308.81L162.26 338.7C187.8 367.78 226.2 383.93 266.01 380.56L277.54 423.55C218.13 431.41 160.1 406.82 124.05 361.64L85.6399 384.68C136.25 451.17 223.84 484.11 309.61 461.16C371.35 444.64 419.4 402.56 445.42 349.38L488.06 364.88C457.17 431.16 398.22 483.82 321.99 504.22Z\"/>\n                            </svg>\n                            Download on Modrinth\n                        </a>\n                        <a th:href=\"${otherRelease.githubUrl}\" th:if=\"${otherRelease.githubUrl != null}\"\n                           class=\"btn btn-primary\">\n                            <i class=\"bi bi-github\"></i>\n                            Download on GitHub\n                        </a>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "docs/pages/security/index.adoc",
    "content": "= Security\n\n- xref:security-manager.adoc[]\n- xref:security-card.adoc[]"
  },
  {
    "path": "docs/pages/security/security-card.adoc",
    "content": "= Security Card\n:from: v1.4.0-beta\n:icon: security-card.png\n\nThe {doctitle} is an item that is bound to a player by right clicking.\n\nThe {doctitle} has to be inserted into a xref:security-manager.adoc[], and can be configured from there as well."
  },
  {
    "path": "docs/pages/security/security-manager.adoc",
    "content": "= Security Manager\n:from: v1.4.0-beta\n:icon: security-manager.png\n\nThe {doctitle} is a block that can store xref:security-card.adoc[security cards].\n\nFrom its GUI, you can configure what permissions each player (that is bound with a xref:security-card.adoc[]) has.\n\nOnce the xref:security-card.adoc[] is inserted in the top slots, the permissions for that player will be restricted to the ones configured.\n\n== Behavior\n\nWhen no xref:security-card.adoc[security cards] are active on the network, everyone has access to all permissions.\n\nStart inserting xref:security-card.adoc[security cards] to define permissions for players.\n\nPlayers who have no configured xref:security-card.adoc[] are still able to do everything in the network (all permissions).\n\nTo configure a \"global\" set of permissions for all unconfigured players, configure a xref:security-card.adoc[] that isn't bound to a player and insert it in the {doctitle}.\n\nOperators (OPs) on a server have access to all permissions, overriding all network security.\n\n== The placer\n\nThe placer of the {doctitle} will always be able to open it's GUI and change the security settings, regardless of permissions.\n\n== Permissions\n\n[cols=\"1,1\"]\n|===\n|Type|Description\n\n|Insert|Inserting items to the network\n|Extract|Extracting items from the network\n|Autocrafting|Starting, cancelling and viewing crafting tasks\n|Modify|Opening block GUIs from the network\n|Build|Adding or removing devices to or from the network\n|Security|Ability to change security options\n|===\n\ninclude::../../partials/recoloring.adoc[]\n"
  },
  {
    "path": "docs/pages/storage/1024k-fluid-storage-block.adoc",
    "content": "= 1024k Fluid Storage Block\n:icon: 1024k-fluid-storage-block.png\n:from: v0.9.0-beta\n\ninclude::../../partials/fluid-storage-block.adoc[]\n\n== Storage capacity\n\nThe {doctitle} can store 1024.000 millibuckets or 1024 buckets of any fluid."
  },
  {
    "path": "docs/pages/storage/1024k-fluid-storage-disk.adoc",
    "content": "= 1024k Fluid Storage Disk\n:icon: 1024k-fluid-storage-disk.png\n:from: v0.9.0-beta\n\ninclude::../../partials/fluid-storage-disk.adoc[]\n\n== Storage capacity\n\nThe {doctitle} can store 1024.000 millibuckets or 1024 buckets of any fluid."
  },
  {
    "path": "docs/pages/storage/1024k-fluid-storage-part.adoc",
    "content": "= 1024k Fluid Storage Part\n:icon: 1024k-fluid-storage-part.png\n:from: v0.9.0-beta\n\nThe {doctitle} is used to craft the xref:1024k-fluid-storage-disk.adoc[] and xref:1024k-fluid-storage-block.adoc[]."
  },
  {
    "path": "docs/pages/storage/16k-storage-block.adoc",
    "content": "= 16k Storage Block\n:icon: 16k-storage-block.png\n:from: v0.3.0-alpha\n\ninclude::../../partials/storage-block.adoc[]\n\n== Storage capacity\n\nThe {doctitle} can store 16.000 items."
  },
  {
    "path": "docs/pages/storage/16k-storage-disk.adoc",
    "content": "= 16k Storage Disk\n:icon: 16k-storage-disk.png\n:from: v0.3.0-alpha\n\ninclude::../../partials/storage-disk.adoc[]\n\n== Storage capacity\n\nThe {doctitle} can store 16.000 items."
  },
  {
    "path": "docs/pages/storage/16k-storage-part.adoc",
    "content": "= 16k Storage Part\n:icon: 16k-storage-part.png\n:from: v0.3.0-alpha\n\nThe {doctitle} is used to craft the xref:16k-storage-block.adoc[]."
  },
  {
    "path": "docs/pages/storage/1k-storage-block.adoc",
    "content": "= 1k Storage Block\n:icon: 1k-storage-block.png\n:from: v0.3.0-alpha\n\ninclude::../../partials/storage-block.adoc[]\n\n== Storage capacity\n\nThe {doctitle} can store 1.000 items."
  },
  {
    "path": "docs/pages/storage/1k-storage-disk.adoc",
    "content": "= 1k Storage Disk\n:icon: 1k-storage-disk.png\n:from: v0.3.0-alpha\n\ninclude::../../partials/storage-disk.adoc[]\n\n== Storage capacity\n\nThe {doctitle} can store 1.000 items."
  },
  {
    "path": "docs/pages/storage/1k-storage-part.adoc",
    "content": "= 1k Storage Part\n:icon: 1k-storage-part.png\n:from: v0.3.0-alpha\n\nThe {doctitle} is used to craft the xref:1k-storage-block.adoc[]."
  },
  {
    "path": "docs/pages/storage/256k-fluid-storage-block.adoc",
    "content": "= 256k Fluid Storage Block\n:icon: 256k-fluid-storage-block.png\n:from: v0.9.0-beta\n\ninclude::../../partials/fluid-storage-block.adoc[]\n\n== Storage capacity\n\nThe {doctitle} can store 256.000 millibuckets or 256 buckets of any fluid."
  },
  {
    "path": "docs/pages/storage/256k-fluid-storage-disk.adoc",
    "content": "= 256k Fluid Storage Disk\n:icon: 256k-fluid-storage-disk.png\n:from: v0.9.0-beta\n\ninclude::../../partials/fluid-storage-disk.adoc[]\n\n== Storage capacity\n\nThe {doctitle} can store 256.000 millibuckets or 256 buckets of any fluid."
  },
  {
    "path": "docs/pages/storage/256k-fluid-storage-part.adoc",
    "content": "= 256k Fluid Storage Part\n:icon: 256k-fluid-storage-part.png\n:from: v0.9.0-beta\n\nThe {doctitle} is used to craft the xref:256k-fluid-storage-disk.adoc[] and xref:256k-fluid-storage-block.adoc[]."
  },
  {
    "path": "docs/pages/storage/4096k-fluid-storage-block.adoc",
    "content": "= 4096k Fluid Storage Block\n:icon: 4096k-fluid-storage-block.png\n:from: v0.9.0-beta\n\ninclude::../../partials/fluid-storage-block.adoc[]\n\n== Storage capacity\n\nThe {doctitle} can store 4096.000 millibuckets or 4096 buckets of any fluid."
  },
  {
    "path": "docs/pages/storage/4096k-fluid-storage-disk.adoc",
    "content": "= 4096k Fluid Storage Disk\n:icon: 4096k-fluid-storage-disk.png\n:from: v0.9.0-beta\n\ninclude::../../partials/fluid-storage-disk.adoc[]\n\n== Storage capacity\n\nThe {doctitle} can store 4096.000 millibuckets or 4096 buckets of any fluid."
  },
  {
    "path": "docs/pages/storage/4096k-fluid-storage-part.adoc",
    "content": "= 4096k Fluid Storage Part\n:icon: 4096k-fluid-storage-part.png\n:from: v0.9.0-beta\n\nThe {doctitle} is used to craft the xref:4096k-fluid-storage-disk.adoc[] and xref:4096k-fluid-storage-block.adoc[]."
  },
  {
    "path": "docs/pages/storage/4k-storage-block.adoc",
    "content": "= 4k Storage Block\n:icon: 4k-storage-block.png\n:from: v0.3.0-alpha\n\ninclude::../../partials/storage-block.adoc[]\n\n== Storage capacity\n\nThe {doctitle} can store 4.000 items."
  },
  {
    "path": "docs/pages/storage/4k-storage-disk.adoc",
    "content": "= 4k Storage Disk\n:icon: 4k-storage-disk.png\n:from: v0.3.0-alpha\n\ninclude::../../partials/storage-disk.adoc[]\n\n== Storage capacity\n\nThe {doctitle} can store 4.000 items."
  },
  {
    "path": "docs/pages/storage/4k-storage-part.adoc",
    "content": "= 4k Storage Part\n:icon: 4k-storage-part.png\n:from: v0.3.0-alpha\n\nThe {doctitle} is used to craft the xref:4k-storage-block.adoc[]."
  },
  {
    "path": "docs/pages/storage/64k-fluid-storage-block.adoc",
    "content": "= 64k Fluid Storage Block\n:icon: 64k-storage-block.png\n:from: v0.9.0-beta\n\ninclude::../../partials/fluid-storage-block.adoc[]\n\n== Storage capacity\n\nThe {doctitle} can store 64.000 millibuckets or 64 buckets of any fluid."
  },
  {
    "path": "docs/pages/storage/64k-fluid-storage-disk.adoc",
    "content": "= 64k Fluid Storage Disk\n:icon: 64k-fluid-storage-disk.png\n:from: v0.9.0-beta\n\ninclude::../../partials/fluid-storage-disk.adoc[]\n\n== Storage capacity\n\nThe {doctitle} can store 64.000 millibuckets or 64 buckets of any fluid."
  },
  {
    "path": "docs/pages/storage/64k-fluid-storage-part.adoc",
    "content": "= 64k Fluid Storage Part\n:icon: 64k-fluid-storage-part.png\n:from: v0.9.0-beta\n\nThe {doctitle} is used to craft the xref:64k-fluid-storage-disk.adoc[] and xref:64k-fluid-storage-block.adoc[]."
  },
  {
    "path": "docs/pages/storage/64k-storage-block.adoc",
    "content": "= 64k Storage Block\n:icon: 64k-storage-block.png\n:from: v0.3.0-alpha\n\ninclude::../../partials/storage-block.adoc[]\n\n== Storage capacity\n\nThe {doctitle} can store 64.000 items."
  },
  {
    "path": "docs/pages/storage/64k-storage-disk.adoc",
    "content": "= 64k Storage Disk\n:icon: 64k-storage-disk.png\n:from: v0.3.0-alpha\n\ninclude::../../partials/storage-disk.adoc[]\n\n== Storage capacity\n\nThe {doctitle} can store 64.000 items."
  },
  {
    "path": "docs/pages/storage/64k-storage-part.adoc",
    "content": "= 64k Storage Part\n:icon: 64k-storage-part.png\n:from: v0.3.0-alpha\n\nThe {doctitle} is used to craft the xref:64k-storage-block.adoc[]."
  },
  {
    "path": "docs/pages/storage/creative-fluid-storage-block.adoc",
    "content": "= Creative Fluid Storage Block\n:icon: creative-fluid-storage-block.png\n:from: v0.9.0-beta\n\ninclude::../../partials/fluid-storage-block.adoc[]\n\n== Storage capacity\n\nThe {doctitle} can store an infinite amount of buckets.\n\nIt can only be obtained in creative mode."
  },
  {
    "path": "docs/pages/storage/creative-fluid-storage-disk.adoc",
    "content": "= Creative Fluid Storage Disk\n:icon: creative-fluid-storage-disk.png\n:from: v0.9.0-beta\n\ninclude::../../partials/fluid-storage-disk.adoc[]\n\n== Storage capacity\n\nThe {doctitle} can store an infinite amount of buckets.\n\nIt can only be obtained in creative mode."
  },
  {
    "path": "docs/pages/storage/creative-storage-block.adoc",
    "content": "= Creative Storage Block\n:icon: creative-storage-block.png\n:from: v0.3.0-alpha\n\ninclude::../../partials/storage-block.adoc[]\n\n== Storage capacity\n\nThe {doctitle} can store an infinite amount of items.\n\nIt can only be obtained in creative mode."
  },
  {
    "path": "docs/pages/storage/creative-storage-disk.adoc",
    "content": "= Creative Storage Disk\n:icon: creative-storage-disk.png\n:from: v0.3.0-alpha\n\ninclude::../../partials/storage-disk.adoc[]\n\n== Storage capacity\n\nThe {doctitle} can store an infinite amount of items.\n\nIt can only be obtained in creative mode."
  },
  {
    "path": "docs/pages/storage/disk-drive.adoc",
    "content": "= Disk Drive\n:icon: disk-drive.png\n:from: v0.3.0-alpha\n\nThe Disk Drive is the block in which you store xref:index.adoc#_storage_disks[storage disks] or xref:index.adoc#_fluid_storage_disks[fluid storage disks].\n\n== Priority\n\nA (negative or positive) priority can be chosen (where a higher priority gets higher precedence to place items in).\n\n== Whitelist and blacklist\n\nThere is also a whitelist and blacklist to only allow or forbid some items or fluids from entering the xref:index.adoc#_storage_disks[storage disks] or xref:index.adoc#_fluid_storage_disks[fluid storage disks] respectively.\n\nThe whitelist or blacklist can be configured to be NBT or damage sensitive.\n\n== Mode\n\nThe Disk Drive has support for the following modes:\n\n- Insert and extract (default)\n- Insert only\n- Extract only"
  },
  {
    "path": "docs/pages/storage/external-storage.adoc",
    "content": "= External Storage\n:from: v0.3.0-alpha\n:icon: external-storage.png\n\nThe {doctitle} is a block that provides the storage network with storage of the inventory or fluid tank in front of the device.\n\n== Priority\n\nA (negative or positive) priority can be chosen (where a higher priority gets higher precedence to place items in).\n\n== Whitelist and blacklist\n\nThere is also a whitelist and blacklist option to only allow or forbid some items or fluids from entering the connected inventory.\n\nThe whitelist or blacklist can be configured to be NBT or damage sensitive.\n\n== Mode\n\nThe {doctitle} has support for the following modes:\n\n- Insert and extract (default)\n- Insert only\n- Extract only"
  },
  {
    "path": "docs/pages/storage/index.adoc",
    "content": "= Storage\n\n- xref:storing-externally.adoc[]\n- xref:storing-fluids.adoc[]\n\n== Network devices\n\n- xref:disk-drive.adoc[]\n- xref:external-storage.adoc[]\n\n[#_storage_parts]\n== Storage parts\n\n- xref:1k-storage-part.adoc[]\n- xref:4k-storage-part.adoc[]\n- xref:16k-storage-part.adoc[]\n- xref:64k-storage-part.adoc[]\n\n[#_storage_disks]\n== Storage disks\n\n- xref:1k-storage-disk.adoc[]\n- xref:4k-storage-disk.adoc[]\n- xref:16k-storage-disk.adoc[]\n- xref:64k-storage-disk.adoc[]\n- xref:creative-storage-disk.adoc[]\n\n[#_storage_blocks]\n== Storage blocks\n\n- xref:1k-storage-block.adoc[]\n- xref:4k-storage-block.adoc[]\n- xref:16k-storage-block.adoc[]\n- xref:64k-storage-block.adoc[]\n- xref:creative-storage-block.adoc[]\n\n[#_fluid_storage_parts]\n== Fluid storage parts\n\n- xref:64k-fluid-storage-part.adoc[]\n- xref:256k-fluid-storage-part.adoc[]\n- xref:1024k-fluid-storage-part.adoc[]\n- xref:4096k-fluid-storage-part.adoc[]\n\n[#_fluid_storage_disks]\n== Fluid storage disks\n\n- xref:64k-fluid-storage-disk.adoc[]\n- xref:256k-fluid-storage-disk.adoc[]\n- xref:1024k-fluid-storage-disk.adoc[]\n- xref:4096k-fluid-storage-disk.adoc[]\n- xref:creative-fluid-storage-disk.adoc[]\n\n[#_fluid_storage_blocks]\n== Fluid storage blocks\n\n- xref:64k-fluid-storage-block.adoc[]\n- xref:256k-fluid-storage-block.adoc[]\n- xref:1024k-fluid-storage-block.adoc[]\n- xref:4096k-fluid-storage-block.adoc[]\n- xref:creative-fluid-storage-block.adoc[]\n"
  },
  {
    "path": "docs/pages/storage/storage-housing.adoc",
    "content": "= Storage Housing\n:icon: storage-housing.png\n:from: v0.6.0-alpha\n\nA Storage Housing is a xref:index.adoc#_storage_disks[storage disk] or xref:index.adoc#_fluid_storage_disks[fluid storage disk] without any xref:index.adoc#_storage_parts[storage part] or xref:index.adoc#_fluid_storage_parts[fluid storage part] assigned to it.\n\nThe player can craft another xref:index.adoc#_storage_disks[storage disk] or xref:index.adoc#_fluid_storage_disks[fluid storage disk] with this item by combining the Storage Housing with a xref:index.adoc#_storage_parts[storage part] or xref:index.adoc#_fluid_storage_parts[fluid storage part] respectively."
  },
  {
    "path": "docs/pages/storage/storing-externally.adoc",
    "content": "= Storing externally\n\nSo far you've used xref:index.adoc#_storage_disks[storage disks] or xref:index.adoc#_storage_blocks[storage blocks].\nWhat if you want to use a chest or another inventory as storage?\n\n== The External Storage\n\nCraft an xref:external-storage.adoc[] and connect it to an external inventory like a link:https://minecraft.gamepedia.com/Chest[Chest].\n\nIf you now insert items, they will go in the inventory.\n\nYou can also filter items that can enter the external inventory with the filter slots.\n\n== Supported storages\n\nThe xref:external-storage.adoc[] supports every block that is an inventory.\nSome examples:\n\n- link:https://minecraft.gamepedia.com/Chest[Chests]\n- Storage Drawers\n- Regular drawers\n- Drawer Controller\n- Iron Chests\n- etc...\n\n== Using an External Storage alongside other storages\n\nWhen you insert or extract an item from the storage network, Refined Storage will extract or insert from the storage with the highest priority first.\n\nSimply give a storage a higher priority than the other one, and Refined Storage will prioritize correctly.\n\nIf the storage is full, Refined Storage will attempt to insert or extract from the next available storage, with a lower priority."
  },
  {
    "path": "docs/pages/storage/storing-fluids.adoc",
    "content": "= Storing fluids\n\nAs opposed to only item storage, Refined Storage is able to store fluids as well.\nThis is done in the entirely same way as item storages.\n\nAll the things you can do to manipulate items (with xref:../input-and-output/exporter.adoc[exporters] or xref:../input-and-output/importer.adoc[importers]) you can do with fluids as well.\n\n== Storage\n\nThe same way as you connect item storages, you can connect fluid storages as well:\n\n- xref:index.adoc#_fluid_storage_disks[Any fluid storage disk] in a xref:disk-drive.adoc[]\n- xref:index.adoc#_fluid_storage_blocks[Any fluid storage block]\n- xref:external-storage.adoc[] in fluid mode\n\n== Accessing fluids\n\nUse a xref:../viewing-resources/fluid-grid.adoc[].\n\n== Manipulating fluids\n\nAny block that would manipulate items can manipulate fluids as well by simply putting the block in fluid mode.\n\nThere is one exception to this: the xref:../input-and-output/interface.adoc[] has no fluid mode.\nUse a xref:../input-and-output/fluid-interface.adoc[] instead."
  },
  {
    "path": "docs/pages/upgrades/crafting-upgrade.adoc",
    "content": "= Crafting Upgrade\n:icon: crafting-upgrade.png\n:from: v0.6.0-alpha\n\nThe {doctitle} will schedule a crafting task when the item being used in a device is needed but not available.\n\nBy using this upgrade, the amount of FE/t that this device draws will increase."
  },
  {
    "path": "docs/pages/upgrades/fortune-upgrade.adoc",
    "content": "= Fortune Upgrade\n:icon: fortune-upgrade.png\n:from: v1.2.0\n\nThe {doctitle} will make the xref:../input-and-output/destructor.adoc[] use a certain fortune level (depending on which upgrade you have) on the block it is breaking.\n\nThis upgrade has 3 versions:\n\n- Fortune 1\n- Fortune 2\n- Fortune 3\n\nBy using this upgrade, the amount of FE/t that this device draws will increase."
  },
  {
    "path": "docs/pages/upgrades/index.adoc",
    "content": "= Upgrades\n\n- xref:upgrade.adoc[]\n- xref:range-upgrade.adoc[]\n- xref:speed-upgrade.adoc[]\n- xref:stack-upgrade.adoc[]\n- xref:crafting-upgrade.adoc[]\n- xref:regulator-upgrade.adoc[]\n- xref:fortune-upgrade.adoc[]\n- xref:silk-touch-upgrade.adoc[]\n- xref:interdimensional-upgrade.adoc[]\n"
  },
  {
    "path": "docs/pages/upgrades/interdimensional-upgrade.adoc",
    "content": "= Interdimensional Upgrade\n:icon: interdimensional-upgrade.png\n:from: v0.8.14-beta\n:to: v1.6.10\n\n[.alert.alert-warning]\n****\nThis upgrade has been removed in v1.6.10. The xref:../wireless-networking/network-transmitter.adoc[] is now cross dimensional by default.\n****\n\nThe Interdimensional Upgrade is an upgrade that allows the xref:../wireless-networking/network-transmitter.adoc[] to work cross-dimensionally.\n\nThis upgrade takes a lot of extra FE/t by default (1000 FE/t extra)."
  },
  {
    "path": "docs/pages/upgrades/range-upgrade.adoc",
    "content": "= Range Upgrade\n:icon: range-upgrade.png\n:from: v0.6.0-alpha\n\nThe {doctitle} increases the range of the xref:../wireless-networking/wireless-transmitter.adoc[].\n\nBy using this upgrade, the amount of FE/t that this device draws will increase."
  },
  {
    "path": "docs/pages/upgrades/regulator-upgrade.adoc",
    "content": "= Regulator Upgrade\n:icon: regulator-upgrade.png\n:from: v1.8.3-beta\n\nThe Regulator Upgrade is an upgrade that can be inserted into an xref:../input-and-output/exporter.adoc[] to keep certain items or fluids in stock in the connected inventory.\n\nIt will try to keep the connected inventory stocked by using items or fluids from the storage network.\n\nAs soon as the upgrade is inserted, you can right click on a filtered item or fluid in the xref:../input-and-output/exporter.adoc[] GUI to configure the amount to keep in stock.\n\nAdditionally, the Regulator Upgrade can be combined with a xref:crafting-upgrade.adoc[] to start autocrafting tasks when the stock from the storage network runs out.\n\nBy using this upgrade, the amount of FE/t that this device draws will increase.\n"
  },
  {
    "path": "docs/pages/upgrades/silk-touch-upgrade.adoc",
    "content": "= Silk Touch Upgrade\n:icon: silk-touch-upgrade.png\n:from: v1.2.0\n\nThe {doctitle} makes the xref:../input-and-output/destructor.adoc[] use Silk Touch on the blocks that it is breaking.\n\nBy using this upgrade, the amount of FE/t that this device draws will increase."
  },
  {
    "path": "docs/pages/upgrades/speed-upgrade.adoc",
    "content": "= Speed Upgrade\n:icon: speed-upgrade.png\n:from: v0.6.0-alpha\n\nThe {doctitle} will increase the speed of the device that it is being inserted to.\n\nBy using this upgrade, the amount of FE/t that this device draws will increase."
  },
  {
    "path": "docs/pages/upgrades/stack-upgrade.adoc",
    "content": "= Stack Upgrade\n:icon: stack-upgrade.png\n:from: v0.7.7-beta\n\nThe {doctitle} will improve item or fluid transfer speeds by using a whole stack (64 items) instead of 1 item at a time.\n\nIt can be combined with xref:speed-upgrade.adoc[speed upgrades] to let the device go to the next slot quicker.\n\nBy using this upgrade, the amount of FE/t that this device draws will increase."
  },
  {
    "path": "docs/pages/upgrades/upgrade.adoc",
    "content": "= Upgrade\n:icon: upgrade.png\n:from: v0.6.0-alpha\n\nThe {doctitle} is the base item used for xref:index.adoc[every type of upgrade]."
  },
  {
    "path": "docs/pages/utility/advanced-processor.adoc",
    "content": "= Advanced Processor\n:icon: advanced-processor.png\n:from: v0.3.0-alpha\n\ninclude::../../partials/processor.adoc[]"
  },
  {
    "path": "docs/pages/utility/basic-processor.adoc",
    "content": "= Basic Processor\n:icon: basic-processor.png\n:from: v0.3.0-alpha\n\ninclude::../../partials/processor.adoc[]"
  },
  {
    "path": "docs/pages/utility/block-of-quartz-enriched-iron.adoc",
    "content": "= Block of Quartz Enriched Iron\n:from: v1.4.0-beta\n:icon: block-of-quartz-enriched-iron.png\n\nThe {doctitle} is xref:quartz-enriched-iron.adoc[] in block form."
  },
  {
    "path": "docs/pages/utility/construction-core.adoc",
    "content": "= Construction Core\n:from: v0.3.0-alpha\n:icon: construction-core.png\n\nThe {doctitle} is used in recipes for devices that turn resources from the storage network into resources in the world."
  },
  {
    "path": "docs/pages/utility/cover.adoc",
    "content": "= Cover\n:icon: cover.png\n:from: v1.6.0-alpha\n\nA {doctitle} is an item used to hide xref:../networking/cable.adoc[cables].\n\nYou can also hide blocks that have a cable on them, like the xref:../input-and-output/importer.adoc[] or xref:../input-and-output/exporter.adoc[].\n\nIt will block network connections, xref:../networking/cable.adoc[cables] can't pass through the \"hidden\" side.\n\nThey can be removed by sneaking and right-clicking them with the xref:wrench.adoc[].\n"
  },
  {
    "path": "docs/pages/utility/cut-silicon.adoc",
    "content": "= Cut Silicon\n:icon: cut-silicon.png\n:from: v0.3.0-alpha\n:to: v1.6.6\n\n[.alert.alert-warning]\n****\n{doctitle} has been removed in v1.6.6. It has been replaced with xref:processor-binding.adoc[].\n****\n\n{doctitle} is used to craft the various processors.\nIt is made with a xref:cutting-tool.adoc[]."
  },
  {
    "path": "docs/pages/utility/cutting-tool.adoc",
    "content": "= Cutting Tool\n:icon: cutting-tool.png\n:from: v1.6.0\n:to: v1.7.0-alpha\n\n[.alert.alert-warning]\n****\nThe Cutting Tool has been removed in v1.7.0-alpha.\nCrafting covers now uses an iron nugget instead.\n****\n\nThe Cutting Tool is a tool that is used to craft xref:../utility/cover.adoc[covers]."
  },
  {
    "path": "docs/pages/utility/destruction-core.adoc",
    "content": "= Destruction Core\n:from: v0.3.0-alpha\n:icon: destruction-core.png\n\nThe {doctitle} is used in recipes for devices that turn resources from the world into resources in the storage network."
  },
  {
    "path": "docs/pages/utility/filter.adoc",
    "content": "= Filter\n:icon: filter.png\n:from: v0.8.13-beta\n\nThe {doctitle} is an item that can be used in any xref:../viewing-resources/grid.adoc[].\n\nIn the {doctitle}'s GUI, which can be opened by pressing right click while holding the filter in hand, the player can specify which items and fluids can be visible.\n\n== Items and fluids\n\nThe Grid can filter fluids in the xref:../viewing-resources/fluid-grid.adoc[] and items in any other xref:../viewing-resources/grid.adoc[] by toggling between item and fluid mode.\n\n== {doctitle}ing\n\nThe player can choose to let the filter be damage or damage sensitive.\nIt is also possible to use a mod filter.\n\nThe {doctitle} can be set in a whitelist or blacklist mode, too.\n\n== Icon and name\n\nThe player can also configure an icon and name for the {doctitle}.\n\nIn item and fluid mode an icon can be specified.\n\nAs soon as the {doctitle} has an icon specified, it will appear as a tab in the xref:../viewing-resources/grid.adoc[].\nThen, open the tab to see the filtered items or fluids.\n\n== Clearing\n\nUse SHIFT + right click in your inventory while holding the {doctitle} to clear it.\n"
  },
  {
    "path": "docs/pages/utility/hollow-cover.adoc",
    "content": "= Hollow Cover\n:icon: hollow-cover.png\n:from: v1.6.0\n\nA {doctitle} is the same as a xref:cover.adoc[] but has a hole so that you can pass xref:../networking/cable.adoc[cables] through it.\n\nYou can also put it on the front of an xref:../input-and-output/importer.adoc[] or xref:../input-and-output/exporter.adoc[] to hide part of the block.\n\nIt will let a network signal through.\n\nThey can be removed by sneaking and right-clicking them with the xref:wrench.adoc[].\n\n"
  },
  {
    "path": "docs/pages/utility/improved-processor.adoc",
    "content": "= Improved Processor\n:icon: improved-processor.png\n:from: v0.3.0-alpha\n\ninclude::../../partials/processor.adoc[]"
  },
  {
    "path": "docs/pages/utility/index.adoc",
    "content": "= Utility\n\n- xref:quartz-enriched-iron.adoc[]\n- xref:block-of-quartz-enriched-iron.adoc[]\n- xref:silicon.adoc[]\n- xref:cut-silicon.adoc[]\n- xref:wrench.adoc[]\n- xref:cutting-tool.adoc[]\n- xref:filter.adoc[]\n- xref:machine-casing.adoc[]\n- xref:solderer.adoc[]\n\n== Raw Processors\n\n- xref:processor-binding.adoc[]\n- xref:raw-basic-processor.adoc[]\n- xref:raw-improved-processor.adoc[]\n- xref:raw-advanced-processor.adoc[]\n\n== Processors\n\n- xref:basic-processor.adoc[]\n- xref:improved-processor.adoc[]\n- xref:advanced-processor.adoc[]\n\n== Cores\n\n- xref:construction-core.adoc[]\n- xref:destruction-core.adoc[]\n\n== Covers\n\n- xref:cover.adoc[]\n- xref:hollow-cover.adoc[]"
  },
  {
    "path": "docs/pages/utility/machine-casing.adoc",
    "content": "= Machine Casing\n:icon: machine-casing.png\n:from: v0.3.0-alpha\n\nThe {doctitle} is a block that is used to craft the various Refined Storage devices."
  },
  {
    "path": "docs/pages/utility/processor-binding.adoc",
    "content": "= Processor Binding\n:icon: processor-binding.png\n:from: v1.6.6\n\n{doctitle} is used to craft the various processors."
  },
  {
    "path": "docs/pages/utility/quartz-enriched-iron.adoc",
    "content": "= Quartz Enriched Iron\n:icon: quartz-enriched-iron.png\n:from: v0.3.0-alpha\n\n{doctitle} is like the name says, iron enriched with quartz.\n\nIt is used in almost all the recipes in Refined Storage."
  },
  {
    "path": "docs/pages/utility/raw-advanced-processor.adoc",
    "content": "= Raw Advanced Processor\n:icon: raw-advanced-processor.png\n:from: v0.3.0-alpha\n\nThe {doctitle} is used to craft a xref:advanced-processor.adoc[]."
  },
  {
    "path": "docs/pages/utility/raw-basic-processor.adoc",
    "content": "= Raw Basic Processor\n:icon: raw-basic-processor.png\n:from: v0.3.0-alpha\n\nThe {doctitle} is used to craft a xref:basic-processor.adoc[]."
  },
  {
    "path": "docs/pages/utility/raw-improved-processor.adoc",
    "content": "= Raw Improved Processor\n:icon: raw-improved-processor.png\n:from: v0.3.0-alpha\n\nThe {doctitle} is used to craft a xref:improved-processor.adoc[]."
  },
  {
    "path": "docs/pages/utility/silicon.adoc",
    "content": "= Silicon\n:icon: silicon.png\n:since: v0.3.0-alpha\n\n{doctitle} can be obtained by smelting quartz.\n\nThis item has no use other than being used in crafting recipes."
  },
  {
    "path": "docs/pages/utility/solderer.adoc",
    "content": "= Solderer\n:icon: solderer.png\n:from: v0.3.0-alpha\n:to: v1.6.0\n\n[.alert.alert-warning]\n****\nThe {doctitle} has been removed in v1.6.0. It has been replaced with xref:processor-binding.adoc[].\n****\n\nThe {doctitle} is a device that is used to craft several items and blocks.\n\nThe {doctitle} is not sided.\nYou can insert from any side and it'll automatically put the items in the right slot.\n\nUse of link:https://minecraft.curseforge.com/projects/jei[JEI (Just Enough Items)] is (highly) recommended to see the recipes of the {doctitle}.\n\n== Applicable upgrades\n\n- xref:../upgrades/speed-upgrade.adoc[]"
  },
  {
    "path": "docs/pages/utility/wrench.adoc",
    "content": "= Wrench\n:icon: wrench.png\n:from: v1.2.0\n\nThe {doctitle} is a tool that can do two things:\n\n- Rotate blocks\n- Break Refined Storage xref:cover.adoc[covers]\n\nSimply sneak and right click when using the {doctitle}."
  },
  {
    "path": "docs/pages/viewing-resources/crafting-grid.adoc",
    "content": "= Crafting Grid\n:icon: crafting-grid.png\n:from: v0.3.0-alpha\n\nThe {doctitle} is the same as a regular xref:grid.adoc[], but has a crafting inventory.\n\nWhen an item is crafted, it won't just clear the crafting slots, but it'll try to retrieve the same items from the storage network again.\n\n== Recipe transferring\n\nThe {doctitle} integrates with link:https://minecraft.curseforge.com/projects/jei[JEI (Just Enough Items)] so the player can use recipe transferring.\n\nRefined Storage will warn you when you don't have the required item present in your inventory, storage network or crafting matrix.\nEven with this warning, you can still transfer items.\n\nIf you don't have some required items, but autocrafting is available for said items, you can press CTRL + CLICK to start autocrafting for said items.\nNote that you need a xref:../autocrafting/pattern.adoc[] configured for these items.\n\ninclude::../../partials/recoloring.adoc[]\n"
  },
  {
    "path": "docs/pages/viewing-resources/fluid-grid.adoc",
    "content": "= Fluid Grid\n:from: v0.9.0-beta\n:icon: fluid-grid.png\n\nThe {doctitle} is the same as a regular xref:grid.adoc[], but is used for viewing fluids in the fluid storage of your storage network.\n\n== Inserting\n\nTo insert a fluid, players can shift click on a fluid container like a bucket in their player inventory while in the {doctitle} GUI.\n\nThe player can also click the fluid container in the GUI to insert it.\n\n== Extracting\n\nPlayers can extract the fluid by clicking on it.\nThe {doctitle} will then fill a bucket with the selected fluid.\n\nRefined Storage will first search an empty bucket in your inventory.\nIf none is found, a bucket will be searched in your storage network.\n\nSome fluids cannot be filled in a bucket, then the only way to extract those fluids is by using an xref:../input-and-output/exporter.adoc[].\n\ninclude::../../partials/recoloring.adoc[]\n"
  },
  {
    "path": "docs/pages/viewing-resources/grid.adoc",
    "content": "= Grid\n:icon: grid.png\n:from: v0.3.0-alpha\n\nThe {doctitle} is a block that allows access to the items and fluids in the storage network.\n\nThe player can extract items or fluids from the central GUI.\n\n[#_controls]\n== Controls\n\n[cols=\"1,1\"]\n|===\n| Type | Description\n\n| Left click | Takes at most 64 items\n| Right click | Takes at most 32 items\n| Middle click | Takes 1 item (removed since v1.9.7)\n| SHIFT + Mouse scroll in the player inventory | Pushes 1 item to or from the player's inventory (since v1.9.7)\n| SHIFT + Mouse scroll in the {doctitle} inventory | Pushes 1 item to or from the {doctitle} inventory (since v1.9.7)\n| CTRL + Mouse scroll | Pushes 1 item to or from the player's mouse (since v1.9.7)\n| SHIFT | Pushes the items to the player's inventory\n| SHIFT + CTRL | Forces the crafting window to open *even if the item or fluid is available*\n| CTRL + X | Clears crafting matrix\n| Right click on search bar | Clears the search query\n| Tab | Selects the search bar when the {doctitle} isn't in autoselection mode\n| When in the crafting start GUI, pressing SHIFT | Skips the crafting preview window\n|===\n\n== Sorting\n\nThe items or fluids in a {doctitle} can be sorted in various ways:\n\n- By name\n- By quantity\n- By item ID\n- Last modified\n- InventoryTweaks sorting (only available if InventoryTweaks is installed)\n\nThe sorting direction can also be chosen (ascending or descending).\n\ninclude::../../partials/search-box.adoc[]\n\n== Filter\n\nIn the sidebar of the {doctitle} there are slots where the player can insert xref:../utility/filter.adoc[filters] to filter certain items in the {doctitle}.\n\n== Tabs\n\nA {doctitle} can also have tabs.\nWhen clicking on the tab, only items configured in the xref:../utility/filter.adoc[] are visible.\n\nTo use tabs in the {doctitle}, make a xref:../utility/filter.adoc[] with an icon specified.\n\nTo have more than 4 tabs, put a xref:../utility/filter.adoc[] in a xref:../utility/filter.adoc[].\n\n== Sizes\n\nThe size of any {doctitle} can be configured as well:\n\n- Stretched (default)\n- Small\n- Medium\n- Large\n\nWhen choosing the stretched size, the {doctitle} will take up all the vertical screen space.\nThis can be limited through the `maxRowsStretch` config option.\n\n== Display\n\nThe {doctitle} can be configured to only show craftable items or only non-craftable items.\n\nBy default, the tooltips for items in a {doctitle} are a little bit bigger to display the total item count and the last modified information.\nThis can be turned off by using the `detailedTooltip` config option.\n\nBy default, the {doctitle} uses a small font size to display item or fluid quantities.\nUse the `largeFont` config option to change this.\n\n== Remember search query\n\nThe {doctitle} can be configured to remember the search query when closing and re-opening the GUI.\nYou can do this by modifying the `rememberSearchQuery` config option.\n\n== Prevent sorting while shift is down\n\nBy default, the {doctitle} doesn't perform sorting when you're shift clicking items out of the storage network.\nThis is done to prevent items and fluids shifting around your screen.\n\nAs soon as you stop pressing the shift key, the view is sorted again.\n\nTo disable this behavior, modify the `preventSortingWhileShiftIsDown` config option.\n\ninclude::../../partials/recoloring.adoc[]\n"
  },
  {
    "path": "docs/pages/viewing-resources/how-to-view-resources.adoc",
    "content": "= How to view resources\n\n== Grid\n\nYou can use the xref:grid.adoc[], xref:crafting-grid.adoc[] or xref:fluid-grid.adoc[] to view resources in your network.\n\n[#_wireless_access]\n== Wireless access\n\nRefined Storage has extensive wireless abilities to access your storage network remotely.\n\nCraft a xref:../wireless-networking/wireless-grid.adoc[] and right click it on a xref:../networking/controller.adoc[].\n\nCraft a xref:../wireless-networking/wireless-transmitter.adoc[] and add it to your network.\nYou can now access your storage in a radius around the xref:../wireless-networking/wireless-transmitter.adoc[].\n\nWant a higher range?\nSimply place multiple xref:../wireless-networking/wireless-transmitter.adoc[wireless transmitters] around your world, but not next to each other.\n\n== Portable Grid\n\nWant to access an individual xref:../storage/index.adoc#_storage_disks[storage disk]?\nUse a xref:portable-grid.adoc[].\n\nGive it energy and insert a disk, and you're good to go.\nIt doesn't depend on a storage network.\n\n== Storage Monitor\n\nWant to see how much you have of an item in your storage network?\nConnect a xref:storage-monitor.adoc[] and configure an item to display.\n\nYou can then see how much you have of that item and interact with it by inserting or extracting multiple items at once."
  },
  {
    "path": "docs/pages/viewing-resources/index.adoc",
    "content": "= Viewing resources\n\n- xref:how-to-view-resources.adoc[]\n- xref:grid.adoc[]\n- xref:crafting-grid.adoc[]\n- xref:fluid-grid.adoc[]\n- xref:storage-monitor.adoc[]\n- xref:portable-grid.adoc[]\n"
  },
  {
    "path": "docs/pages/viewing-resources/portable-grid.adoc",
    "content": "= Portable Grid\n:icon: portable-grid.png\n:from: v1.4.5-beta\n\nThe {doctitle} is a portable storage that isn't connected to a network.\nIt allows you to interact with a xref:../storage/index.adoc#_storage_disks[storage disk] while not being connected to a network.\n\nAs soon as you insert a xref:../storage/index.adoc#_storage_disks[storage disk], you can access the contents of your xref:../storage/index.adoc#_storage_disks[storage disk] in the grid view.\n\nIt's essentially a xref:../storage/disk-drive.adoc[] and xref:grid.adoc[] in one block or item.\nIt can be placed in the world, or, be used as a handheld device as well.\n\nTo place it in the world hold the {doctitle} while sneaking.\n\n== Energy behavior\n\nTo use the {doctitle} the item or block needs Forge Energy (FE).\n\nThe {doctitle} draws energy on following actions:\n\n[cols=\"1,1\"]\n|===\n|Action|Amount of Forge Energy drawed\n\n|Opening the {doctitle}|30 FE\n|Extracting an item or fluid from storage|3 FE\n|Inserting an item or fluid to storage|3 FE\n|==="
  },
  {
    "path": "docs/pages/viewing-resources/storage-monitor.adoc",
    "content": "= Storage Monitor\n:icon: storage-monitor.png\n:from: v1.4.1-beta\n\nThe {doctitle} is a block that displays the current amount of a certain item or fluid in your storage system.\n\n== Configuration\n\nUse SHIFT + right click on the block to open a GUI to configure the item or fluid being displayed.\n\n== Item inserting and extracting\n\n- You can extract the item specified from the system by left clicking\n- Regular left click for a full stack (64 items)\n- Shift left click for 1 of a stack (1 item)\n- You can insert items from your inventory that match the item being displayed by right clicking\n- Right click quickly to insert all items matching the item displayed in your\n\n== Fluid inserting and extracting (since v1.8.1)\n\n- You can extract the fluid specified in bucket from from the system by shift left clicking\n- Make sure you have a bucket in your inventory or storage network\n- You can insert fluids from your inventory that match the fluid being displayed by right clicking\n- Make sure you have a fluid container in your inventory that contains the fluid you want to insert"
  },
  {
    "path": "docs/pages/wireless-networking/creative-wireless-crafting-monitor.adoc",
    "content": "= Creative Wireless Crafting Monitor\n:icon: wireless-crafting-monitor.png\n:from: v1.2.1\n\nThe {doctitle} is the same as a regular xref:wireless-crafting-monitor.adoc[] but has infinite energy.\n\nIt can only be obtained in creative mode.\n"
  },
  {
    "path": "docs/pages/wireless-networking/creative-wireless-fluid-grid.adoc",
    "content": "= Creative Wireless Fluid Grid\n:from: v1.4.0-beta\n:icon: wireless-fluid-grid.png\n\nThe {doctitle} is the same as a regular xref:wireless-fluid-grid.adoc[] but has infinite energy.\n\nIt can only be obtained in creative mode."
  },
  {
    "path": "docs/pages/wireless-networking/creative-wireless-grid.adoc",
    "content": "= Creative Wireless Grid\n:icon: wireless-grid.png\n:from: v0.5.3-alpha\n\nThe {doctitle} is the same as a regular xref:wireless-grid.adoc[] but has infinite energy.\n\nIt can only be obtained in creative mode."
  },
  {
    "path": "docs/pages/wireless-networking/index.adoc",
    "content": "= Wireless networking\n\n- xref:networks-over-long-distances.adoc[]\n\n== Wireless tools\n\n- xref:wireless-transmitter.adoc[]\n- xref:wireless-grid.adoc[]\n- xref:creative-wireless-grid.adoc[]\n- xref:wireless-fluid-grid.adoc[]\n- xref:creative-wireless-fluid-grid.adoc[]\n- xref:wireless-crafting-monitor.adoc[]\n- xref:creative-wireless-crafting-monitor.adoc[]\n- xref:wireless-crafting-grid.adoc[]\n\n== Wireless networks\n\n- xref:network-card.adoc[]\n- xref:network-receiver.adoc[]\n- xref:network-transmitter.adoc[]\n"
  },
  {
    "path": "docs/pages/wireless-networking/network-card.adoc",
    "content": "= Network Card\n:from: v0.8.13-beta\n:icon: network-card.png\n\nA {doctitle} is an item that stores the coordinates of a xref:network-receiver.adoc[].\n\nThe player has to insert the {doctitle} in a xref:network-transmitter.adoc[]."
  },
  {
    "path": "docs/pages/wireless-networking/network-receiver.adoc",
    "content": "= Network Receiver\n:icon: network-receiver.png\n:from: v0.8.13-beta\n\nThe {doctitle} is the block that receives a signal from the xref:network-transmitter.adoc[].\n\nIn order for the {doctitle} to work reliably the {doctitle} has to be chunkloaded.\n\ninclude::../../partials/recoloring.adoc[]\n\n== Using Refined Storage v1.7.x or v1.8.x?\n\nCross dimensional functionality isn't available in this version.\n"
  },
  {
    "path": "docs/pages/wireless-networking/network-transmitter.adoc",
    "content": "= Network Transmitter\n:icon: network-transmitter.png\n:from: v0.8.13-beta\n\nA {doctitle} sends a network signal to a xref:network-receiver.adoc[] that is specified in the given xref:network-card.adoc[].\n\nIn order for the {doctitle} to work the xref:../networking/controller.adoc[] where the {doctitle} is connected to has to be chunkloaded.\n\nThe {doctitle} can work in the current dimension or across different dimensions.\n\ninclude::../../partials/recoloring.adoc[]\n\n== Using Refined Storage v1.7.x or v1.8.x?\n\nCross dimensional functionality isn't available in this version."
  },
  {
    "path": "docs/pages/wireless-networking/networks-over-long-distances.adoc",
    "content": "= Networks over long distances\n\nRefined Storage supports 2 scenarios for long distance networking:\n\n- xref:../viewing-resources/how-to-view-resources.adoc#_wireless_access[Viewing your resources wirelessly]\n- Extending a network over a long distance without using cables (see below)\n\n== The problem\n\nSometimes, you may have different areas all scattered throughout your world.\n\nHere is the problem: you want access to your Refined Storage system on all of those areas.\n\nYou could lay xref:../networking/cable.adoc[] from your base to every area, but what if said area is 1000 blocks away?\nAre you really going to craft 1000 xref:../networking/cable.adoc[cables]?\nDidn't think so.\n\n== The solution\n\nUse the xref:network-transmitter.adoc[] and xref:network-receiver.adoc[].\n\nSimply craft a xref:network-transmitter.adoc[] and connect it to your Refined Storage system in your main base.\n\nNext up, craft a xref:network-card.adoc[].\nI'll be telling what you need this for in a second, bear with me.\n\nAfter crafting a xref:network-card.adoc[], craft a xref:network-receiver.adoc[] and place it in the area far away from your base. \n\nIf the xref:network-receiver.adoc[] was added to an existing network, remove the xref:../networking/controller.adoc[] from that network, the receiver will act as a controller.\n\nTake the xref:network-card.adoc[] and right click it on the xref:network-receiver.adoc[].\n\nPut the xref:network-card.adoc[] in the xref:network-transmitter.adoc[] so the xref:network-transmitter.adoc[] knows where to send a signal to.\n\nAnd now you are done.\nSimply connect machines to your xref:network-receiver.adoc[] according to the normal machine connecting rules.\n\nI suppose you could treat the xref:network-receiver.adoc[] as a xref:...\n\n== One very important thing to note\n\nThe xref:../networking/controller.adoc[] in your main base and the xref:network-receiver.adoc[] in the other area **both** have to be chunkloaded **before** linking it to the network.\n\nAfter linking, both areas have to stay chunkloaded.\n\n== Using Refined Storage v1.7.x or v1.8.x?\n\nCross dimensional functionality isn't available in this version.\n"
  },
  {
    "path": "docs/pages/wireless-networking/wireless-crafting-grid.adoc",
    "content": "= Wireless Crafting Grid\n:icon: wireless-crafting-grid.png\n\nWith the {doctitle} the player can access their items and has the ability to craft using a crafting matrix from anywhere.\n\nIt is not available in the base Refined Storage mod, but in Refined Storage Addons.\n\nTo activate the {doctitle}, the player has to right-click the {doctitle} on a xref:../networking/controller.adoc[].\nIf you're playing on Refined Storage v1.7.x or higher you can bind the {doctitle} by right clicking on any connected network device.\n\nTo use the {doctitle} the item needs Forge Energy.\nYou'll have to charge it in a block that charges items from another mod.\n\nAfter doing all these steps, the {doctitle} is still missing a signal from the storage network.\nAdd at least 1 xref:wireless-transmitter.adoc[] to the network to get a basic range of 16 blocks.\n\nIf the {doctitle} is ready for use, it will light up blue.\n\n== Troubleshooting\n\nSometimes, the {doctitle} doesn't open or stays gray.\nTo enable it make sure that:\n\n- The {doctitle} is bound to a xref:../networking/controller.adoc[]\n- There is at least 1 xref:wireless-transmitter.adoc[] connected to the network\n- That you are in range of the xref:wireless-transmitter.adoc[]\n- The xref:../networking/controller.adoc[] block is still in the world on the place where you bound it to\n\n== Energy behavior\n\nThe {doctitle} draws energy on following actions:\n\n[cols=\"1,1\"]\n|===\n|Action|Amount of Forge Energy used\n\n|Opening the {doctitle}|30 FE\n|Pulling an item from storage|3 FE\n|Pushing an item to storage|3 FE\n|Crafting an item|1 FE\n|Clearing the crafting matrix|10 FE\n|==="
  },
  {
    "path": "docs/pages/wireless-networking/wireless-crafting-monitor.adoc",
    "content": "= Wireless Crafting Monitor\n:icon: wireless-crafting-monitor.png\n:from: v1.2.1\n\nWith the {doctitle} the player can see what is crafting from anywhere.\n\nTo activate the {doctitle}, the player has to right click the {doctitle} on a xref:../networking/controller.adoc[].\nIf you're playing on Refined Storage v1.7.x or higher you can bind the {doctitle} by right clicking on any connected network device.\n\nTo use the {doctitle} the item needs Forge Energy.\nYou'll have to charge it in a block that charges items from another mod.\n\nAfter doing all these steps, the {doctitle} is still missing a signal from the system.\nAdd at least 1 xref:wireless-transmitter.adoc[] to the network to get a basic range of 16 blocks.\n\nIf the {doctitle} is ready for use, it will light up blue.\n\n== Troubleshooting\n\nSometimes, the {doctitle} doesn't open or stays grey.\nTo enable it make sure that:\n\n- The {doctitle} is bound to a xref:../networking/controller.adoc[]\n- There is at least 1 xref:wireless-transmitter.adoc[] connected to the network\n- That you are in range of the xref:wireless-transmitter.adoc[]\n- The xref:../networking/controller.adoc[] block is still in the world on the place where you bound it to\n\n== Energy behavior\n\nThe {doctitle} draws energy on following actions:\n\n[cols=\"1,1\"]\n|===\n|Action|Amount of Forge Energy used\n\n|Opening the {doctitle}|35 FE\n|Cancelling a task|4 FE\n|Cancelling all tasks|5 FE\n|==="
  },
  {
    "path": "docs/pages/wireless-networking/wireless-fluid-grid.adoc",
    "content": "= Wireless Fluid Grid\n:icon: wireless-fluid-grid.png\n:from: v1.4.0-beta\n\nWith the {doctitle} the player can access their fluids from anywhere.\n\nTo activate the {doctitle}, the player has to right click the {doctitle} on a xref:../networking/controller.adoc[].\nIf you're playing on Refined Storage v1.7.x or higher you can bind the {doctitle} by right clicking on any connected network device.\n\nTo use the {doctitle} the item needs Forge Energy.\nYou'll have to charge it in a block that charges items from another mod.\n\nAfter doing all these steps, the {doctitle} is still missing a signal from the system.\nAdd at least 1 xref:wireless-transmitter.adoc[] to the network to get a basic range of 16 blocks.\n\nIf the {doctitle} is ready for use, it will light up blue.\n\n== Troubleshooting\n\nSometimes, the {doctitle} doesn't open or stays gray.\nTo enable it make sure that:\n\n- The {doctitle} is bound to a xref:../networking/controller.adoc[]\n- There is at least 1 xref:wireless-transmitter.adoc[] connected to the network\n- That you are in range of the xref:wireless-transmitter.adoc[]\n- The xref:../networking/controller.adoc[] block is still in the world on the place where you bound it to\n\n== Energy behavior\n\nThe {doctitle} draws energy on following actions:\n\n[cols=\"1,1\"]\n|===\n|Action|Amount of Forge Energy used\n\n|Opening the {doctitle}|30 FE\n|Pulling a fluid from storage|3 FE\n|Pushing a fluid to storage|3 FE\n|==="
  },
  {
    "path": "docs/pages/wireless-networking/wireless-grid.adoc",
    "content": "= Wireless Grid\n:from: v0.3.0-alpha\n:icon: wireless-grid.png\n\nWith the {doctitle} the player can access their items from anywhere.\n\nTo activate the {doctitle}, the player has to right click the {doctitle} on a xref:../networking/controller.adoc[].\nIf you're playing on Refined Storage v1.7.x or higher you can bind the {doctitle} by right clicking on any connected network device.\n\nTo use the {doctitle} the item needs Forge Energy (FE).\nYou'll have to charge it in a block that charges items from another mod.\n\nAfter doing all these steps, the {doctitle} is still missing a signal from the storage network.\nAdd at least 1 xref:wireless-transmitter.adoc[] to the network to get a basic range of 16 blocks.\n\nIf the {doctitle} is ready for use, it will light up blue.\n\n== Troubleshooting\n\nSometimes, the {doctitle} doesn't open or stays gray.\nTo enable it make sure that:\n\n- The {doctitle} is bound to a xref:../networking/controller.adoc[]\n- There is at least 1 xref:wireless-transmitter.adoc[] connected to the network\n- That you are in range of the xref:wireless-transmitter.adoc[]\n- The xref:../networking/controller.adoc[] block is still in the world on the place where you bound it to\n\n== Energy behavior\n\nThe {doctitle} draws energy on following actions:\n\n[cols=\"1,1\"]\n|===\n|Action|Amount of Forge Energy used\n\n|Opening the {doctitle}|30 FE\n|Pulling an item from storage|3 FE\n|Pushing an item to storage|3 FE\n|==="
  },
  {
    "path": "docs/pages/wireless-networking/wireless-transmitter.adoc",
    "content": "= Wireless Transmitter\n:icon: wireless-transmitter.png\n:from: v0.6.0-alpha\n\nThe {doctitle} is used to send signals to wireless network items in Refined Storage.\n\n== Range\n\nThe default range is 16 blocks, but can be upgraded with xref:../upgrades/range-upgrade.adoc[range upgrades].\n\n=== Bigger range\n\nKeep in mind, **you are not limited to 1 {doctitle}**!\n\nYou can spread multiple around in your world, each maximally upgraded with xref:../upgrades/range-upgrade.adoc[range upgrades].\n\nNote that every {doctitle} needs to be connected to the network through a xref:../networking/cable.adoc[] or xref:network-receiver.adoc[].\n\n== Placing transmitters efficiently\n\nPlacing 2 {doctitle}s just next to each other will not do that much.\n\nThe wireless signal starts from the {doctitle}'s position, so, if you place 2 transmitters next to each other you'll only have a net gain of 1 block.\n\nInstead, you have to spread your wireless transmitters around.\n\ninclude::../../partials/recoloring.adoc[]\n\n== Applicable upgrades\n\n- xref:../upgrades/range-upgrade.adoc[]"
  },
  {
    "path": "docs/partials/fluid-storage-block.adoc",
    "content": "The {doctitle} is a block that provides the system with storage.\nIt is similar to the xref:../pages/storage/index.adoc#_fluid_storage_disks[fluid storage disk], but can be placed in the world.\n\nWhen breaking the {doctitle}, the fluids that it holds persist, so you won't lose any of your fluids.\n\nThe {doctitle} won't despawn when dropped in the world.\n\n== Priority\n\nA (negative or positive) priority can be chosen (where a higher priority gets higher precedence to place items in).\n\n== Whitelist and blacklist\n\nThere is also a whitelist and blacklist option to only allow or forbid some fluid from entering the {doctitle}.\n\nThe whitelist or blacklist can be configured to be NBT or damage sensitive.\n\n== Mode\n\nThe {doctitle} has support for the following modes:\n\n- Insert and extract (default)\n- Insert only\n- Extract only\n\n== Uncrafting\n\nSneak and right click while holding the empty {doctitle} to retrieve the various parts back:\n\n- The corresponding xref:../pages/storage/index.adoc#_fluid_storage_parts[Fluid Storage Part]\n- xref:../pages/utility/basic-processor.adoc[]\n- xref:../pages/utility/machine-casing.adoc[]\n"
  },
  {
    "path": "docs/partials/fluid-storage-disk.adoc",
    "content": "A {doctitle} is an item where items from the storage system are stored on.\nIt has to be put in a xref:../pages/storage/disk-drive.adoc[].\n\nThe {doctitle} won't despawn when dropped in the world.\n\n== Uncrafting\n\nSneak and right click while holding the empty {doctitle} to retrieve the various parts back:\n\n- The corresponding xref:../pages/storage/index.adoc#_fluid_storage_parts[fluid storage part]\n- xref:../pages/storage/storage-housing.adoc[]\n"
  },
  {
    "path": "docs/partials/processor.adoc",
    "content": "The {doctitle} is used to craft the various Refined Storage devices."
  },
  {
    "path": "docs/partials/recoloring.adoc",
    "content": "== Recoloring\n\nYou can recolor the {doctitle} in 2 ways:\n\n- Using a dye on the {doctitle}\n- Combining the block with a dye as a crafting recipe"
  },
  {
    "path": "docs/partials/search-box.adoc",
    "content": "== Search box modes\n\n[cols=\"1,1\"]\n|===\n|Type|Description\n\n|Normal|The default search box mode\n|Normal (autoselected)|Autoselects the search box\n|JEI synchronized|Synchronizes the search box with JEI\n|JEI synchronized (autoselected)|Synchronizes the search box with JEI and autoselects the search box\n|JEI synchronized (two-way)|Synchronizes the search box with JEI and synchronizes JEI with the search box\n|JEI synchronized (two-way autoselected)|Synchronizes the search box with JEI, synchronizes JEI with the search box and autoselects the search box\n|===\n\n== Search box filters\n\n=== Mod ID or name\n\nPrefix your search query with `@` followed by the mod ID or name to only show items of said mod.\n\nYou can also give search terms after that, so it'll only display certain items of that mod.\n\nFor example:\n\n- `@ic2` will only show link:https://minecraft.curseforge.com/projects/industrial-craft[IndustrialCraft 2] items and blocks\n- `@ic2 nuclear` will only show link:https://minecraft.curseforge.com/projects/industrial-craft[IndustrialCraft 2] items and blocks that have \"nuclear\" in its name\n\n=== Tooltip\n\nPrefix your search query with `#` followed by the tooltip text to search for.\n\n=== Ore dictionary (Refined Storage 1.6.x or lower)\n\nPrefix your search query with `$` followed by the ore dictionary name.\n\nFor example: `$ingot` will only show ingots, because those are listed as `ingotIron`, `ingotGold`, ... in the ore dictionary.\n\n=== Tags (Refined Storage 1.7.x or higher)\n\nPrefix your search query with `$` followed by the tag name.\n\nFor example: `$gem` will show all items marked as a gem in the item tags.\n\n=== Searching multiple items\n\nYou can use the `|` symbol to search for multiple items at once.\n\nFor example: to look for ingots and dirt, use: `ingot|dirt`.\n\n== Search box history\n\nUse the up and down arrow keys to scroll through the search box history."
  },
  {
    "path": "docs/partials/storage-block.adoc",
    "content": "The {doctitle} is a block that provides the system with storage.\nIt is similar to the xref:../pages/storage/index.adoc#_storage_disks[storage disk], but can be placed in the world.\n\nWhen breaking the {doctitle}, the items that it holds persist, so you won't lose any of your items.\n\nThe {doctitle} won't despawn when dropped in the world.\n\n== Priority\n\nA (negative or positive) priority can be chosen (where a higher priority gets higher precedence to place items in).\n\n== Whitelist and blacklist\n\nThere is also a whitelist and blacklist option to only allow or forbid some items from entering the {doctitle}.\n\nThe whitelist or blacklist can be configured to be NBT or damage sensitive.\n\n== Mode\n\nThe {doctitle} has support for the following modes:\n\n- Insert and extract (default)\n- Insert only\n- Extract only\n\n== Uncrafting\n\nSneak and right click while holding the empty {doctitle} to retrieve the various parts back:\n\n- The corresponding xref:../pages/storage/index.adoc#_storage_parts[Storage Part]\n- xref:../pages/utility/basic-processor.adoc[]\n- xref:../pages/utility/machine-casing.adoc[]"
  },
  {
    "path": "docs/partials/storage-disk.adoc",
    "content": "A {doctitle} is an item where items from the storage network are stored on.\nIt has to be put in a xref:../pages/storage/disk-drive.adoc[].\n\nThe {doctitle} won't despawn when dropped in the world.\n\n== Uncrafting\n\nSneak and right click while holding the empty {doctitle} to retrieve the various parts back:\n\n- The corresponding xref:../pages/storage/index.adoc#_storage_parts[storage part]\n- xref:../pages/storage/storage-housing.adoc[]\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-8.5-bin.zip\nnetworkTimeout=10000\nvalidateDistributionUrl=true\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradle.properties",
    "content": "# Sets default memory used for gradle commands. Can be overridden by user or command line properties.\n# This is required to provide enough memory for the Minecraft decompilation process.\norg.gradle.jvmargs=-Xmx3G\norg.gradle.daemon=false"
  },
  {
    "path": "gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\nAPP_HOME=$( cd \"${APP_HOME:-./}\" && pwd -P ) || exit\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=${0##*/}\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n# Collect all arguments for the java command;\n#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of\n#     shell script including quotes and variable substitutions, so put them in\n#     double quotes to make sure that they get re-expanded; and\n#   * put everything else in single quotes, so that it's not re-expanded.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        org.gradle.wrapper.GradleWrapperMain \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@rem\n@rem Copyright 2015 the original author or authors.\n@rem\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\n@rem you may not use this file except in compliance with the License.\n@rem You may obtain a copy of the License at\n@rem\n@rem      https://www.apache.org/licenses/LICENSE-2.0\n@rem\n@rem Unless required by applicable law or agreed to in writing, software\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n@rem See the License for the specific language governing permissions and\n@rem limitations under the License.\n@rem\n\n@if \"%DEBUG%\"==\"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif %ERRORLEVEL% equ 0 goto execute\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto execute\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\n\n:end\n@rem End local scope for the variables with windows NT shell\nif %ERRORLEVEL% equ 0 goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nset EXIT_CODE=%ERRORLEVEL%\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\nexit /b %EXIT_CODE%\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "images/description.md",
    "content": "![Refined Storage logo](https://i.imgur.com/Ro6lk7U.png)\n\n## Refined Storage is a mass storage mod for Minecraft that offers the player a network-based storage system, allowing them to store items and fluids on a massively expandable device network.\n\n---\n\nItems and fluids can be stored in one of the many storage capabilities that the mod offers. Any storage devices connected to the same network are accessible to the player through one simple Grid interface, allowing the player to access the inventories of many devices through a single unified GUI.\n\nThis mod not only adds storage solutions, but also devices that can be used to manipulate items and blocks in the world and from within the system, such as importers, exporters, constructors, destructors, and more! There are also devices in this mod that allow the player to setup auto-crafting, allowing the crafting of complex recipes in a few simple clicks.\n"
  },
  {
    "path": "src/generated/resources/.cache/59eb3dbb5f86130e09b3c62d89b9525ee01cf52d",
    "content": "// 1.20.4\t2024-02-12T20:34:18.534056485\tLoot Tables\n24df81614f6b28c4c7e59589d79fd2c929d71727 data/refinedstorage/loot_tables/blocks/black_controller.json\naadbec0f79a3fb95d39e866a453cfec0cbbacd36 data/refinedstorage/loot_tables/blocks/black_crafter.json\na792eb6ac90ce775052c9c4a1b29bf9551477b5d data/refinedstorage/loot_tables/blocks/black_crafter_manager.json\n8d35a75c3113cc686903be08841f9947a4e283ac data/refinedstorage/loot_tables/blocks/black_crafting_grid.json\n012ad0521b80c1702b2bc3e40f497e7183d026d5 data/refinedstorage/loot_tables/blocks/black_crafting_monitor.json\n4c0821c26133436eb65a6d3f9582ace6645022b6 data/refinedstorage/loot_tables/blocks/black_creative_controller.json\n637e7efcb6f118e02ccff1ee8a4e942941c5f752 data/refinedstorage/loot_tables/blocks/black_detector.json\n7999fa88db679231287dc5f26e6ec806e4f960a8 data/refinedstorage/loot_tables/blocks/black_disk_manipulator.json\nb50c133cdeb92695c8dce45b51ddcc38f62170bd data/refinedstorage/loot_tables/blocks/black_fluid_grid.json\n63d1d4f37b3ffbeb4fc1ade464d75eecbd6d1bc0 data/refinedstorage/loot_tables/blocks/black_grid.json\nc4ae253974a27ea4a2eb4a1886fe1fd563662387 data/refinedstorage/loot_tables/blocks/black_network_receiver.json\nc9ac403f6e8cc119e2c0301a2986386458db8c44 data/refinedstorage/loot_tables/blocks/black_network_transmitter.json\nee63465c82f3b6057724a18d4191b75d61e594fb data/refinedstorage/loot_tables/blocks/black_pattern_grid.json\ndfdc5c4b6a29d6d09a9f978ae72d416c747d49f5 data/refinedstorage/loot_tables/blocks/black_relay.json\n57b43a2820cdc36a1149bdd09787a7ac93261f5a data/refinedstorage/loot_tables/blocks/black_security_manager.json\ne304e42fe33afc5255989a8e8d347024b1427128 data/refinedstorage/loot_tables/blocks/black_wireless_transmitter.json\n0296cc57b6041564bb8fed5e0a932deb84d4bf05 data/refinedstorage/loot_tables/blocks/blue_controller.json\na08dd8907fc5779207804aa2cb4193c9dd5eab1c data/refinedstorage/loot_tables/blocks/blue_crafter.json\n56b6e9d582e51c0dca14235c419c8bf61c8af6ed data/refinedstorage/loot_tables/blocks/blue_crafter_manager.json\na4302c275277be4cf7d0390e6d1ea0992416cf21 data/refinedstorage/loot_tables/blocks/blue_crafting_grid.json\n0da6d20c18230429cec259adb30b4424c9778093 data/refinedstorage/loot_tables/blocks/blue_crafting_monitor.json\n8a3784d5c3d51182678726274fcc79fdef70d498 data/refinedstorage/loot_tables/blocks/blue_creative_controller.json\n050ec8e7340ec97b68f480d7c6901d7d5510dc60 data/refinedstorage/loot_tables/blocks/blue_detector.json\n93e877f743d1ccf6bb6eba3c60af1554a429815d data/refinedstorage/loot_tables/blocks/blue_disk_manipulator.json\n14921e4a33424e7441d5fd0b4fdc3668460b7e12 data/refinedstorage/loot_tables/blocks/blue_fluid_grid.json\nfb0553be84143db66f967729b738b2324e0dca77 data/refinedstorage/loot_tables/blocks/blue_grid.json\n6447a482f3af9307a4fd8a8fd1a23cb875639b79 data/refinedstorage/loot_tables/blocks/blue_network_receiver.json\n33e0950230a312281fce50d688678b2aff26a474 data/refinedstorage/loot_tables/blocks/blue_network_transmitter.json\nbe8e6e5fea118107b59f89ce0f404b5fef9761a7 data/refinedstorage/loot_tables/blocks/blue_pattern_grid.json\necf55accdc040cada2d4e7eefda8cac6f2a4ce14 data/refinedstorage/loot_tables/blocks/blue_relay.json\n673c38ad280709ac1662e8bc58a9f8229764b7f4 data/refinedstorage/loot_tables/blocks/blue_security_manager.json\n08b72ed148b8e1728c58011ff0ddc8d5a466e940 data/refinedstorage/loot_tables/blocks/blue_wireless_transmitter.json\nb3237ea64098bd1fbf71c63fffc759093b874865 data/refinedstorage/loot_tables/blocks/brown_controller.json\n914fbbb04e5f9bb9352d875afc3cd63d7abc9f63 data/refinedstorage/loot_tables/blocks/brown_crafter.json\n3d3f99a92764bd9d89a40821c0851979b19d3971 data/refinedstorage/loot_tables/blocks/brown_crafter_manager.json\n460b1ee39206de106a690b05a4a0a9b4a2f11b00 data/refinedstorage/loot_tables/blocks/brown_crafting_grid.json\n18d4fd48da652f3399d464b86445e5dd80188b28 data/refinedstorage/loot_tables/blocks/brown_crafting_monitor.json\neda5a766276ec827ef9d7f0cd6a5270d06036b37 data/refinedstorage/loot_tables/blocks/brown_creative_controller.json\n86e9f01aa04c79323d242d46dc5f78663523fea7 data/refinedstorage/loot_tables/blocks/brown_detector.json\n902cecd6312f228465cd2997070ae621db076fd2 data/refinedstorage/loot_tables/blocks/brown_disk_manipulator.json\n95168aebbc23eba242dab32f7a3cb7ab88918839 data/refinedstorage/loot_tables/blocks/brown_fluid_grid.json\n59ec70614a7a75b94522cb20c8e3462496f995bf data/refinedstorage/loot_tables/blocks/brown_grid.json\ned0877cc6b64179d6cc13ebcca44d6b663d90e6b data/refinedstorage/loot_tables/blocks/brown_network_receiver.json\n4a23a64fcefa7a944877c0df463989c39c7812ac data/refinedstorage/loot_tables/blocks/brown_network_transmitter.json\n4770d6f0799098bb682bc2ef2779c9d6f5f706fe data/refinedstorage/loot_tables/blocks/brown_pattern_grid.json\na5bf6fb6fd9deda0086a8f668f6df4b9a6968020 data/refinedstorage/loot_tables/blocks/brown_relay.json\n20844d7fa89051d608178eac9557f56a3e8086b4 data/refinedstorage/loot_tables/blocks/brown_security_manager.json\n9e012b0d20c6b027ccbaa244424c48ae1edab87d data/refinedstorage/loot_tables/blocks/brown_wireless_transmitter.json\n13eaf1d8f3590c76ae60cad2b0e245946dba0491 data/refinedstorage/loot_tables/blocks/controller.json\nb0acafdeb359996979dda5951c75e93b533ed405 data/refinedstorage/loot_tables/blocks/crafter.json\nd39773a6d3f107a7068357d69936312e13811046 data/refinedstorage/loot_tables/blocks/crafter_manager.json\n5d66d52291db34ac4b2f15572654a73e2f230d06 data/refinedstorage/loot_tables/blocks/crafting_grid.json\n8ded2143b0001e35db03f982b69ecde40d8d8f77 data/refinedstorage/loot_tables/blocks/crafting_monitor.json\ncce990773ee788735e2a2b683e971b4b23d607c1 data/refinedstorage/loot_tables/blocks/creative_controller.json\n67345bd6e3b6c0b8d508a7616181c3115e97cc02 data/refinedstorage/loot_tables/blocks/cyan_controller.json\n20fc40541c376fd28727c7836cf7822400e0aa74 data/refinedstorage/loot_tables/blocks/cyan_crafter.json\nf0b8b0b499d202ec7e237f15b89ce1025e24339f data/refinedstorage/loot_tables/blocks/cyan_crafter_manager.json\n2eab8b310091b32b0ab453b9debb156c23d200a0 data/refinedstorage/loot_tables/blocks/cyan_crafting_grid.json\n7e4f01e9c94edbd6c216be21658f044340207df9 data/refinedstorage/loot_tables/blocks/cyan_crafting_monitor.json\n11074d09ba1cc7c04b17b07f9f481b408d07a807 data/refinedstorage/loot_tables/blocks/cyan_creative_controller.json\ndb6b92cae914d6e33b365da52b1d1a1a50b5d90c data/refinedstorage/loot_tables/blocks/cyan_detector.json\n23dd314b2db7817a2a506a6ddcb6cd46828e98c0 data/refinedstorage/loot_tables/blocks/cyan_disk_manipulator.json\n7ce3366b8ca5a0fbeb460118b4fe4511054343b4 data/refinedstorage/loot_tables/blocks/cyan_fluid_grid.json\n40aac1ca0fcde10b0cd17bfd1fa21d9a0972e5dd data/refinedstorage/loot_tables/blocks/cyan_grid.json\nf05d82fea559ca7e2d45e246b577eaf6b5c49ba4 data/refinedstorage/loot_tables/blocks/cyan_network_receiver.json\na3dc355c2a4c4d38a90662bf9ebaedb606d42280 data/refinedstorage/loot_tables/blocks/cyan_network_transmitter.json\n4c5ceb9196f030d7aef1716556f205a7ce79c583 data/refinedstorage/loot_tables/blocks/cyan_pattern_grid.json\nc2d4acd3c98dd473b0d80b5961592a8d61f96191 data/refinedstorage/loot_tables/blocks/cyan_relay.json\n295d129c7fd49180e9b14058567269571acda43e data/refinedstorage/loot_tables/blocks/cyan_security_manager.json\n56ca30fdf4d256d1392fa90a474094a2ed81a442 data/refinedstorage/loot_tables/blocks/cyan_wireless_transmitter.json\n156eabe81e2ac096f6ca34c39805dec8f1370346 data/refinedstorage/loot_tables/blocks/detector.json\n1d5bc2eaa70e29576d05a2dcd1df639402c34b7e data/refinedstorage/loot_tables/blocks/disk_manipulator.json\n107bc53a7e09fbbc5db214fe0c8a7679456b333d data/refinedstorage/loot_tables/blocks/fluid_grid.json\n2ad4c836fac06bbee7121f506feec44dc1b7c65f data/refinedstorage/loot_tables/blocks/gray_controller.json\nb9857a36d6ee90f53c1c59df8fbc892359394e6b data/refinedstorage/loot_tables/blocks/gray_crafter.json\n6ac770d2b9a4bc57efb306fe9aa94479fa6b4852 data/refinedstorage/loot_tables/blocks/gray_crafter_manager.json\n0f0c0ed12a2d37258914f28b9b3d319cdbac158c data/refinedstorage/loot_tables/blocks/gray_crafting_grid.json\n5e89a416f0f116493c95ced55cc77d14c7fc1e3b data/refinedstorage/loot_tables/blocks/gray_crafting_monitor.json\n376724ab7bff219a1bc7d7f59141fd8fd79b43be data/refinedstorage/loot_tables/blocks/gray_creative_controller.json\n894e4868a4b56b51df079b8d082a8a539c0aa349 data/refinedstorage/loot_tables/blocks/gray_detector.json\nccce676f74305b63d7a45e76d1093d2881cc2d1b data/refinedstorage/loot_tables/blocks/gray_disk_manipulator.json\n9e818613128f3e24f938ea39519998606b2f6107 data/refinedstorage/loot_tables/blocks/gray_fluid_grid.json\nef34eceddddeb3777ba114d25a3b093bb1985139 data/refinedstorage/loot_tables/blocks/gray_grid.json\n7463992e4ea9b61d3dbfcd81341dd8b756a94531 data/refinedstorage/loot_tables/blocks/gray_network_receiver.json\n4f662f4d38ef075c010b0a337a2cd45c9710fcf4 data/refinedstorage/loot_tables/blocks/gray_network_transmitter.json\nce1871ff8079907c0de3e50ceb40802145f98f72 data/refinedstorage/loot_tables/blocks/gray_pattern_grid.json\nc739c4afad2147f0902a1013d53da59e7eb1e656 data/refinedstorage/loot_tables/blocks/gray_relay.json\nfd4af6d41f5612a4ac464d465ad21dce414984dc data/refinedstorage/loot_tables/blocks/gray_security_manager.json\ne1353552c7aed55619efb3ed643fd33eadb13087 data/refinedstorage/loot_tables/blocks/gray_wireless_transmitter.json\n2dd7488f69441e242618f0e9dfeb93abd0bc0ad3 data/refinedstorage/loot_tables/blocks/green_controller.json\n32ccfda148ce86567f186607ae93b2c4117e8d7e data/refinedstorage/loot_tables/blocks/green_crafter.json\nd363818fcbcdd2c51401a534c00065d44fddc0e9 data/refinedstorage/loot_tables/blocks/green_crafter_manager.json\ne1e0d283fdaa6ff9904e1e60f005bedb767b0798 data/refinedstorage/loot_tables/blocks/green_crafting_grid.json\n1d12d626542f20ad4c52ad9f6b6e87db8757b8b2 data/refinedstorage/loot_tables/blocks/green_crafting_monitor.json\n56164ad40e03763835fcbb68d2ff9fbdf5e8171d data/refinedstorage/loot_tables/blocks/green_creative_controller.json\nd2ff277a9a0c37c996e042ce59ddc9c7fe1b92d7 data/refinedstorage/loot_tables/blocks/green_detector.json\nd10680065650631f22d28bc7aade92b2cbb4aada data/refinedstorage/loot_tables/blocks/green_disk_manipulator.json\ne0ce4fd2d89fd0e021dc7d52f48dd107a242f1ec data/refinedstorage/loot_tables/blocks/green_fluid_grid.json\n5c4dff25ce16c01e1bf0fc0e0cd83f87ac195dcf data/refinedstorage/loot_tables/blocks/green_grid.json\n71545b38180cb9bde153577f710bed49e86cbc1d data/refinedstorage/loot_tables/blocks/green_network_receiver.json\n772a687694d40153439ee486788c1072c630dfde data/refinedstorage/loot_tables/blocks/green_network_transmitter.json\n764ac435e57b29770189f5c7a792802540f4dd1a data/refinedstorage/loot_tables/blocks/green_pattern_grid.json\n65321612e15b70f4feb7a0c682a13ed20e22008e data/refinedstorage/loot_tables/blocks/green_relay.json\n95e279728c3bf38953213a3a3e8b4a3df84da9f8 data/refinedstorage/loot_tables/blocks/green_security_manager.json\nd64a37db61317d3c0952740116f231b94602b0d8 data/refinedstorage/loot_tables/blocks/green_wireless_transmitter.json\n8686ebf23a0c2f933f83cb6199fe4df0caf20605 data/refinedstorage/loot_tables/blocks/grid.json\ne9ed2e584a1dcab850e7bae6c0dd92a872b278f4 data/refinedstorage/loot_tables/blocks/light_gray_controller.json\n053a94f2151f2764149cf7d8aa54fc2e70b70c2e data/refinedstorage/loot_tables/blocks/light_gray_crafter.json\n184c45a8c184817e1dbbd6feb03167f1fdcae7d6 data/refinedstorage/loot_tables/blocks/light_gray_crafter_manager.json\nde4a69f0aac181b36d60f145b2b35766b5a09401 data/refinedstorage/loot_tables/blocks/light_gray_crafting_grid.json\n9dbeb212f1973177f8d46dd3e252ac4675c7d65d data/refinedstorage/loot_tables/blocks/light_gray_crafting_monitor.json\naa648985c345347e5e01f8409c0f45727592c4c6 data/refinedstorage/loot_tables/blocks/light_gray_creative_controller.json\n748f422c40c96f5bf2532ecb0d67d8d9fc2fde73 data/refinedstorage/loot_tables/blocks/light_gray_detector.json\n4c4f9259bb20324d683bb3edd6601b6cdfd99d3a data/refinedstorage/loot_tables/blocks/light_gray_disk_manipulator.json\n05b5b11c7a048ff3c00c48321d9b0d64ff28ba50 data/refinedstorage/loot_tables/blocks/light_gray_fluid_grid.json\n4a850d2a9905c8977e6de3d21105945f2442de1f data/refinedstorage/loot_tables/blocks/light_gray_grid.json\n3a83c78d233ba5d80a2cdbb293474fdab177b003 data/refinedstorage/loot_tables/blocks/light_gray_network_receiver.json\n2d66d17b758a77419bb11b2ecdf6f4cd352e0d30 data/refinedstorage/loot_tables/blocks/light_gray_network_transmitter.json\na85a5cc9a326b786474fb9efad32abc3d0afff9b data/refinedstorage/loot_tables/blocks/light_gray_pattern_grid.json\nd780c67d377d8c95afc37f00cf3b41bed969dd5c data/refinedstorage/loot_tables/blocks/light_gray_relay.json\nc47f072a53c7becbab85b2a1fa1e1bcb874f182e data/refinedstorage/loot_tables/blocks/light_gray_security_manager.json\n34300f1c0f498b6525eb884dc828f7f08740644c data/refinedstorage/loot_tables/blocks/light_gray_wireless_transmitter.json\n496511df85e27278e47953fed29d8fd799309e71 data/refinedstorage/loot_tables/blocks/lime_controller.json\nca310f08455606ac4e396fd5bac020693bce6caf data/refinedstorage/loot_tables/blocks/lime_crafter.json\nb1423335fa0c8a09a9e259353399a503466224f2 data/refinedstorage/loot_tables/blocks/lime_crafter_manager.json\nffd8c0eb615b97d850fcef854a769e493c4716ff data/refinedstorage/loot_tables/blocks/lime_crafting_grid.json\n783e77a1007c4493722cfbf350ae87d4de3c7709 data/refinedstorage/loot_tables/blocks/lime_crafting_monitor.json\n63df35073fd082358f319ddfa9151680c8c11a97 data/refinedstorage/loot_tables/blocks/lime_creative_controller.json\n963a9cf50e1637f58168564b8a3e6c79b6f7df31 data/refinedstorage/loot_tables/blocks/lime_detector.json\n5108afbce6b00ba5aebecf5a1b830676c9ab46e0 data/refinedstorage/loot_tables/blocks/lime_disk_manipulator.json\n36c2b8de89a3be3b9c94eb888172f14c597397a1 data/refinedstorage/loot_tables/blocks/lime_fluid_grid.json\n3f06f52d23473176254ded743c65f1a0f705c274 data/refinedstorage/loot_tables/blocks/lime_grid.json\nf7f89777329a9947b78d44aa598130eeeaf46e56 data/refinedstorage/loot_tables/blocks/lime_network_receiver.json\nde0bd3f51fb36d84a1e878e1c245873fdf8d5092 data/refinedstorage/loot_tables/blocks/lime_network_transmitter.json\n7f6e0347cd73c6c32f049bc24b31615774bafb5c data/refinedstorage/loot_tables/blocks/lime_pattern_grid.json\n54b79f03c436a14c01c7336ea7990737c7f0d1a5 data/refinedstorage/loot_tables/blocks/lime_relay.json\n224b225bcfdc170f0e252f5b24cc3ad1cdd22c35 data/refinedstorage/loot_tables/blocks/lime_security_manager.json\n8a1c7b13a82323edf98d35dea2d58a7f67f1be1e data/refinedstorage/loot_tables/blocks/lime_wireless_transmitter.json\nee7f558dcd74223058695bd556e7c9fb4822ab1a data/refinedstorage/loot_tables/blocks/magenta_controller.json\n6c9af4551b92ab22898ef23c97c800fd9f9ecfa8 data/refinedstorage/loot_tables/blocks/magenta_crafter.json\neb99d699ca7fc009e42c9b1ade0cfd15f01a9318 data/refinedstorage/loot_tables/blocks/magenta_crafter_manager.json\nb62eca644682ccb4330ce0bb859887a3699d0e20 data/refinedstorage/loot_tables/blocks/magenta_crafting_grid.json\nc83c3e0c58d11f59777a19417aa95f4d875471a8 data/refinedstorage/loot_tables/blocks/magenta_crafting_monitor.json\ne17fd6f969351f971c45fb4d57d4df9e281f9ba8 data/refinedstorage/loot_tables/blocks/magenta_creative_controller.json\n6a953eb2d9ca8af562bb0d45fc2fe36b40cabb6a data/refinedstorage/loot_tables/blocks/magenta_detector.json\n1301940aa011c199a3317cd69dd6eaf0b1620e54 data/refinedstorage/loot_tables/blocks/magenta_disk_manipulator.json\nffdede2468925a2b10dff6bf5af3b1431c0ca9d8 data/refinedstorage/loot_tables/blocks/magenta_fluid_grid.json\nd7047c8c229ede6bf7ac65047603d25e6f1ed2a2 data/refinedstorage/loot_tables/blocks/magenta_grid.json\nb815c5765403df1462e93a6071ff09cbba46e475 data/refinedstorage/loot_tables/blocks/magenta_network_receiver.json\nac54dab195ac0ab0f50a2839d294784f0521f31b data/refinedstorage/loot_tables/blocks/magenta_network_transmitter.json\n400364c11c26cd3d8f7b71b5ae879fa1d10663fb data/refinedstorage/loot_tables/blocks/magenta_pattern_grid.json\n70fd6ab4e7a23fae99b040cd9af85fb3c45b9ccc data/refinedstorage/loot_tables/blocks/magenta_relay.json\neb72984254ac782338bda19317d843137c19c275 data/refinedstorage/loot_tables/blocks/magenta_security_manager.json\nd14a7e2df81a8227effd234e29d7463aa736d567 data/refinedstorage/loot_tables/blocks/magenta_wireless_transmitter.json\n3b996feb6bb950269703c8b8c739631146ddc9ab data/refinedstorage/loot_tables/blocks/network_receiver.json\nb6fff20f89fe4b20fadb246103f78a02076d6e31 data/refinedstorage/loot_tables/blocks/network_transmitter.json\n9b81c9aa19ae65d547fd9bfb517022eb9999d9a0 data/refinedstorage/loot_tables/blocks/orange_controller.json\n1bef1c8c51963a2e3d6c165fe93d65e6cdfd223e data/refinedstorage/loot_tables/blocks/orange_crafter.json\nf9a701ef8fd365eb00036f7386d1e7fef483ffdf data/refinedstorage/loot_tables/blocks/orange_crafter_manager.json\nb052347226c701e3fbd6fcce2704cdd6a5eec7d2 data/refinedstorage/loot_tables/blocks/orange_crafting_grid.json\nfa4e843e3ece45877f5aa4eb581bb415bb843b2e data/refinedstorage/loot_tables/blocks/orange_crafting_monitor.json\n2c5fdb4fdcbeceda862b78415a46d544d6c799e4 data/refinedstorage/loot_tables/blocks/orange_creative_controller.json\nfeed8d697c60b9e3f5c350495dd09d88c5166186 data/refinedstorage/loot_tables/blocks/orange_detector.json\nd6bed8b23f4f4ca4423e8c7ec2c7ef6508c73883 data/refinedstorage/loot_tables/blocks/orange_disk_manipulator.json\n8b2b1669f6de2119226e7aac025930bbf0547786 data/refinedstorage/loot_tables/blocks/orange_fluid_grid.json\n47d683086d96acd03df1e0a3f39d1650f5042f43 data/refinedstorage/loot_tables/blocks/orange_grid.json\n6028ef5f54524256be2614bf74e6d5a2cd9f37d8 data/refinedstorage/loot_tables/blocks/orange_network_receiver.json\n5eb2338f90194901fde0223b2b8f9cf4df7a1dc5 data/refinedstorage/loot_tables/blocks/orange_network_transmitter.json\na345f55acce3a08adcfa989b466e665b132eaac5 data/refinedstorage/loot_tables/blocks/orange_pattern_grid.json\n05f957b8c247c9ff8e3a52ba2e9eacda9e833901 data/refinedstorage/loot_tables/blocks/orange_relay.json\n40e68229e3680b257c6d27393e3605099d3e1d2d data/refinedstorage/loot_tables/blocks/orange_security_manager.json\n3b406197bc87c8eee2ffff10a3ad8a6b26dd26e1 data/refinedstorage/loot_tables/blocks/orange_wireless_transmitter.json\ne734a87e44a3ab72b839061e2c410b280976abf5 data/refinedstorage/loot_tables/blocks/pattern_grid.json\n7d432b1ca2685d96c5a075eb627c643f1c238478 data/refinedstorage/loot_tables/blocks/pink_controller.json\naabd2cb525aedd90574528aac116e616febae44b data/refinedstorage/loot_tables/blocks/pink_crafter.json\nf95958233f8404103e2e3b12a1f67c65bcda91ad data/refinedstorage/loot_tables/blocks/pink_crafter_manager.json\nc6008a683980e41ecfe85e6eb28b5172e8ea1647 data/refinedstorage/loot_tables/blocks/pink_crafting_grid.json\nf2b276ed4fcee2b2496f618865b81ba9d20ef349 data/refinedstorage/loot_tables/blocks/pink_crafting_monitor.json\nde731f64d79adb6d72a7718fcbf8a08057364429 data/refinedstorage/loot_tables/blocks/pink_creative_controller.json\n1fa8402228b423d6837db0f0f0a89b2b977386e3 data/refinedstorage/loot_tables/blocks/pink_detector.json\n7b6aedb2e39cfd039c12fa965e544874fec3bb6e data/refinedstorage/loot_tables/blocks/pink_disk_manipulator.json\n8b68b1adfaf61ec47065b240780486093fa44d8d data/refinedstorage/loot_tables/blocks/pink_fluid_grid.json\n5aad68b152ce93baacdd3782e9741a23a86bff66 data/refinedstorage/loot_tables/blocks/pink_grid.json\n1cd050c613c6ebf27dbc7b600b35ff5209c92da3 data/refinedstorage/loot_tables/blocks/pink_network_receiver.json\n1ffe3968b44d6412c7d46998b1b8dceb059d8e38 data/refinedstorage/loot_tables/blocks/pink_network_transmitter.json\n4a23c78a95c2a5d8acc68fc6f291565b209c7a9e data/refinedstorage/loot_tables/blocks/pink_pattern_grid.json\n467014d74cf161a2c3a6361a8ee6c22533ce55f2 data/refinedstorage/loot_tables/blocks/pink_relay.json\n64038f767f4cf1328f997b40bb40a172d13b8c55 data/refinedstorage/loot_tables/blocks/pink_security_manager.json\nc07f1e1a05d68d8a35b1fc5dcd432cf8b578e2cf data/refinedstorage/loot_tables/blocks/pink_wireless_transmitter.json\nf0e9df045caf7a2a5ab026acaee0c0b63467459d data/refinedstorage/loot_tables/blocks/purple_controller.json\necf72bb58c1416d231041cdf6597d5985ac3bf63 data/refinedstorage/loot_tables/blocks/purple_crafter.json\n58b286402377dd10c026710ee30c6c3210a65a07 data/refinedstorage/loot_tables/blocks/purple_crafter_manager.json\n2427fc724d952fc259157b04e7e47e9a9adf9aef data/refinedstorage/loot_tables/blocks/purple_crafting_grid.json\n913e0ef93af29c19bbefe95061b5a95894b3d77f data/refinedstorage/loot_tables/blocks/purple_crafting_monitor.json\nf3175f9f9415c65280c9d43a8deae5825afecdbd data/refinedstorage/loot_tables/blocks/purple_creative_controller.json\n8281ca3173c8f137dca52f4d8b15e8ae62328323 data/refinedstorage/loot_tables/blocks/purple_detector.json\n69c32db236c4a4c5ab97f17f1b6c7e9470c24180 data/refinedstorage/loot_tables/blocks/purple_disk_manipulator.json\n6a5cd1a241a9824a80020daf0bdf86b36eebf2e1 data/refinedstorage/loot_tables/blocks/purple_fluid_grid.json\n91c69a86c61dfaa9183548f9a4b9d3bb6d457ae6 data/refinedstorage/loot_tables/blocks/purple_grid.json\nd142bb7058ad7ab11a69fa3cdda0d493dd0fd8e5 data/refinedstorage/loot_tables/blocks/purple_network_receiver.json\n12410d1595702c613b4dd65e1292e604c808e002 data/refinedstorage/loot_tables/blocks/purple_network_transmitter.json\nf40cad0e109abd767ef8dd083f29ecf81eec4021 data/refinedstorage/loot_tables/blocks/purple_pattern_grid.json\n7b2a23a5f7d5ef7768dcad8f1e1dddbed80911f0 data/refinedstorage/loot_tables/blocks/purple_relay.json\n447952f40fbbce47c420ea597a23e6c93ef38efe data/refinedstorage/loot_tables/blocks/purple_security_manager.json\n9ba20dab86f37397695805c8db0f572e96e541b6 data/refinedstorage/loot_tables/blocks/purple_wireless_transmitter.json\n43229da34d37f4560833a9742b3f4b6138da89b3 data/refinedstorage/loot_tables/blocks/red_controller.json\n056331455eb87d28a0cb1659d0724282a4ea1449 data/refinedstorage/loot_tables/blocks/red_crafter.json\n3972629af5458ffb1c03cea0740e62a78a7b2666 data/refinedstorage/loot_tables/blocks/red_crafter_manager.json\n9fb2d4f0c6bed2c9060f4aebe78475ffb75cf83b data/refinedstorage/loot_tables/blocks/red_crafting_grid.json\nf75544f8ce7efc64fb91d354af1d5f50dda4c9a1 data/refinedstorage/loot_tables/blocks/red_crafting_monitor.json\n22c7826e4cec1b9fd4756427bf1a3b0b187c52df data/refinedstorage/loot_tables/blocks/red_creative_controller.json\nf437c5db37d754b96df4dd9c7761f3412b9a3e53 data/refinedstorage/loot_tables/blocks/red_detector.json\n9ce161f040fa06eef72775d51f531fd07bef6ed3 data/refinedstorage/loot_tables/blocks/red_disk_manipulator.json\ndd1f509da29f69f311d66deb6becf87e75be7e57 data/refinedstorage/loot_tables/blocks/red_fluid_grid.json\ne1cb6154faac93b2ca63f1a3c8d894361a532b58 data/refinedstorage/loot_tables/blocks/red_grid.json\n02f5ccdccc47354ca9690b347f32a96f5b0051f2 data/refinedstorage/loot_tables/blocks/red_network_receiver.json\n600ec0b5ee923cfb7f8ed9d14e24b132660cb413 data/refinedstorage/loot_tables/blocks/red_network_transmitter.json\n2e79450eba074c46756b16be391901f2b89daa48 data/refinedstorage/loot_tables/blocks/red_pattern_grid.json\nd20b27a7c016c29a431eb70542110a1e7f4ef797 data/refinedstorage/loot_tables/blocks/red_relay.json\n3c21b2588322b43c7ceb5b8ef276416c0aa972af data/refinedstorage/loot_tables/blocks/red_security_manager.json\nbaa1d85de292567f37bb3c4fa082d5f202caea19 data/refinedstorage/loot_tables/blocks/red_wireless_transmitter.json\nd2f04a0605843de064981d3ee6d2b7e782c37356 data/refinedstorage/loot_tables/blocks/relay.json\n6cc2e8ee53e0bcf6753c2d8d69a9891b27110eb0 data/refinedstorage/loot_tables/blocks/security_manager.json\n1ca249351ca9e410362047b3502e3b4e32613cbb data/refinedstorage/loot_tables/blocks/white_controller.json\na0827f3368539eb492d03ff2f8dbc98d530add20 data/refinedstorage/loot_tables/blocks/white_crafter.json\nc40e7a90edda22be3940886ee5246677ef82c09d data/refinedstorage/loot_tables/blocks/white_crafter_manager.json\n045e2477745e4972ff05638a8191755dcb1766b0 data/refinedstorage/loot_tables/blocks/white_crafting_grid.json\ne465dc037c72ffbe767857ff51d0c20dadb37e72 data/refinedstorage/loot_tables/blocks/white_crafting_monitor.json\n7d8f3d222b0f155c0f31e6c0f8b456cfc0626701 data/refinedstorage/loot_tables/blocks/white_creative_controller.json\n8475b4c7c0ca24facdd93443761d032fcfa4d240 data/refinedstorage/loot_tables/blocks/white_detector.json\n04a87335b56c2935578c64257b534fcb0c6ccaf5 data/refinedstorage/loot_tables/blocks/white_disk_manipulator.json\n7d84c9cbcc4dba2429375001785ea4730baf985a data/refinedstorage/loot_tables/blocks/white_fluid_grid.json\n9e62382949bfad25fd8c83ec0973d4e7297908d2 data/refinedstorage/loot_tables/blocks/white_grid.json\nb355304a9aeb739c07d9f9f4c3eed2238423c37a data/refinedstorage/loot_tables/blocks/white_network_receiver.json\n4dd2e115fa2d37ad228fe037693fdfb7f3a6d74d data/refinedstorage/loot_tables/blocks/white_network_transmitter.json\n130caa289363874ab2dc96a9c3171be4bd4a4140 data/refinedstorage/loot_tables/blocks/white_pattern_grid.json\nd7d36879c59cbeebfa0851e428ef6252e04128e3 data/refinedstorage/loot_tables/blocks/white_relay.json\nf990de5e3803c7a3c620228fb398e25a84a98524 data/refinedstorage/loot_tables/blocks/white_security_manager.json\n1e8bc1858a3dcd0bfaa5b2a5d13bcdec0dce5438 data/refinedstorage/loot_tables/blocks/white_wireless_transmitter.json\nb6211ce48a7aef9cbd64f4435ad43b41cdccaaff data/refinedstorage/loot_tables/blocks/wireless_transmitter.json\n8009a288908306e879924346d0d4d5f2123b88a0 data/refinedstorage/loot_tables/blocks/yellow_controller.json\n641acf6da9b5f838171a42bae45dc19f0fa51299 data/refinedstorage/loot_tables/blocks/yellow_crafter.json\n74f175474b5f74c4139b0c85deae09104ed3ef1a data/refinedstorage/loot_tables/blocks/yellow_crafter_manager.json\n33fc0a6833d600569ded23cf55dc4c8e2a0883c4 data/refinedstorage/loot_tables/blocks/yellow_crafting_grid.json\na600997dc1478e5d290f171ebbdb42a5a86501d3 data/refinedstorage/loot_tables/blocks/yellow_crafting_monitor.json\ndd06b6d13cec49ac1290f89d3ce232daba4fdcb7 data/refinedstorage/loot_tables/blocks/yellow_creative_controller.json\nb04dae60c3996c52d86ebaa5a6a876afb5faa536 data/refinedstorage/loot_tables/blocks/yellow_detector.json\na9a6c1a6f9e145dc6f55b6acae994983c41f0918 data/refinedstorage/loot_tables/blocks/yellow_disk_manipulator.json\n352d37f7117556cb2c53de4b0846e8ef5ee84682 data/refinedstorage/loot_tables/blocks/yellow_fluid_grid.json\n80659f567c1fb6fdad99f9b79522f2b25d1365c9 data/refinedstorage/loot_tables/blocks/yellow_grid.json\n288f81f67a969225f871be891af29ff90cf86ea5 data/refinedstorage/loot_tables/blocks/yellow_network_receiver.json\n5c016e53badfba708081c8c21e000e7cb591ad7c data/refinedstorage/loot_tables/blocks/yellow_network_transmitter.json\nec629e7f9a1efb517c49e38666e27f141c0c815d data/refinedstorage/loot_tables/blocks/yellow_pattern_grid.json\n9a61fb36d749298451e7baec7ec965b91fb3a142 data/refinedstorage/loot_tables/blocks/yellow_relay.json\nf7111d534c44737bb7f8e8e15c6484b314a10dc8 data/refinedstorage/loot_tables/blocks/yellow_security_manager.json\n3d20f6b4a0f17c42d79516f2bf66647154ef57e7 data/refinedstorage/loot_tables/blocks/yellow_wireless_transmitter.json\n"
  },
  {
    "path": "src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e",
    "content": "// 1.20.4\t2024-02-12T20:34:18.538076766\tRecipes\nd350b2771bd4ad63c80d048da51e610005d6daca data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_controller.json\n54840c4b526d0652d376bc75f06930142b6ee47e data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_crafter.json\n23b7a5b786b618c8061202dba92bf6751510b15b data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_crafter_manager.json\nb15e62f2c4fe216e157e898b53c0465d4f173a84 data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_crafting_grid.json\n97005bdb24b1113ec6b6d89749122d223dfa9356 data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_crafting_monitor.json\n55622084b126567c34634c919496ad17b9bf90f2 data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_detector.json\nfcf26564563a2e04e74f411d4d7bf7f3f459e193 data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_disk_manipulator.json\nd7bef08a9c37f96bd17943d97489ff4b758f0608 data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_fluid_grid.json\n2b443003f3344edf2b0d7822868a6cc8fcd16089 data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_grid.json\n43455ac450834a527402617e5e57a4017ebf0316 data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_network_receiver.json\nf51c17ad3c15121e2ecac366ee763cd448b3c4bf data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_network_transmitter.json\n30fc6bc4416522b5478ec7f45fda0444cf677b05 data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_pattern_grid.json\nc4f162dee00f9d2f0c3d067c6c392873432bc20f data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_relay.json\n9dcbbdb26e0c2e2a5365c65e86d5975c233d7cbf data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_security_manager.json\n529c5dd81a44add1cdad7fe4535f379532fc68b5 data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_wireless_transmitter.json\nd26368b812c74eef2c0cd62398d00b749dbeab32 data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_controller.json\n444ae3b86d615aae2c496cd8a4ea4b5ad72d265f data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_crafter.json\nb35122d76b4bb806a71934b073749208072acc25 data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_crafter_manager.json\ndb19bc28ee75d480ce92a6fc8378c4050cee63c1 data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_crafting_grid.json\n62f2936fba8519e449a2025bcfc2ef0a34586b79 data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_crafting_monitor.json\na2eb10818ed380108e7baed01fc01fb29958cee6 data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_detector.json\nc9ee2feb3892a37a097d2ed726913138ca2ddcde data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_disk_manipulator.json\ne42c45ebfda407bc8a63b6707736f1d9fc5d0ba7 data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_fluid_grid.json\naba1df8aef34cd1d4c65784f1b85735b716167db data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_grid.json\n399944bc9e7249d69b21dc76cc6efb43e60746d1 data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_network_receiver.json\n9552d403b622ceffaa8adbb67c1ccdd994c5761c data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_network_transmitter.json\nf1ae7f1ceb705970b9f3b6069d09d23a14c3ea83 data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_pattern_grid.json\n11777e4d00ad8cd996669a38771bd6107cf9e218 data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_relay.json\n558e83123713433b9218a73e5d73fb77319955ea data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_security_manager.json\n8bd0fd506e240f8f52722203d3ef0b2e991eb7c2 data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_wireless_transmitter.json\nf331f32959b42fd8ec8b029f6280db5ccd3cb2b1 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_controller.json\nfd01b544422d143849c67deda5ca42837c1ca398 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_crafter.json\n54ca4eb21f728930d7ec85f0c71751098df068e0 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_crafter_manager.json\n0abe0f9c101ef02e32e5bd156788019fb84b9033 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_crafting_grid.json\ndefa0fd4df43b104b12ddbe58fe4143388a1fb37 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_crafting_monitor.json\n2286d49a53f5e9e9950f7b3493bc36d21b8156f0 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_detector.json\nd1c01332b1d6d71471307d8ed317b7e4af5faa8a data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_disk_manipulator.json\n326b68bbffd81f01702f92cccf2f2cc30b905c40 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_fluid_grid.json\nefef6095e9e358abedd58e5a30aebfa730b61b93 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_grid.json\n82cf9f104a4f196a41a4623c4374e948ac790231 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_network_receiver.json\n58255d690b0900e394de5db9d5bfcce218121398 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_network_transmitter.json\n4aaa821eab15d6e1797db5e11c1b1aedd1531c57 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_pattern_grid.json\n45a34a412a792f74b6a2a1110343879329a888eb data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_relay.json\n17292d3a1960cf27224ff3be2f0d489c994616b0 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_security_manager.json\n120cea1d066a276ead272fd65f6c87d67a4c51a9 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_wireless_transmitter.json\nec1f6d949021b377481cc85f3c467ce0a22773de data/refinedstorage/advancements/recipes/misc/coloring_recipes/controller.json\nf308296bcfd82dbe8ec0b16fd8676695b5507b05 data/refinedstorage/advancements/recipes/misc/coloring_recipes/crafter.json\nc2799d9f2a96b93ae0a5a44a3ca19f8b3d118829 data/refinedstorage/advancements/recipes/misc/coloring_recipes/crafter_manager.json\n08fa572f80f7950cd44f45226e6674277d6302c1 data/refinedstorage/advancements/recipes/misc/coloring_recipes/crafting_grid.json\nd04b75de8d7beed6a9fb4b95c76fb2e7372879d2 data/refinedstorage/advancements/recipes/misc/coloring_recipes/crafting_monitor.json\n7279fc15ca132eed3ec3b98d8d8b4000a8b946e0 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_controller.json\n81d170036872e1aa35773cfe1a54e9ae25e3c8bd data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_crafter.json\n22d75217a257c2bfde3faa9042016391fdd1a881 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_crafter_manager.json\n0c1d56d7620d98e018103bb8bd6a1ac4a6ba8f8a data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_crafting_grid.json\na049e2fa95f344d566a3b4e9a8bb723f361d3b22 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_crafting_monitor.json\n46e2401b27b24f2daa3f92be57bd0917efc1cd17 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_detector.json\n69361419882d5b0beb1e2c97dca3fb5333e96006 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_disk_manipulator.json\n38e3aba8366c111c322c25f33afd1e05db0495cd data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_fluid_grid.json\n4df118e5e0a7f3d44b13c29b6e17fdc74375e4f3 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_grid.json\nfd921c19c96c88f248cb72066bcdaef5244d0e29 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_network_receiver.json\n78b6a92c183db89ec7ed784752821da4663c53f5 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_network_transmitter.json\ne41899b7a205cc933ddbae98de06b2eb56d7fc61 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_pattern_grid.json\ndac4aa9f73456bfa0d589a997980f7cccbca01f9 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_relay.json\ne29e96cf471a1f3751358cb4847fa34e95d02ca5 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_security_manager.json\ncb4c05ab919c0bc0a83def453f74e6f783b9dff5 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_wireless_transmitter.json\nd55193c421a69c24dd64d98ac3154a433a537325 data/refinedstorage/advancements/recipes/misc/coloring_recipes/detector.json\n3e89a210043d9e41dd2165f0e73548e1884c2232 data/refinedstorage/advancements/recipes/misc/coloring_recipes/disk_manipulator.json\n81d30c747d62a729c195c55435283dbf9ec3ccc6 data/refinedstorage/advancements/recipes/misc/coloring_recipes/fluid_grid.json\ne8cf20a95b3bf091612098b3c516a5189b8d6799 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_controller.json\ne77cdb0c96a755fab508295cbc021a4198a73a32 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_crafter.json\n8655e0374baeecefd17e45b8b3bdd500d898497f data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_crafter_manager.json\n29049edb4edc8f183401d42fe90e56e796b9f524 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_crafting_grid.json\n74feb00efdaa6bdec68d6d98fbdfe20d66f89178 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_crafting_monitor.json\n2361ea074be45b6d5bc156d92765cfe95d005927 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_detector.json\n80a4d154d21b70a184eac395a5a7b72d209de429 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_disk_manipulator.json\na25f5655c5b77acadc21f13bb6386738d5bfbbd2 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_fluid_grid.json\nb0e993da2cae346c1314ede633f8e01b88000a9c data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_grid.json\nb47265fad6beae6b7e8902c8b8711b8c4b1c3f67 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_network_receiver.json\n8c1027dfd8d0f024c4cff7888a06f4bf28ff2ceb data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_network_transmitter.json\n2b14eef6f0640ef29b10b0496b3b2e03a8401efb data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_pattern_grid.json\nb9ba15b383fc750bd8f51fbe757ac398be229979 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_relay.json\nba0ff95eb1d047d4045d27cd67ed2b74e1faade2 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_security_manager.json\n93194bde577130f3aafd15968ccef34fdcaa0994 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_wireless_transmitter.json\n5b494d4de2d8e760868080a3a47e6d9ffa6d2d97 data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_controller.json\n23166b7d06c90415a904b874ecec4ef3b76d376b data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_crafter.json\nbb271c810fd9010232efca4a44faad9d4a9cd90c data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_crafter_manager.json\n081abe762fb4198d49a0baf0858b5d2fe37a1595 data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_crafting_grid.json\nfa2567877f0fb5bb02a5831ee137aa66ac47dfe4 data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_crafting_monitor.json\n0e6a77a42153aa2bba05e96c5c553114c4c718b1 data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_detector.json\n43321a147268c573478497f2aaf5e26baa044859 data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_disk_manipulator.json\ne08307b008e993464bfa52815a2673fc057c6d49 data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_fluid_grid.json\n504bb9ddda37a8ef76c7765de0f2a2e24f7b0171 data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_grid.json\n5d72547ae9d1d014cd8f922dc045eafac843698e data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_network_receiver.json\nff769707888be7b3d0233f664ba7129f37c9f5bc data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_network_transmitter.json\nce4880ad86cacb787dfb3c20eab27c01b0a7f3f1 data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_pattern_grid.json\n1b5141b4908766b25af9b1d4a2cf5018957f25d7 data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_relay.json\n33854d93ce3dc17717ad234d3dc875a69841c9ad data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_security_manager.json\n7008d4ec46c9c0995e603648d347438232749296 data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_wireless_transmitter.json\nbf27477c47f4f5af6b5a8adc4e177fdf5794afcd data/refinedstorage/advancements/recipes/misc/coloring_recipes/grid.json\n3541bc5c522700de1004183d7dbeb9721749f99d data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_controller.json\nc4c71c447d0170c3ff20d777fe7983d9bcc799bc data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_crafter.json\n702b34d1c0dbec4956f82a622d95f581135a5cc1 data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_crafter_manager.json\n5926515e95f7faa6e81bdb539f1da4b7922bdc22 data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_crafting_grid.json\n7113c0865a37a843238c0bd618656575f5b8613e data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_crafting_monitor.json\nd9de193424b692af7724bfa428dde79463c94083 data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_detector.json\nbeaa78d1ca605357c665cb6c077a1aa1695eb2c7 data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_disk_manipulator.json\n0d62c18cd86e523a197e84ffe15fdb2fe6444668 data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_fluid_grid.json\n4a92ca1f1cb915269db078ed1bd14d90b024a7a0 data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_grid.json\n212af37ca0be812f405238fe913bcdc33fdee9a5 data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_network_receiver.json\ne6a7aed89254fcaaf24eb42897e6d853fa9cbbdc data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_network_transmitter.json\n9afae748bf4f8539db59bdfe6bc77ca7d1f94a8e data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_pattern_grid.json\na83096cbd33db7938aaf28cfadedcc6227d1dfab data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_relay.json\n196951d09482eba275eea65407da6f3f9ef659a2 data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_security_manager.json\n6862bcabca8ac284dec0ca21113d2a47fe2a25c4 data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_wireless_transmitter.json\n8920ad0af9501e05ae67a18c185422ea3f2d494f data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_controller.json\n4f744de464eeab733def439030ec568704dbdfc5 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_crafter.json\n704dc694a1392918c9df6f1bcb711cae74d09bf7 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_crafter_manager.json\n65f7d805a7fa684271d1232f532886c31caf08b8 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_crafting_grid.json\nb665f849378bcded92f27612b5ee4714a2bdb3c8 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_crafting_monitor.json\n1d2b1bde350c014d31a47e2acd64344aaf39f006 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_detector.json\na2fc75ed0e55da1a09b5e4f7d0d3d1f932b20296 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_disk_manipulator.json\n6e48a78e9a261f218bcc530f4f2f9bf8d1f5b7b0 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_fluid_grid.json\n382df921efdc89d06e6570d96456200893701847 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_grid.json\n0e2f9c833b32dbbb9cc994d5331e201f646e2260 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_network_receiver.json\n340e02a24ca341d029fe6eb0edf54527456b6fca data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_network_transmitter.json\n7ae8303f3b8d083ac253629732fe5843d98a46ef data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_pattern_grid.json\na9d8202520a2eeb40036b4f08b2906a235b26c7e data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_relay.json\nd76d10c59fdf4c3faf6736f788d88eeb1c361fb3 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_security_manager.json\nb7468157902e6a9f332b038e0b6a104243ed3824 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_wireless_transmitter.json\nd5e5099a140396ad770fc1e080b06ae58e5bab53 data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_controller.json\n0d738a1bcb7f70d0c8a2fb8ddc58106cf1f1af56 data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_crafter.json\ne71700d2067eda969cff274b75fa06abe55e5456 data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_crafter_manager.json\n8cdad9ed6a81ae38b39ff89e3c8b8a3162591ec4 data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_crafting_grid.json\ne889eb8c665ecde9fd814aeae186c33fa9fe774c data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_crafting_monitor.json\ned8f2c1dfbb3efdaf9a17abd528ddc4fa9c4351b data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_detector.json\na1eaf5560aa797a920c6d859e1da12f26df70ba0 data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_disk_manipulator.json\n9337dd604b42c894ec795ea4d933494eb6cd3ffa data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_fluid_grid.json\n3b5787043fdf9470c94c55a1ec4e2332ec7e92f8 data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_grid.json\nf47530ed35d85cff56678f2848f508e16d5d754e data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_network_receiver.json\n75c0c87f36745c83d7d7afe95ace7fab776bf049 data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_network_transmitter.json\n6480e36774a962568474a4ebace57436f841d105 data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_pattern_grid.json\ne637d70e432940ff585c3bff26e9883ab61243c8 data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_relay.json\ncfe2c6806954fa84c96a886883617ade1920cba4 data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_security_manager.json\n27590375ef521bd3dac015c46483e8a14e6d518a data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_wireless_transmitter.json\nedf871954047dc82a5baa504f093c8bd95bc9e4f data/refinedstorage/advancements/recipes/misc/coloring_recipes/network_receiver.json\nff22d01d0549186d21c65245d7a8647cb3e8d831 data/refinedstorage/advancements/recipes/misc/coloring_recipes/network_transmitter.json\n7a1e7c7acf6c5e517a825c416354b1c52993e8e8 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_controller.json\n146baa694f6912ec9b34d0f9f0c94fb49b7a66c6 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_crafter.json\nb53f5da5a6745f0ab4479284a5b238e52d23af31 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_crafter_manager.json\nc6a0b5ad7a2701caa7f185b2445730d8de2d8231 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_crafting_grid.json\n77ab4c02e39cf139fa110a5543e6c4121d095959 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_crafting_monitor.json\n5464c441ae2378ff8cf655bf092698e8e5cc6698 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_detector.json\n6212064e3078df7b4b2f0eaf2c66b2351afb8d75 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_disk_manipulator.json\n9fa3953437f41825a1a94cfd8b26ad0deba512c4 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_fluid_grid.json\n3da19d71780bb0dd8b598680f0f6cdf51d095a5b data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_grid.json\ne8c6ea5c6321cb3f0c0818a7f20bb34dd19d6b8b data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_network_receiver.json\n599372e90c5525ba6965d85bad3dc598684cbce8 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_network_transmitter.json\nc89d2ab0fc65018f61c6e0db371d1b91fa0dc304 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_pattern_grid.json\nacc414b2be65c1bd89fb1236627d418eb3359095 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_relay.json\n50b1bbd95f32b7f79fca433d06c7cf9d312ff635 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_security_manager.json\nc6e2ba623ce6e0ecc93357415ed1c33190cc9416 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_wireless_transmitter.json\n1bfff6f3c7fef860a7813bb3f6196605b47de77b data/refinedstorage/advancements/recipes/misc/coloring_recipes/pattern_grid.json\n230c5ac17bd397b63dd54c22a6b1f4d5abb1f6c2 data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_controller.json\n64ae49fdeadba8df9bc5cfc01aaf84c757265fa1 data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_crafter.json\nd49b9aa96ca0b53f42f13c133141c903608ca66e data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_crafter_manager.json\n787fb6d515ef4e04abe1ef518634b93d862642ae data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_crafting_grid.json\n1920557334d4fa98a37d154f4bc8ddc242d3c278 data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_crafting_monitor.json\n13223e633b19fdaaaded08f0a645b352cc2ad754 data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_detector.json\n13f2066a6766b5eb76eaeb9b8c2b443ae8ceabde data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_disk_manipulator.json\nb6531737768efdf4fd516609f5b7e26c3c626995 data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_fluid_grid.json\n3102d2be9e0ebbbfbf433b6758fb26cd538f8f3a data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_grid.json\n13a94375a8af3ef1752f87fe175a4004b1f222ed data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_network_receiver.json\n3c60279b49941739ee15d5ec8300e0509afca26d data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_network_transmitter.json\nd3839fb0c7a92432e930bc3a9a45dc4b93afddf0 data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_pattern_grid.json\n0b690f7621a8a70fe15da08d0c5b4353f132a510 data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_relay.json\n96915b3461232a2b27887fdbba7752c8dc14d532 data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_security_manager.json\n7c308ed13a18f4ce573e1d335ace88f8785fbfdb data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_wireless_transmitter.json\n8c81dd70017507b21aa84af1d133c5bb9e0354b1 data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_controller.json\nb70a31b425cd286d3e5852c67c35b3c5cc8f1204 data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_crafter.json\na63197c094c15d3d07f6dadcedc5cd5cacbcc6d6 data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_crafter_manager.json\n38928bc5a96a0b17e98957e5fdaa09315ecea8fe data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_crafting_grid.json\n239fb41ac609b312e47800ab6b244ad2ec011694 data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_crafting_monitor.json\n4088a819616dc7de931babe577ab852184335f5b data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_detector.json\n19084ac15e80de9255f57ec6f50efe9f287ad47e data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_disk_manipulator.json\n6e020575b9eeef96eb31cec01440853d292a78b3 data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_fluid_grid.json\nab76e99e048aa7a507bc2ee71238195f42df1f52 data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_grid.json\nb551e2e756475c031a49169b8cdb7bb1478d5690 data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_network_receiver.json\nfaa57612200a9f95fb0c03bbd00bf3ba07971b10 data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_network_transmitter.json\n1b362ecad4b8c539f36bfc93055f0c3396ffbaea data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_pattern_grid.json\n2c6093b322f2836d4902537d90fae35df6b2785c data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_relay.json\ncab4f5742b5bbebd870dc64f4617ac1023b02b2b data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_security_manager.json\nb3778f099b387d2fa457070572b2b55931c8ee73 data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_wireless_transmitter.json\n2c7559a6e8746c6f4b47c006a70b165d181b8c80 data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_controller.json\n78a4b901f4a3c0a186bbcbe9881bbf9fe0fa4da2 data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_crafter.json\na5dd747b9b93ea4393fcf401768d1cf521595983 data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_crafter_manager.json\n584abaeac9f96f87185a65cb221dd5dc94f2e67f data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_crafting_grid.json\ndcb775ecd844a7c9e30d501bef8caa0fc09f5b07 data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_crafting_monitor.json\nfb6ae6665e14807c2690f71504c9b26da92142ae data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_detector.json\nf40b82c9a1bed8dba73353dd8d6104c2744bf5e5 data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_disk_manipulator.json\n577f50cc70ed05e6bb5c1f88cd4f36e6ffdc38a3 data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_fluid_grid.json\n0b295fa3bdc3a126cfb16cdab106eeef65f88077 data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_grid.json\n1587e589c213f567966fdc5c3009771e51cc83d0 data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_network_receiver.json\ned6cf3e3917a03bf1d7d3305297e3d3a5f16f47c data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_network_transmitter.json\nca1ca09f9ea4351c754030e3ca05f7f3a4b45e93 data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_pattern_grid.json\nf5716311b802fd0dbf1c5e56fe7c6936fc35d1fe data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_relay.json\n1472f516a95d9e6a7c698acc741c439383eefcbe data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_security_manager.json\n83a709b3f2b2d077ece8315b4cd0d414b4d03706 data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_wireless_transmitter.json\n193f0653ac14aead77cd82b381bf005527cf710d data/refinedstorage/advancements/recipes/misc/coloring_recipes/relay.json\nfcb727e6a921c3005c42965f9487ebd1ad5fed72 data/refinedstorage/advancements/recipes/misc/coloring_recipes/security_manager.json\ndddb4b444133f4c7b25ce0f61a3a99115bf6e34f data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_controller.json\n090ff26f519be45f17cd26bbd0a4bffac8788d9f data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_crafter.json\n0fab47854d53df7e11046062d079ee2907f45542 data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_crafter_manager.json\nf680b3d58426290b96582ec6c503ed67d70fb76a data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_crafting_grid.json\ned146018b0984f5b0d1a8268967faaef19137b8c data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_crafting_monitor.json\nefc126ddb87d193a0da48e463b1491c55bc2acd4 data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_detector.json\nf5330852a980dc96909fb7d8d0e5fc041f7b7746 data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_disk_manipulator.json\n5647b0161acd0c3ba7c9be2bb4dbe16a189da2e6 data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_fluid_grid.json\n22e149a387a8f312ba9418a2560a9d90491bbd13 data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_grid.json\n03d901c37cf4325431dee4b42383821819aeafe5 data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_network_receiver.json\ne972d1fb5200ad4d76e81acca1f0981ffcd3ecd7 data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_network_transmitter.json\nd30354bd77cfe54177d401bac7f3fae3b43a7358 data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_pattern_grid.json\n885e79474ecd484200a4c74c5b9b5793d3af5f54 data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_relay.json\n40ebabe8d88e40f05dbd884955e03e6c9874e8fc data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_security_manager.json\nfe956edaee3a34348d624d99ddd549f40d3643e1 data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_wireless_transmitter.json\n6eecfd13553d104c093c3822c148cc7f08d2bd0a data/refinedstorage/advancements/recipes/misc/coloring_recipes/wireless_transmitter.json\n6a754b8300dd0e23f9b996cee593916c057ca3d3 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_controller.json\n9c632320c99a245a3ecadf9236e6910549e76e54 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_crafter.json\nadccd41abbcfb9b1bd5deb9f9c1f0ed94fa063ce data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_crafter_manager.json\n68e92c065a5f08c8b497c4c383c9430f8cc8e8ba data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_crafting_grid.json\nb5f5f31089375ade9a47c63d3885a83422a1b23b data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_crafting_monitor.json\n45c6aab891bdd10105893ecfc0f07d0b811083d9 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_detector.json\n7c384cda09300a12f85bc22dd004c3e03b6242f5 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_disk_manipulator.json\n51916964e73f4ba5bcb2d4f3119b9fb8816753c6 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_fluid_grid.json\n659328b91541f94cf9266c43a18dd0f94dc5c415 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_grid.json\nd29f87c0cf06922d65e8b04de93ab19d29c45001 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_network_receiver.json\nd3bb694cf85ff441ba6fa29a6f4c16378a598094 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_network_transmitter.json\nb9fee6c5a251fe8294772e0dd0ed3378e79133f8 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_pattern_grid.json\n2cfbe64c72ad2fd07d4004a9c099a0c855e621e4 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_relay.json\nfc362a4803693a183950d7e373153cf802a4ff2b data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_security_manager.json\n3b3b450e9af59ba31397fb93c198f57208a243d7 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_wireless_transmitter.json\n9996c185802c040d7454b1cfcfd822605d56b79b data/refinedstorage/advancements/recipes/misc/crafting_grid/black_crafting_grid.json\nb4a51061a225e0ee4c52af75b79668e2b731b86c data/refinedstorage/advancements/recipes/misc/crafting_grid/blue_crafting_grid.json\nfc16827a50393291982a6e0e19da4b7e440942f3 data/refinedstorage/advancements/recipes/misc/crafting_grid/brown_crafting_grid.json\n05a059a165244eb944688123206078edf380bd35 data/refinedstorage/advancements/recipes/misc/crafting_grid/crafting_grid.json\nf759470c704e5bf08ddd19d6e0fc738dc22d7256 data/refinedstorage/advancements/recipes/misc/crafting_grid/cyan_crafting_grid.json\n9b544ac54835cd3717af3cfa78fc99c626ed857c data/refinedstorage/advancements/recipes/misc/crafting_grid/gray_crafting_grid.json\n610cd12ad1fd27af1d428898077a6c1e604dc33f data/refinedstorage/advancements/recipes/misc/crafting_grid/green_crafting_grid.json\n5ffe1397bf0f3d666c452303216d3389e4e634c4 data/refinedstorage/advancements/recipes/misc/crafting_grid/light_gray_crafting_grid.json\ncf48c0c9e45bedfaa2dfc28414ae77b4589bb058 data/refinedstorage/advancements/recipes/misc/crafting_grid/lime_crafting_grid.json\n4114ead8379196e77b74d5c91aae72426664944c data/refinedstorage/advancements/recipes/misc/crafting_grid/magenta_crafting_grid.json\n323efa415a91a1a57327d2f9f37d85924f59b08b data/refinedstorage/advancements/recipes/misc/crafting_grid/orange_crafting_grid.json\nb399c6d4a3344a6835d5f869ee2e423369a9a148 data/refinedstorage/advancements/recipes/misc/crafting_grid/pink_crafting_grid.json\ne99cfcfdb579bca6a1ee5f051f49ddb90e5ff53c data/refinedstorage/advancements/recipes/misc/crafting_grid/purple_crafting_grid.json\n81cd4d1b9defdfec2977c5c54fd1d6acdaada81c data/refinedstorage/advancements/recipes/misc/crafting_grid/red_crafting_grid.json\n3be49d30bfd65404d73d0a028f8037128ae79f2b data/refinedstorage/advancements/recipes/misc/crafting_grid/white_crafting_grid.json\n35df545e58407a3b84abb737ddbc50680da66899 data/refinedstorage/advancements/recipes/misc/crafting_grid/yellow_crafting_grid.json\n5705ee4e85e94edf72a96de2dc3fb6ecb60b6729 data/refinedstorage/advancements/recipes/misc/fluid_grid/black_fluid_grid.json\ne2bf1c90dea3f8e4f67fda2747237da7ba540213 data/refinedstorage/advancements/recipes/misc/fluid_grid/blue_fluid_grid.json\n525cfca4916fcc674e741fada4cc606abb745f7c data/refinedstorage/advancements/recipes/misc/fluid_grid/brown_fluid_grid.json\nece66d6ed3ee6b031f495034bfa4c38c4a1ae5cc data/refinedstorage/advancements/recipes/misc/fluid_grid/cyan_fluid_grid.json\n9e4b7cb2fdfa2805a53cf7dbc496dba36151caed data/refinedstorage/advancements/recipes/misc/fluid_grid/fluid_grid.json\n37b3fc51d47c365088514a703cc5fcf11bd6837c data/refinedstorage/advancements/recipes/misc/fluid_grid/gray_fluid_grid.json\neaa9e19285209fe2d5bb68953892748b8433cd19 data/refinedstorage/advancements/recipes/misc/fluid_grid/green_fluid_grid.json\n2d2a94c20cd953005d4483a0af18af9498006128 data/refinedstorage/advancements/recipes/misc/fluid_grid/light_gray_fluid_grid.json\n6217e87d976a2d97f137debe4b7af117bb0d9946 data/refinedstorage/advancements/recipes/misc/fluid_grid/lime_fluid_grid.json\nc6faf936615279617b893d8a2b8c197f1cdc1922 data/refinedstorage/advancements/recipes/misc/fluid_grid/magenta_fluid_grid.json\ne1bea619d01e04e61c2295535840a294bda4e46f data/refinedstorage/advancements/recipes/misc/fluid_grid/orange_fluid_grid.json\n69f1805039706b422b733e743addcd165452d7eb data/refinedstorage/advancements/recipes/misc/fluid_grid/pink_fluid_grid.json\n38d16b36b2c8c1e0dabb778bcf03b967f262739b data/refinedstorage/advancements/recipes/misc/fluid_grid/purple_fluid_grid.json\nd067044876223011f3e9736673ca67435e9a66e2 data/refinedstorage/advancements/recipes/misc/fluid_grid/red_fluid_grid.json\n0d47235aa57900ddca60c8599d92f4a1a79877d0 data/refinedstorage/advancements/recipes/misc/fluid_grid/white_fluid_grid.json\n1ffaa363c95cff7d00cad878af9c42015b4bfa1b data/refinedstorage/advancements/recipes/misc/fluid_grid/yellow_fluid_grid.json\nb4445540f30612fd4ac460c83b20d6adef72c619 data/refinedstorage/advancements/recipes/misc/pattern_grid/black_pattern_grid.json\n2aa9e0e19a41b6996a84b9a7ec2416ad0e0f4ab9 data/refinedstorage/advancements/recipes/misc/pattern_grid/blue_pattern_grid.json\nd75032ae87285c3a4d1924d0655ca50748a40eb7 data/refinedstorage/advancements/recipes/misc/pattern_grid/brown_pattern_grid.json\nf624f44cf7e80933b2f8351701adfbf2212a8fc5 data/refinedstorage/advancements/recipes/misc/pattern_grid/cyan_pattern_grid.json\n03a3dbfb06c413572b93c5426873bddbb32924a2 data/refinedstorage/advancements/recipes/misc/pattern_grid/gray_pattern_grid.json\n95614af1e6d8694b29bae065e43e2afce8e252e4 data/refinedstorage/advancements/recipes/misc/pattern_grid/green_pattern_grid.json\n905018dec1c9f5224aeb72407967b6983f1f7ed8 data/refinedstorage/advancements/recipes/misc/pattern_grid/light_gray_pattern_grid.json\nc854b76d5c75b4936394bb331441457aa3a5356f data/refinedstorage/advancements/recipes/misc/pattern_grid/lime_pattern_grid.json\n12f393c295bb60814be1bd29ad9e07d5343106fe data/refinedstorage/advancements/recipes/misc/pattern_grid/magenta_pattern_grid.json\n1c19ef9067c2ea223a419ce5f6d0967169fe44ea data/refinedstorage/advancements/recipes/misc/pattern_grid/orange_pattern_grid.json\ne53eb701016f00c8c727a36ccd0d41d6d6ff1cf3 data/refinedstorage/advancements/recipes/misc/pattern_grid/pattern_grid.json\ncaa14b841c970d31a9247387ab7690f17f92f626 data/refinedstorage/advancements/recipes/misc/pattern_grid/pink_pattern_grid.json\nce6ed82f788fa0e8fe471971c590b36c5582969a data/refinedstorage/advancements/recipes/misc/pattern_grid/purple_pattern_grid.json\n05ed2ae9497d2ff40398d9da5f8c7e2e584536c3 data/refinedstorage/advancements/recipes/misc/pattern_grid/red_pattern_grid.json\n82c53eb4b9d9ff5f7ae26b59aafef71c90712006 data/refinedstorage/advancements/recipes/misc/pattern_grid/white_pattern_grid.json\n28c917f48693b907454319c6d7f04c56cd9a5e04 data/refinedstorage/advancements/recipes/misc/pattern_grid/yellow_pattern_grid.json\n1e484115999fa62d482da0ba86c36e3a7568513c data/refinedstorage/recipes/coloring_recipes/black_controller.json\n837df99fec4b00d059e5f258c8c51040989fd59b data/refinedstorage/recipes/coloring_recipes/black_crafter.json\ncc777c1de15ee96706565e3032d8a17962452316 data/refinedstorage/recipes/coloring_recipes/black_crafter_manager.json\n71a7d1ce09686c97292c9f7fe90397a4ee0b3d0e data/refinedstorage/recipes/coloring_recipes/black_crafting_grid.json\nbf9c9f4ab628826aacb1b310c0997946ed42a023 data/refinedstorage/recipes/coloring_recipes/black_crafting_monitor.json\n5c13f67cd1a2c12b948039fef5e5bbe7988e2104 data/refinedstorage/recipes/coloring_recipes/black_detector.json\n2ba43fdfa0c9c2e558f5437c63f9629934c1a818 data/refinedstorage/recipes/coloring_recipes/black_disk_manipulator.json\n8976bd18990aa165753024ab57e6d4ca0db78e4b data/refinedstorage/recipes/coloring_recipes/black_fluid_grid.json\n1931c84a99f99264cfecfa442f0fb7a0f0120aec data/refinedstorage/recipes/coloring_recipes/black_grid.json\n7ef51e8c9d67a75733dd35a2147de292476a5b92 data/refinedstorage/recipes/coloring_recipes/black_network_receiver.json\n1771e330ab8ed131f3599fbbb384adb0975e998b data/refinedstorage/recipes/coloring_recipes/black_network_transmitter.json\n091051a710572811a3667d8e0080c3871bd45daf data/refinedstorage/recipes/coloring_recipes/black_pattern_grid.json\nfd71581f200ecffd14e85f248329039379222479 data/refinedstorage/recipes/coloring_recipes/black_relay.json\ne0f4c9cbc082845a2b9b22036600136241594aa7 data/refinedstorage/recipes/coloring_recipes/black_security_manager.json\n5e200307f6317b2efa641e2c8616417086d57aac data/refinedstorage/recipes/coloring_recipes/black_wireless_transmitter.json\n558cdfb9ab1e1b58165aff5d9cfabc7c18f2ff81 data/refinedstorage/recipes/coloring_recipes/blue_controller.json\n877ce0de12f2d1242d436ecc33e7668418afc51c data/refinedstorage/recipes/coloring_recipes/blue_crafter.json\nc3ecb5dee328da9c2573852eb5f1277c424803e9 data/refinedstorage/recipes/coloring_recipes/blue_crafter_manager.json\naf1dad13103c12463cc19735b459918785b555a1 data/refinedstorage/recipes/coloring_recipes/blue_crafting_grid.json\ne1abdfc940501d07568d8e2ff5f4b1305826e907 data/refinedstorage/recipes/coloring_recipes/blue_crafting_monitor.json\nf82fc0d730557fb523376a6624bba58af1608787 data/refinedstorage/recipes/coloring_recipes/blue_detector.json\nfa010026eb95b4ae2abe4380c39c412419feeb97 data/refinedstorage/recipes/coloring_recipes/blue_disk_manipulator.json\nd393aaf88281d449a54345a62db43488f7d9ab35 data/refinedstorage/recipes/coloring_recipes/blue_fluid_grid.json\na8f7bda8af1dbbdf0812dca695b352e692d95957 data/refinedstorage/recipes/coloring_recipes/blue_grid.json\n9258bde68dc2ca0bc4d1becf182f893cb1427281 data/refinedstorage/recipes/coloring_recipes/blue_network_receiver.json\nbf71db6ca317ef6cdac9c474869a1506970d759a data/refinedstorage/recipes/coloring_recipes/blue_network_transmitter.json\n09e04694c20f5dbf70756431efa00eb10a1e1767 data/refinedstorage/recipes/coloring_recipes/blue_pattern_grid.json\nc053aa38a5f0bb3b14a3b4d1e835f9db7ad270bb data/refinedstorage/recipes/coloring_recipes/blue_relay.json\n2e3eaad4c458805972415b0bb5b6706b98977a19 data/refinedstorage/recipes/coloring_recipes/blue_security_manager.json\n3aa1f2ec541238abcd590d042e484cd91041a393 data/refinedstorage/recipes/coloring_recipes/blue_wireless_transmitter.json\nfe702b3093653416d11cac5c75307b6bf1f523ee data/refinedstorage/recipes/coloring_recipes/brown_controller.json\n85f7c531571ce0a8ca574598752a5abf7eb07329 data/refinedstorage/recipes/coloring_recipes/brown_crafter.json\n847dc405eb66a48ba1aa44c952f41a0cececcb46 data/refinedstorage/recipes/coloring_recipes/brown_crafter_manager.json\n2a0599e860048197e6f09e1ad280733ae4cf6584 data/refinedstorage/recipes/coloring_recipes/brown_crafting_grid.json\n41aad04c9677225d7c25aa82737b727bec3f7bc5 data/refinedstorage/recipes/coloring_recipes/brown_crafting_monitor.json\nc261128142cd85f1cc795f7bd39448af67b3e4de data/refinedstorage/recipes/coloring_recipes/brown_detector.json\naf05ffb684495cd67a14c42a20bc845a365e1b7c data/refinedstorage/recipes/coloring_recipes/brown_disk_manipulator.json\n572f7f49be2f807e698f00f4e4f30bb56ea3aa0b data/refinedstorage/recipes/coloring_recipes/brown_fluid_grid.json\nab73cfdade881ba269a8a06397aeb2b82f2a21bd data/refinedstorage/recipes/coloring_recipes/brown_grid.json\n85762417f1d46f81d9d74ed1353bd8817dbcde6c data/refinedstorage/recipes/coloring_recipes/brown_network_receiver.json\ncc4e328b53e6e9d7a064e87b66a3e5cfa6b9fa4f data/refinedstorage/recipes/coloring_recipes/brown_network_transmitter.json\nf33c81984de9bc038d6c03236fa60dfd52d419a5 data/refinedstorage/recipes/coloring_recipes/brown_pattern_grid.json\n210c2b7b92c48d2f32458cc5c3d5910392f9e997 data/refinedstorage/recipes/coloring_recipes/brown_relay.json\nd895b41ada1d66ab9e7b8632b837f57276d306a7 data/refinedstorage/recipes/coloring_recipes/brown_security_manager.json\nb60379a43934b84994a7080dcfe007b7a0f3a6ec data/refinedstorage/recipes/coloring_recipes/brown_wireless_transmitter.json\nea0e5be25c24c1397a61995e60ad77b0e4957c7b data/refinedstorage/recipes/coloring_recipes/controller.json\n0e52aa0f87bd8b55cbe9d2a60d8c3e1e130636f0 data/refinedstorage/recipes/coloring_recipes/crafter.json\n5f1a68aeefb616316bf4e30238d59649a731c64a data/refinedstorage/recipes/coloring_recipes/crafter_manager.json\nb1513edf52ff9f3af93ebf0ca0d305be5d104a41 data/refinedstorage/recipes/coloring_recipes/crafting_grid.json\na11298d3883765d7873763e3526ba367c8a46284 data/refinedstorage/recipes/coloring_recipes/crafting_monitor.json\n5129a9870a709ff9f4e18855e8b141b760880a72 data/refinedstorage/recipes/coloring_recipes/cyan_controller.json\n2c75c39bce50b9759d0ab241cc4a7ebc0ff633b3 data/refinedstorage/recipes/coloring_recipes/cyan_crafter.json\nc3f47e396862e9aa944348aaf9f254ac50532d11 data/refinedstorage/recipes/coloring_recipes/cyan_crafter_manager.json\nc1b2a9c366d5062d5c800605b78958f7c34d650f data/refinedstorage/recipes/coloring_recipes/cyan_crafting_grid.json\n10b9f12e753b31044f4cb6100f355c88e7fef7f3 data/refinedstorage/recipes/coloring_recipes/cyan_crafting_monitor.json\n4d4e1643279662793291a7b24ceb89e44bfcc689 data/refinedstorage/recipes/coloring_recipes/cyan_detector.json\n8a1ad5686442737bf11437a1b5a62cff756ccac7 data/refinedstorage/recipes/coloring_recipes/cyan_disk_manipulator.json\n4fc265412a18f392c22af9fa4674f9a609e08209 data/refinedstorage/recipes/coloring_recipes/cyan_fluid_grid.json\n332fc9c1e21f70e6fe1dda7bb1c964f0ed7715ad data/refinedstorage/recipes/coloring_recipes/cyan_grid.json\n819b91726b96bd57eae98d6d8b0b9be99e3db11d data/refinedstorage/recipes/coloring_recipes/cyan_network_receiver.json\n7f00009bd87defab006770026bb7a3528a7ce236 data/refinedstorage/recipes/coloring_recipes/cyan_network_transmitter.json\n4d77311bce6a5ed341b1e69fa8e808a158e7d767 data/refinedstorage/recipes/coloring_recipes/cyan_pattern_grid.json\n0a69efd0b4e23d7225016f731f5e00f176762356 data/refinedstorage/recipes/coloring_recipes/cyan_relay.json\n911b3bb449c468e0c45a1fa2eace3649871f80a8 data/refinedstorage/recipes/coloring_recipes/cyan_security_manager.json\n545821250a3e514540af53d58c302fd7a53d0964 data/refinedstorage/recipes/coloring_recipes/cyan_wireless_transmitter.json\n96fd9b436a78b7a0b40a96768589f609bedb9248 data/refinedstorage/recipes/coloring_recipes/detector.json\n0c2555ef2ad11844b1224bcec144f67a109e5449 data/refinedstorage/recipes/coloring_recipes/disk_manipulator.json\nfd119bae8fc3daee094d892d1197f9ec7152d346 data/refinedstorage/recipes/coloring_recipes/fluid_grid.json\n87791b279165a6792585449159085151230b5f50 data/refinedstorage/recipes/coloring_recipes/gray_controller.json\n127c027aca2912960a2fef6704eabdb326a60f3b data/refinedstorage/recipes/coloring_recipes/gray_crafter.json\n428babaa3af6dbb524c7af06710766f486ad7e93 data/refinedstorage/recipes/coloring_recipes/gray_crafter_manager.json\ndcee57ab0ba8233854f0db8fe665051d201a5fdd data/refinedstorage/recipes/coloring_recipes/gray_crafting_grid.json\n4c499c7feac78f060c224f7da65c24ee57725e9e data/refinedstorage/recipes/coloring_recipes/gray_crafting_monitor.json\n372b40564dbb3152f8be6f416a7711b7b65f60cd data/refinedstorage/recipes/coloring_recipes/gray_detector.json\nc1e9273af3ca3b242e14945fc90a57aea5117f01 data/refinedstorage/recipes/coloring_recipes/gray_disk_manipulator.json\n9cecd6f9d03722b87a26f9705db8a253d6f1796d data/refinedstorage/recipes/coloring_recipes/gray_fluid_grid.json\naff07f6c78363a60c4c21672ebaecf7cf22ee159 data/refinedstorage/recipes/coloring_recipes/gray_grid.json\nf0ecd6ccd48024dc2215e73a281ff7a51c8d03c8 data/refinedstorage/recipes/coloring_recipes/gray_network_receiver.json\n8e2ee645d974e0c729d1062d91c70bedf6011dfd data/refinedstorage/recipes/coloring_recipes/gray_network_transmitter.json\na8adbf5e2f8f4b56a057d070e9888a8c034504f3 data/refinedstorage/recipes/coloring_recipes/gray_pattern_grid.json\nc9a3e09908a7ea0ab06fe3479147ecad4109f392 data/refinedstorage/recipes/coloring_recipes/gray_relay.json\n18c39313de520b58c932425124636d2372e0eb36 data/refinedstorage/recipes/coloring_recipes/gray_security_manager.json\n9636a002ade247edd0b2050d26ccb378f04eec9f data/refinedstorage/recipes/coloring_recipes/gray_wireless_transmitter.json\n571222e11b04c8c6674d2f16271d3bb58036353d data/refinedstorage/recipes/coloring_recipes/green_controller.json\na06ff50f11e287f88c2becff762dfda010752889 data/refinedstorage/recipes/coloring_recipes/green_crafter.json\na9ddaf744dcb1157b29604db33cd6bd46a60579f data/refinedstorage/recipes/coloring_recipes/green_crafter_manager.json\n5db8a75ccc60e014d9ad80d0610eb15125a55c49 data/refinedstorage/recipes/coloring_recipes/green_crafting_grid.json\ncd581941ade93fef9c8cbc05a0b52378663ee89c data/refinedstorage/recipes/coloring_recipes/green_crafting_monitor.json\nd61ba813c27e1eed5e5dd2ace77662bfc60d3ef2 data/refinedstorage/recipes/coloring_recipes/green_detector.json\n509a9d12aeba7d2342d7ba2b08b8286d7ac5c356 data/refinedstorage/recipes/coloring_recipes/green_disk_manipulator.json\n84d16780e7d8c5eec35b2d0916bbf3ac2558f7d9 data/refinedstorage/recipes/coloring_recipes/green_fluid_grid.json\n19e0ac130c216c62826c4505ac0fae1e1ecbde56 data/refinedstorage/recipes/coloring_recipes/green_grid.json\n333f3249ffc14e2e69c85a6f4f9d218ae25815f2 data/refinedstorage/recipes/coloring_recipes/green_network_receiver.json\na3324bdd1f7f735696680c49e0d03e688ccb2ca0 data/refinedstorage/recipes/coloring_recipes/green_network_transmitter.json\ne7b213d23d8b95e5d694e4be4eda9ad5b1473e64 data/refinedstorage/recipes/coloring_recipes/green_pattern_grid.json\ne930e7e251ff813fa59b994a1e9269b5e7dee126 data/refinedstorage/recipes/coloring_recipes/green_relay.json\n697124ea286b4ba093101fe9b76fa11da2385b82 data/refinedstorage/recipes/coloring_recipes/green_security_manager.json\n8b96cdcfa7cbdb2b89df3ce19e951d7f39be5616 data/refinedstorage/recipes/coloring_recipes/green_wireless_transmitter.json\n23e96eb30da11115b605fdca12bf1e05ecdff4de data/refinedstorage/recipes/coloring_recipes/grid.json\n5e9675aaef7ddc77b12556cbb9791598a92a07f3 data/refinedstorage/recipes/coloring_recipes/light_gray_controller.json\n98fff324cb8b935b7a9516b1eba2fb784b65a3be data/refinedstorage/recipes/coloring_recipes/light_gray_crafter.json\nb126c981954923e0a320c860cce9ddca6d672f66 data/refinedstorage/recipes/coloring_recipes/light_gray_crafter_manager.json\n17cb71c9405814aba06b457d6af6af4d32901859 data/refinedstorage/recipes/coloring_recipes/light_gray_crafting_grid.json\n2fb5bc2a239347cc3ae4d6740ac230f04ef4e983 data/refinedstorage/recipes/coloring_recipes/light_gray_crafting_monitor.json\n7d22c72c3cec2222329b798d080674403dcdc123 data/refinedstorage/recipes/coloring_recipes/light_gray_detector.json\n1b4a0a0deeb2df01e6f73e2ef4a894bd9b060f28 data/refinedstorage/recipes/coloring_recipes/light_gray_disk_manipulator.json\nb2a284139ae79e1338d89b06452ef8efec0b3e90 data/refinedstorage/recipes/coloring_recipes/light_gray_fluid_grid.json\n67373e80a26d1da083b85922524dab408bf53839 data/refinedstorage/recipes/coloring_recipes/light_gray_grid.json\nbff40091f772b9f2a24fa7e5e2470f6c2c2de55b data/refinedstorage/recipes/coloring_recipes/light_gray_network_receiver.json\na1e2bef7f7482107903171d5132cdf12c3ac6ab8 data/refinedstorage/recipes/coloring_recipes/light_gray_network_transmitter.json\n4cab0eece82ffdd908f52dd4e1a060fdfa0d308c data/refinedstorage/recipes/coloring_recipes/light_gray_pattern_grid.json\n06b1dd6edafe4a8dc03688e65d2540abce6b385f data/refinedstorage/recipes/coloring_recipes/light_gray_relay.json\nb1042ed6d8ec775933db67d4fec619056d659bba data/refinedstorage/recipes/coloring_recipes/light_gray_security_manager.json\n3111fcc735ef720b9bc762606c710f45ffd48400 data/refinedstorage/recipes/coloring_recipes/light_gray_wireless_transmitter.json\nae13a92dbc4744a003148eff1d3dcecaa47e0d23 data/refinedstorage/recipes/coloring_recipes/lime_controller.json\nb5d9f3882743a3ef34d5b25024002824ea96baf2 data/refinedstorage/recipes/coloring_recipes/lime_crafter.json\n9896b152c54adc37cdbe7878ad5b6a8c6bdd3121 data/refinedstorage/recipes/coloring_recipes/lime_crafter_manager.json\n1db21f1300c4cbb3265c556c6744549383b9a555 data/refinedstorage/recipes/coloring_recipes/lime_crafting_grid.json\n0fb2a066450b1de109aa9caba9be689215170c35 data/refinedstorage/recipes/coloring_recipes/lime_crafting_monitor.json\nc6edccdb599a1cfc0b03bb79ac9b85c809419ec2 data/refinedstorage/recipes/coloring_recipes/lime_detector.json\n934dd2b4e0b12f5f5f988d01a3963bde832920be data/refinedstorage/recipes/coloring_recipes/lime_disk_manipulator.json\n2b7c26801fd95c0a24d58d0305d6bad8e79090c5 data/refinedstorage/recipes/coloring_recipes/lime_fluid_grid.json\n65ef043e374ee6f59f65dbdc88b286da12af3c71 data/refinedstorage/recipes/coloring_recipes/lime_grid.json\nb0cfb3da8622f05ed21921f924fa51b415b84f38 data/refinedstorage/recipes/coloring_recipes/lime_network_receiver.json\nefef0d233db0be3a0fe2fffb14388058b7a0dbbf data/refinedstorage/recipes/coloring_recipes/lime_network_transmitter.json\n8d1f6f9e387d8b0d83ad97846148a1aafe0d3a5e data/refinedstorage/recipes/coloring_recipes/lime_pattern_grid.json\nfbf0f28d64c918570d519417f1b1cd65ec368066 data/refinedstorage/recipes/coloring_recipes/lime_relay.json\n20bfcb5904525581d2a0c921f3ed18a951629cf5 data/refinedstorage/recipes/coloring_recipes/lime_security_manager.json\n80bccc5833f48612764a8c84c30e5abfed586f6f data/refinedstorage/recipes/coloring_recipes/lime_wireless_transmitter.json\nfb508d9df420507adde445a14bf861f1757cb25c data/refinedstorage/recipes/coloring_recipes/magenta_controller.json\n9a09eaaf701c1c109e58a173844a3e4ef4f1c17f data/refinedstorage/recipes/coloring_recipes/magenta_crafter.json\ne45c83d5bc6d79866d797052d0315368b97b3b7e data/refinedstorage/recipes/coloring_recipes/magenta_crafter_manager.json\na149625b63cf3f12a4cf2348c4a1b0b5c6c91bea data/refinedstorage/recipes/coloring_recipes/magenta_crafting_grid.json\nca44b8335b9f2b9cae96039e0ff0cda5a2ecfb19 data/refinedstorage/recipes/coloring_recipes/magenta_crafting_monitor.json\n826f3b02b1cddf927e6815d28cda43c7c3c6bcd0 data/refinedstorage/recipes/coloring_recipes/magenta_detector.json\nf4160ad5703892ac81539dfe5d42dfa56a66fb5e data/refinedstorage/recipes/coloring_recipes/magenta_disk_manipulator.json\n1677d3ffae4312141d2e0aa0cba00241074172b5 data/refinedstorage/recipes/coloring_recipes/magenta_fluid_grid.json\na2c152975047b74488665e2ae2680ca5542a6831 data/refinedstorage/recipes/coloring_recipes/magenta_grid.json\n5140b7d4b1035670e5a42744a8c911e22bfb7d8b data/refinedstorage/recipes/coloring_recipes/magenta_network_receiver.json\ndb1ab8b0c13236fb4179d20df1854baafb84698b data/refinedstorage/recipes/coloring_recipes/magenta_network_transmitter.json\ne75b8d1066fb2d9e3077952993df6a9081603181 data/refinedstorage/recipes/coloring_recipes/magenta_pattern_grid.json\n81801f29a3e554e4c4ed98b8b0f71418319f8f8c data/refinedstorage/recipes/coloring_recipes/magenta_relay.json\n857f71c7ceaf827efd01ba574c88881e4980e3ef data/refinedstorage/recipes/coloring_recipes/magenta_security_manager.json\n369e62e1080765c60d0781de53ab3859c4b665c4 data/refinedstorage/recipes/coloring_recipes/magenta_wireless_transmitter.json\ne5e382659de78fdab2030e7e5d462e7556c7988a data/refinedstorage/recipes/coloring_recipes/network_receiver.json\ne0183a74741e0d5768c9336f64a26aafffd46f73 data/refinedstorage/recipes/coloring_recipes/network_transmitter.json\n52473cf95f53e31da36cb43f40b6e102840ca392 data/refinedstorage/recipes/coloring_recipes/orange_controller.json\n6524d474a295f6852121e19ee55f2a82991d3cb9 data/refinedstorage/recipes/coloring_recipes/orange_crafter.json\n670d38ae734ddbd110daed5a621b268084ccc5d9 data/refinedstorage/recipes/coloring_recipes/orange_crafter_manager.json\n53d29ecc2217e48f4c8a9f38c5be6eba9876f6ba data/refinedstorage/recipes/coloring_recipes/orange_crafting_grid.json\n302a81df05265e4e59b4d84a14e7bb64ba5af729 data/refinedstorage/recipes/coloring_recipes/orange_crafting_monitor.json\n9887bc0031479ed703e976e5470e9f0b0fa2af35 data/refinedstorage/recipes/coloring_recipes/orange_detector.json\n3a032d126abb017dea46201f92afec58c7850ec5 data/refinedstorage/recipes/coloring_recipes/orange_disk_manipulator.json\n8c681ffaa103480ebc523ac1fd957a02ffe0ad6c data/refinedstorage/recipes/coloring_recipes/orange_fluid_grid.json\n2531c751e09a4eef9adea51ccb7f251a8df371ab data/refinedstorage/recipes/coloring_recipes/orange_grid.json\n0b51e2aaec752b3849c9add94c685fa21ce241c1 data/refinedstorage/recipes/coloring_recipes/orange_network_receiver.json\n8cda1a4f63ab5dac7fb1931630f4a36766ace3a0 data/refinedstorage/recipes/coloring_recipes/orange_network_transmitter.json\nb454a0ce04a16e18d6d1d9b3a82f356c2f5a5a43 data/refinedstorage/recipes/coloring_recipes/orange_pattern_grid.json\nbc3e05adc7957579b49485cdc44ae48c84fdfce9 data/refinedstorage/recipes/coloring_recipes/orange_relay.json\ne6d772ca91f90cd3fba8c6c1686f025cdcabebbd data/refinedstorage/recipes/coloring_recipes/orange_security_manager.json\n44cf2cc6eecb342b06434db9ee1c9bcc4e5fb096 data/refinedstorage/recipes/coloring_recipes/orange_wireless_transmitter.json\n96c9e64ac6b1fda884e583c3dfc578f17523185d data/refinedstorage/recipes/coloring_recipes/pattern_grid.json\n44379d03945259c390aeb7bfcc83d2dbbb789cd5 data/refinedstorage/recipes/coloring_recipes/pink_controller.json\n7b324217e4253b4c26813ad51bc799e983d73a0e data/refinedstorage/recipes/coloring_recipes/pink_crafter.json\ncdbca04e29f809d3ad67ff02679a24ba2a4aa07d data/refinedstorage/recipes/coloring_recipes/pink_crafter_manager.json\nd2c7a7a5eccea5262864f88a4e5154a0d1d8d96b data/refinedstorage/recipes/coloring_recipes/pink_crafting_grid.json\n5b8eb35ccf50004142d698fcbe605185a3d72b8a data/refinedstorage/recipes/coloring_recipes/pink_crafting_monitor.json\nfbc20d7148217e2160e8ffa22059c441c761d720 data/refinedstorage/recipes/coloring_recipes/pink_detector.json\na2abdb193c34df50760d3cb1f4c5704ee39b41df data/refinedstorage/recipes/coloring_recipes/pink_disk_manipulator.json\n2f2a5446b775976b62915a43f4ff9e21631ebaf9 data/refinedstorage/recipes/coloring_recipes/pink_fluid_grid.json\n8f8fde9aece7f5dd15c5579e5686be03085fdb9d data/refinedstorage/recipes/coloring_recipes/pink_grid.json\nece30292dfe346d4c25778388932635753380621 data/refinedstorage/recipes/coloring_recipes/pink_network_receiver.json\nff5a0d844e0a2390a54a07ac9edeacd2e219592d data/refinedstorage/recipes/coloring_recipes/pink_network_transmitter.json\n47dc1079808dd60981c2eab6135fefe6d0c3dc74 data/refinedstorage/recipes/coloring_recipes/pink_pattern_grid.json\n3ba8e454038a8a504d5f64954484a735fefe3265 data/refinedstorage/recipes/coloring_recipes/pink_relay.json\n6c06e158f115242158aa4f9bef345c22697e6c95 data/refinedstorage/recipes/coloring_recipes/pink_security_manager.json\n9b988f2425d07acf55a04cd8310a5ad7dc18370f data/refinedstorage/recipes/coloring_recipes/pink_wireless_transmitter.json\n040afa4d28b2bc0a8fba9551c2f9a83a8a55275d data/refinedstorage/recipes/coloring_recipes/purple_controller.json\nbce4dd6a44a136d2415edec1ac9c53b1c3f51219 data/refinedstorage/recipes/coloring_recipes/purple_crafter.json\n98eb23aaa064bd5e4b9099f67218ef11643e68ae data/refinedstorage/recipes/coloring_recipes/purple_crafter_manager.json\n12f97e8bcfcc92e85e26365dc23650c4f1790a8c data/refinedstorage/recipes/coloring_recipes/purple_crafting_grid.json\n3bb0c59da1362c330c8427933c44a274933bff30 data/refinedstorage/recipes/coloring_recipes/purple_crafting_monitor.json\n4ad1ceb85568ac121220d3ad1911d7335b68e783 data/refinedstorage/recipes/coloring_recipes/purple_detector.json\n67b741e5a74bba2d24dc22f3b9c59ed8e9ab8ee2 data/refinedstorage/recipes/coloring_recipes/purple_disk_manipulator.json\n0bcbdf519eabf09e3818588558b3e9ce7d6fceb3 data/refinedstorage/recipes/coloring_recipes/purple_fluid_grid.json\n4eefec69f667cf88eb3a1e651fd2beba93870597 data/refinedstorage/recipes/coloring_recipes/purple_grid.json\n8a5e04a5d6130b299bacf95a62fab5f8e707877b data/refinedstorage/recipes/coloring_recipes/purple_network_receiver.json\n4f2e6f74509c70d312b71632f4c38be3cfeba77c data/refinedstorage/recipes/coloring_recipes/purple_network_transmitter.json\n7309f883662ccbbaa97fa3cdb479674c2cdc7516 data/refinedstorage/recipes/coloring_recipes/purple_pattern_grid.json\nea8f6b5d26335c64f511f8d854a6f18c944acdcb data/refinedstorage/recipes/coloring_recipes/purple_relay.json\n661e9d811201abfb56b7b27175b9ec1e10de1584 data/refinedstorage/recipes/coloring_recipes/purple_security_manager.json\n384938122caeca74c92e8047e386244db2e19985 data/refinedstorage/recipes/coloring_recipes/purple_wireless_transmitter.json\n5213d1fc2c6269321b78a23eafc533968677631e data/refinedstorage/recipes/coloring_recipes/red_controller.json\n8d9ca91c28c9ca40c932688bccb88261f6c6402c data/refinedstorage/recipes/coloring_recipes/red_crafter.json\n98b6fb4a2141356fb7e18995288935d5b0617c4e data/refinedstorage/recipes/coloring_recipes/red_crafter_manager.json\ne424d6daf7fdfa9f62c920b8f551dafb6907ea9c data/refinedstorage/recipes/coloring_recipes/red_crafting_grid.json\n0160755468a19e98b4dbc4447b1efae7dec53e0f data/refinedstorage/recipes/coloring_recipes/red_crafting_monitor.json\n1a9cbbb583120ee079d3191bbf399651cd89577a data/refinedstorage/recipes/coloring_recipes/red_detector.json\n29148381c6707e3b7181d534255baee78917ac95 data/refinedstorage/recipes/coloring_recipes/red_disk_manipulator.json\n4d63aa706daf331f47978f66e0fd3dc29ae223ac data/refinedstorage/recipes/coloring_recipes/red_fluid_grid.json\nc8be1ebdf463794c8aeb52003d035ebac78be94d data/refinedstorage/recipes/coloring_recipes/red_grid.json\n4a3d94a64b099bd47c84e15b3fabba7fc985f065 data/refinedstorage/recipes/coloring_recipes/red_network_receiver.json\ndc1c971e5d0f8874c294b975309ea8f01ea51e5e data/refinedstorage/recipes/coloring_recipes/red_network_transmitter.json\nee5aeaeb62cef55b5538018706a83d624748ef00 data/refinedstorage/recipes/coloring_recipes/red_pattern_grid.json\n9dc5bda9e6a365c83a50b039935603ef7c977938 data/refinedstorage/recipes/coloring_recipes/red_relay.json\n35215d8666e19b9c91e32b20d461f2b098f5f734 data/refinedstorage/recipes/coloring_recipes/red_security_manager.json\ndd2d8f572913d26f79cfee38a679fec72ba27a40 data/refinedstorage/recipes/coloring_recipes/red_wireless_transmitter.json\n1bfa44597a6301d570a09ac73be6bca9da6f9483 data/refinedstorage/recipes/coloring_recipes/relay.json\n83f1a7f20933935059cf86c44b4194718c3cff1d data/refinedstorage/recipes/coloring_recipes/security_manager.json\nb42095cd9222c36d358a578f48af359a0bfdf026 data/refinedstorage/recipes/coloring_recipes/white_controller.json\nc8b886a2890b64e3f746ae55f3dcc9c526fc390d data/refinedstorage/recipes/coloring_recipes/white_crafter.json\n1564dc43ec03da2e6bf11e7ee9a73a65a3506690 data/refinedstorage/recipes/coloring_recipes/white_crafter_manager.json\n0efeb724bf6b11cb03f91f1c1de6dfe0f7731704 data/refinedstorage/recipes/coloring_recipes/white_crafting_grid.json\n4ed50e1f8369240d1f87e9be9190ad7244b2e996 data/refinedstorage/recipes/coloring_recipes/white_crafting_monitor.json\nb8123ca500d032d5cf14fa4eb6acf94819735c8f data/refinedstorage/recipes/coloring_recipes/white_detector.json\n27bdf73bccced8c2f694be1327f6e59d38e667fe data/refinedstorage/recipes/coloring_recipes/white_disk_manipulator.json\n37681dbb38a2cae990001cadda98107f7a85d8ba data/refinedstorage/recipes/coloring_recipes/white_fluid_grid.json\n746481e67dc39802296560c6286a1896162f656e data/refinedstorage/recipes/coloring_recipes/white_grid.json\nd3fabfda138031705c70e6f558e89a80b6304f7f data/refinedstorage/recipes/coloring_recipes/white_network_receiver.json\nf0e6c4760dd916b3f27c67d9d372a12d7438eefd data/refinedstorage/recipes/coloring_recipes/white_network_transmitter.json\n88d61adc326d663112475ea2eeafc39e2c00dfb1 data/refinedstorage/recipes/coloring_recipes/white_pattern_grid.json\nfc289082d30d79a6901963f169c96cc9bb13c2db data/refinedstorage/recipes/coloring_recipes/white_relay.json\n6a813bd5fe61dfa8f8843c0a41eb63c8a179d24c data/refinedstorage/recipes/coloring_recipes/white_security_manager.json\nd10924039deb155dbe8626c1a122f7a4a2b5a1ba data/refinedstorage/recipes/coloring_recipes/white_wireless_transmitter.json\nde06ff58be01086d2db6708903219a6d30e54dbd data/refinedstorage/recipes/coloring_recipes/wireless_transmitter.json\n5ab08310c1bca2d1e6fc97f1611db8dce66b01d3 data/refinedstorage/recipes/coloring_recipes/yellow_controller.json\nd988c6e9533eb8e93ec8b219b5d032596d89ae8d data/refinedstorage/recipes/coloring_recipes/yellow_crafter.json\n79cfee17ee03565aa0a27ada8d9f375b4cb665bc data/refinedstorage/recipes/coloring_recipes/yellow_crafter_manager.json\n8a4c6b78bb4fef3ceef338ac655c80503190059d data/refinedstorage/recipes/coloring_recipes/yellow_crafting_grid.json\na1b1f47a605beccad8acacfbaf77964e991f0a4f data/refinedstorage/recipes/coloring_recipes/yellow_crafting_monitor.json\n10f0ea9ac167aee81a610da0c4b16465be3c39e0 data/refinedstorage/recipes/coloring_recipes/yellow_detector.json\n335a728979bc32d15ed7d72a84e3eddfa9c55b95 data/refinedstorage/recipes/coloring_recipes/yellow_disk_manipulator.json\n0393b2ce55a6202b4eee5ce0b2d3344ab2b8e11b data/refinedstorage/recipes/coloring_recipes/yellow_fluid_grid.json\n9cef292a0457b7987442d04572047f286bc20fc0 data/refinedstorage/recipes/coloring_recipes/yellow_grid.json\n63c20b0f45f8453a2588da8e0f915de07d91073f data/refinedstorage/recipes/coloring_recipes/yellow_network_receiver.json\n0c0e1fc0dd6d4251b655e3c3232ab393f380722c data/refinedstorage/recipes/coloring_recipes/yellow_network_transmitter.json\nd66efb72494084b29a32b81c1f72bc5b37088689 data/refinedstorage/recipes/coloring_recipes/yellow_pattern_grid.json\n513f415c4ba145ab71bfa892a04ddb02cfaa80c8 data/refinedstorage/recipes/coloring_recipes/yellow_relay.json\n656ab81fea0782a64a0b129f50095cbcff47dc41 data/refinedstorage/recipes/coloring_recipes/yellow_security_manager.json\n7fc4f29327366fb10065e0fad63df119c706d55e data/refinedstorage/recipes/coloring_recipes/yellow_wireless_transmitter.json\nbc35cb59ff004ffc78886d46608b3c81072bfdbd data/refinedstorage/recipes/crafting_grid/black_crafting_grid.json\n97f1bd4e344764dbdefd260fb35c749d4b7fdb21 data/refinedstorage/recipes/crafting_grid/blue_crafting_grid.json\n867de3ece15a35979d7ed3e0d1a10c581a825ab7 data/refinedstorage/recipes/crafting_grid/brown_crafting_grid.json\n0f17bd970606073347d35401d2fe7bbf66033052 data/refinedstorage/recipes/crafting_grid/crafting_grid.json\n41fe7509aa8bfa0dba6e26641ee318c89b4f583a data/refinedstorage/recipes/crafting_grid/cyan_crafting_grid.json\n16256265f3c2a6ad33fc3dde40c588f94de97cbb data/refinedstorage/recipes/crafting_grid/gray_crafting_grid.json\n554f972cfa470f77b2ed03e3c580a489d981200e data/refinedstorage/recipes/crafting_grid/green_crafting_grid.json\n246bd2536f0109a299f4d8f46e820dbaa94f8f83 data/refinedstorage/recipes/crafting_grid/light_gray_crafting_grid.json\nf8264879f798b5977e2fa8598b7b70895f18bc77 data/refinedstorage/recipes/crafting_grid/lime_crafting_grid.json\n2e50e2eb39657b2dbe7a804ac8fc520f5f90d2cb data/refinedstorage/recipes/crafting_grid/magenta_crafting_grid.json\na4b7575e6a11a3717c1a72cff0273c621b6f3a0d data/refinedstorage/recipes/crafting_grid/orange_crafting_grid.json\n580d7623cbe6b53a1f0d84dcd5fdfd77716251e1 data/refinedstorage/recipes/crafting_grid/pink_crafting_grid.json\n806d5168ce1cc39a8fd39e0eda55de1f4ab20484 data/refinedstorage/recipes/crafting_grid/purple_crafting_grid.json\ndefa112e99475c51d55edabbbc54a8ae26e32257 data/refinedstorage/recipes/crafting_grid/red_crafting_grid.json\nb4d1347ed742afbde81c5b14c132a21eaf9ca884 data/refinedstorage/recipes/crafting_grid/white_crafting_grid.json\nc9a5db4ebcd1924d32787987fed38a164acb360f data/refinedstorage/recipes/crafting_grid/yellow_crafting_grid.json\n06566cbfe62a2783dab30391f8353175214a2071 data/refinedstorage/recipes/fluid_grid/black_fluid_grid.json\ndba62f4ae40b27bdf17803904fab31d8e3c1b481 data/refinedstorage/recipes/fluid_grid/blue_fluid_grid.json\n84c68d2bcc4831e93d3da768e49ce193474193c3 data/refinedstorage/recipes/fluid_grid/brown_fluid_grid.json\n81db210076da3b665841bd4eb17ce80c881aa782 data/refinedstorage/recipes/fluid_grid/cyan_fluid_grid.json\n3f27e8e601206031c607f74ffb8bfa27434c4eea data/refinedstorage/recipes/fluid_grid/fluid_grid.json\n772ec2b3e75670f3f574fd1f9a0a50229df71c23 data/refinedstorage/recipes/fluid_grid/gray_fluid_grid.json\nc1c3ca490a74e17f20ff413d8300f5bf4dadce28 data/refinedstorage/recipes/fluid_grid/green_fluid_grid.json\n7e5ac70a9cad754664b18caba3995c2df2edafbc data/refinedstorage/recipes/fluid_grid/light_gray_fluid_grid.json\n4eb90edc1dd25cd99eb7f171afd84d647e9f3a5d data/refinedstorage/recipes/fluid_grid/lime_fluid_grid.json\n12993cc922c42d66ea486143178bde12814d6f72 data/refinedstorage/recipes/fluid_grid/magenta_fluid_grid.json\nad42253972dde97319fc963cca9f276cd682a434 data/refinedstorage/recipes/fluid_grid/orange_fluid_grid.json\n42fa4ba965eb143060edc58fd354fd166d7d7ee3 data/refinedstorage/recipes/fluid_grid/pink_fluid_grid.json\na3cd500967a7ca8bbdc63b5f7e28cda83332f764 data/refinedstorage/recipes/fluid_grid/purple_fluid_grid.json\nacc3d1c9823a56f4fcd3ed4a10800017b3470308 data/refinedstorage/recipes/fluid_grid/red_fluid_grid.json\nf82ad46f703166947701746f367fb3e9c9ee13e6 data/refinedstorage/recipes/fluid_grid/white_fluid_grid.json\n0493642eb294a1ddd03aea909e9412c6e7d7cb13 data/refinedstorage/recipes/fluid_grid/yellow_fluid_grid.json\ncf865a91fe46c1a6d177eba5bd659d7306e4b752 data/refinedstorage/recipes/pattern_grid/black_pattern_grid.json\n595c344e5a3ee10eedbb3911adb7d1637d2d25c5 data/refinedstorage/recipes/pattern_grid/blue_pattern_grid.json\n78ce90102d193d4d1dac5c93a1aef10188e63258 data/refinedstorage/recipes/pattern_grid/brown_pattern_grid.json\n77f667c9bb96f33e8d753b54bf770b63fca33e7c data/refinedstorage/recipes/pattern_grid/cyan_pattern_grid.json\nfc5e7f25f6a72af1623604cfa64a978f5ccffeec data/refinedstorage/recipes/pattern_grid/gray_pattern_grid.json\ndc03f0e09c3b4ab00ef3ee40c7cc09ec9b82e30e data/refinedstorage/recipes/pattern_grid/green_pattern_grid.json\n7ea662fadd5ab396382788cce9b9f3b46a454f29 data/refinedstorage/recipes/pattern_grid/light_gray_pattern_grid.json\ne7affc6561b15e1ae04bce3daa9824fe137bf909 data/refinedstorage/recipes/pattern_grid/lime_pattern_grid.json\n65f0ef8dfae6e58433b9c59def75afaf5c0b632c data/refinedstorage/recipes/pattern_grid/magenta_pattern_grid.json\n37dcf0cd09c15ece8123456213b0d510d754ab22 data/refinedstorage/recipes/pattern_grid/orange_pattern_grid.json\nbda3a866c990f55409a0ff0d5643184d73e23961 data/refinedstorage/recipes/pattern_grid/pattern_grid.json\ncfbc0ab0d39fca6ddc432c497427019bb7e70dad data/refinedstorage/recipes/pattern_grid/pink_pattern_grid.json\na9d41d0fd2a9eb83673ce0c4015d40a249f9afa5 data/refinedstorage/recipes/pattern_grid/purple_pattern_grid.json\n151b980298e4968ef4227cc62a351cd2c17c2331 data/refinedstorage/recipes/pattern_grid/red_pattern_grid.json\nef55bc909cc5ac605db1a673a310942549072eab data/refinedstorage/recipes/pattern_grid/white_pattern_grid.json\nabd03dded7af5ea3d4d05f192496760d1a07470a data/refinedstorage/recipes/pattern_grid/yellow_pattern_grid.json\n"
  },
  {
    "path": "src/generated/resources/.cache/c52895b732924e707cb6e5ddd1c6b6962039449c",
    "content": "// 1.20.4\t2024-02-12T20:34:18.531158825\tBlock Entity Type Tags\n98555d946827da8ddb7a7c451a1c99f4d0184ad3 data/packingtape/tags/block_entity_type/blacklist/problematic.json\n"
  },
  {
    "path": "src/generated/resources/.cache/cb654f100e416ac39358630d6623170b9bfdc5d2",
    "content": "// 1.20.4\t2024-02-12T20:34:18.533198729\tTags for minecraft:item mod id refinedstorage\n061bf4c2f3bdd530115615f2b04e55c2602908bd data/refinedstorage/tags/items/controller.json\n407a16e5d941c69915f75b135a13e9144cc9c43e data/refinedstorage/tags/items/crafter.json\ndc1342f1d3e6a4cd8eaaa52429a011c10c6c2d96 data/refinedstorage/tags/items/crafter_manager.json\n2f8fee222ac543909ae06a35de3c08e3e19f4f4b data/refinedstorage/tags/items/crafting_grid.json\nbf4f4ed5b02babe4717894e4823d5541d69dbfe6 data/refinedstorage/tags/items/crafting_monitor.json\n6abdee7222576fd0b2da7f86954e35ca8cab4d25 data/refinedstorage/tags/items/detector.json\n7b9c6d4ef32d5e63c327d71a8758f8b900ac9cb6 data/refinedstorage/tags/items/disk_manipulator.json\n651ca3794c0a1c28aa275a9814de7fdc04c90653 data/refinedstorage/tags/items/fluid_grid.json\n31a65b9d23f79a0191f78ba46c5ed39942d38023 data/refinedstorage/tags/items/grid.json\n295fce6281b688f4992b1181c58e9a52c80465a1 data/refinedstorage/tags/items/network_receiver.json\n37ea6fd2ffdb762fb9351359ddf9cc0f401bbbf5 data/refinedstorage/tags/items/network_transmitter.json\n9dae822d3373a348a6ab4e11de2056f369a0253b data/refinedstorage/tags/items/pattern_grid.json\n52c8060208bf763f487313b8de6243550cc2f63a data/refinedstorage/tags/items/relay.json\n555b5c80da6838aa2a4d8f5044276852b1bc525d data/refinedstorage/tags/items/security_manager.json\ne740b41d26fe5be1b6251db461627b8e5e5925aa data/refinedstorage/tags/items/wireless_transmitter.json\n"
  },
  {
    "path": "src/generated/resources/.cache/f481442ce31db2c3b3dabb5b6d85f9a78568164e",
    "content": "// 1.20.4\t2024-02-12T20:34:18.553572165\tTags for minecraft:block mod id refinedstorage\n7af8948adf9214476b9b2995799c32277c960c55 data/forge/tags/blocks/relocation_not_supported.json\n061bf4c2f3bdd530115615f2b04e55c2602908bd data/refinedstorage/tags/blocks/controller.json\n407a16e5d941c69915f75b135a13e9144cc9c43e data/refinedstorage/tags/blocks/crafter.json\ndc1342f1d3e6a4cd8eaaa52429a011c10c6c2d96 data/refinedstorage/tags/blocks/crafter_manager.json\n2f8fee222ac543909ae06a35de3c08e3e19f4f4b data/refinedstorage/tags/blocks/crafting_grid.json\nbf4f4ed5b02babe4717894e4823d5541d69dbfe6 data/refinedstorage/tags/blocks/crafting_monitor.json\n4c7059780d3896d0f042e88076b8a0326e0cf86d data/refinedstorage/tags/blocks/creative_controller.json\n6abdee7222576fd0b2da7f86954e35ca8cab4d25 data/refinedstorage/tags/blocks/detector.json\n7b9c6d4ef32d5e63c327d71a8758f8b900ac9cb6 data/refinedstorage/tags/blocks/disk_manipulator.json\n651ca3794c0a1c28aa275a9814de7fdc04c90653 data/refinedstorage/tags/blocks/fluid_grid.json\n31a65b9d23f79a0191f78ba46c5ed39942d38023 data/refinedstorage/tags/blocks/grid.json\n295fce6281b688f4992b1181c58e9a52c80465a1 data/refinedstorage/tags/blocks/network_receiver.json\n37ea6fd2ffdb762fb9351359ddf9cc0f401bbbf5 data/refinedstorage/tags/blocks/network_transmitter.json\n9dae822d3373a348a6ab4e11de2056f369a0253b data/refinedstorage/tags/blocks/pattern_grid.json\n52c8060208bf763f487313b8de6243550cc2f63a data/refinedstorage/tags/blocks/relay.json\n555b5c80da6838aa2a4d8f5044276852b1bc525d data/refinedstorage/tags/blocks/security_manager.json\ne740b41d26fe5be1b6251db461627b8e5e5925aa data/refinedstorage/tags/blocks/wireless_transmitter.json\n"
  },
  {
    "path": "src/generated/resources/.cache/fd27170b6bf91459ed2598d25721edfeafc82e0a",
    "content": "// 1.20.4\t2024-02-12T20:34:18.545348794\tBlock States: refinedstorage\n7b69e3ab3a7471a50e264579d36c04adb8acad35 assets/refinedstorage/blockstates/black_controller.json\nc87045bd089212825bdd0f06b0d25e7bcf0e3f5d assets/refinedstorage/blockstates/black_crafter.json\n999fe91e1661d6b45f9c29878f06438b3b5919dc assets/refinedstorage/blockstates/black_crafter_manager.json\n6dfbf26cac2596445fce1b6bae6df2e3b161100a assets/refinedstorage/blockstates/black_crafting_grid.json\ncad10d852489b5c9f7bc570d658bc2d3503da7d7 assets/refinedstorage/blockstates/black_crafting_monitor.json\n7b69e3ab3a7471a50e264579d36c04adb8acad35 assets/refinedstorage/blockstates/black_creative_controller.json\n16e7f975097055171aa436c1a632715a9ef8341a assets/refinedstorage/blockstates/black_detector.json\n6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/black_disk_manipulator.json\n2d65d70d315150a429448eae15cd20045596d27b assets/refinedstorage/blockstates/black_fluid_grid.json\n2a89227c1e5c69cf378001ec5c804e8057b94925 assets/refinedstorage/blockstates/black_grid.json\nfb8aa2633b61db8bc3c6a0e4baac65089c48fc43 assets/refinedstorage/blockstates/black_network_receiver.json\n05ffd20caf7ca4db1806b9d0872b32804966368d assets/refinedstorage/blockstates/black_network_transmitter.json\n728791ad72200b43e0e873405aff863faaa0d667 assets/refinedstorage/blockstates/black_pattern_grid.json\n808e7192637fba2b5dff521b0b8830f9f62ca819 assets/refinedstorage/blockstates/black_relay.json\ne5c9aaad492c8643c7e82b9b8cdaa3bcbd1068e6 assets/refinedstorage/blockstates/black_security_manager.json\nd749ab3e2d6aae2c4ac4610850791d4e0ba31b72 assets/refinedstorage/blockstates/black_wireless_transmitter.json\nc259424f1ef73c4dc12d770ba1c47fcf965e6175 assets/refinedstorage/blockstates/blue_controller.json\n0b1e46e3502ef5dc39129f01e77423842f378523 assets/refinedstorage/blockstates/blue_crafter.json\n667d3a36aa89313f5ded585f8ada125a0380ea61 assets/refinedstorage/blockstates/blue_crafter_manager.json\n32a82613e09f6c5dc5dfa9ee6b0b7901518af5f4 assets/refinedstorage/blockstates/blue_crafting_grid.json\n274b86b9b6df510a58e65ca7b80529d1ba88c699 assets/refinedstorage/blockstates/blue_crafting_monitor.json\nc259424f1ef73c4dc12d770ba1c47fcf965e6175 assets/refinedstorage/blockstates/blue_creative_controller.json\nd71686564d14b615681df9140c6b4d6d948673cd assets/refinedstorage/blockstates/blue_detector.json\n6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/blue_disk_manipulator.json\n3822722dbfebcac426e9d07a8fbad76a3c72f106 assets/refinedstorage/blockstates/blue_fluid_grid.json\n031ee9de046949535200ccf5e1a5e9439adbb282 assets/refinedstorage/blockstates/blue_grid.json\n9ccd5c6695f09476c0a6c1af1728809efea90054 assets/refinedstorage/blockstates/blue_network_receiver.json\nb20dd47441068c7b8ed38c4ed4c857f6e0ec0b0b assets/refinedstorage/blockstates/blue_network_transmitter.json\na9fb566f3c1f6779ef2b03ec847d6736beab92cd assets/refinedstorage/blockstates/blue_pattern_grid.json\n3fae9d1e68030dbcbbaeb4534a39e915b1c8f976 assets/refinedstorage/blockstates/blue_relay.json\n69dac9e3833cd351672467aa34e19f2bf466cfe7 assets/refinedstorage/blockstates/blue_security_manager.json\n4566b01a555b7307bf1ea8390def853089a69d49 assets/refinedstorage/blockstates/blue_wireless_transmitter.json\nb78e4501f02364499a0aeaf599eb32fc010f1c58 assets/refinedstorage/blockstates/brown_controller.json\n965abf8e749ac0cf7b585946dfa5ea5898fdc9d9 assets/refinedstorage/blockstates/brown_crafter.json\n27b1077b0aa443abadd855ff340e10504ae6faec assets/refinedstorage/blockstates/brown_crafter_manager.json\nd01e8708c28a9aeb6658510d7aa767294607dc97 assets/refinedstorage/blockstates/brown_crafting_grid.json\n94e4f8e400897059d52362997170ffcae2291340 assets/refinedstorage/blockstates/brown_crafting_monitor.json\nb78e4501f02364499a0aeaf599eb32fc010f1c58 assets/refinedstorage/blockstates/brown_creative_controller.json\ncaa950648cde215f3110c9530a3916c38a578f61 assets/refinedstorage/blockstates/brown_detector.json\n6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/brown_disk_manipulator.json\necf5814b4e50a7ef37e3bbcc383ea0540ff34bc8 assets/refinedstorage/blockstates/brown_fluid_grid.json\nf67203e2d420ee9b164432a6c631c1045c0839f3 assets/refinedstorage/blockstates/brown_grid.json\na8af2cefa692c0485a61fd932cb9dbf3336a94b7 assets/refinedstorage/blockstates/brown_network_receiver.json\nb26700458e89654d8c180da1997f309532366ae0 assets/refinedstorage/blockstates/brown_network_transmitter.json\n1953b72641278b83ab9102612d21e8308dacc1ab assets/refinedstorage/blockstates/brown_pattern_grid.json\n449f908d91689f0750bfa9ea15212cdf884f8d37 assets/refinedstorage/blockstates/brown_relay.json\nb2bc3d1c93df4307a16eb3df245418318ba08b0f assets/refinedstorage/blockstates/brown_security_manager.json\n3ef998a83b2388ba0133c6d5fe9d3d96ee9823b5 assets/refinedstorage/blockstates/brown_wireless_transmitter.json\n6bebb7848ef81448082cb992878e5468cda66d3b assets/refinedstorage/blockstates/controller.json\n66a78b99df31444ee80aaf5790fdf29a5fb97c67 assets/refinedstorage/blockstates/crafter.json\n711443d364ea85b23bd61902e4cfec0897175b36 assets/refinedstorage/blockstates/crafter_manager.json\n9fdd6f844061b5d7eb5dc141f9a087a33e7297cd assets/refinedstorage/blockstates/crafting_grid.json\nc0f0ae43414371d80a42639792bb8845da5f06b7 assets/refinedstorage/blockstates/crafting_monitor.json\n6bebb7848ef81448082cb992878e5468cda66d3b assets/refinedstorage/blockstates/creative_controller.json\n32ed126a06d3cfadeaffdb5f72a92d0992841bf1 assets/refinedstorage/blockstates/cyan_controller.json\n90b9eb7f6ca9f3b3d0c6db53553abfc74236e9fe assets/refinedstorage/blockstates/cyan_crafter.json\nc07193099f8241889ef04dae18a2a57ab31f0e64 assets/refinedstorage/blockstates/cyan_crafter_manager.json\ne25b53ada26df3ac55b532b0e5a8b7d1378f8f6e assets/refinedstorage/blockstates/cyan_crafting_grid.json\n70a431cfe0a7b6049ad2c4d8da449b523151db70 assets/refinedstorage/blockstates/cyan_crafting_monitor.json\n32ed126a06d3cfadeaffdb5f72a92d0992841bf1 assets/refinedstorage/blockstates/cyan_creative_controller.json\nd39cb51f414057d970a458dfea5c191ec7ba06b0 assets/refinedstorage/blockstates/cyan_detector.json\n6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/cyan_disk_manipulator.json\n0b59eab2a3214c33ea7fdd50198e4f3943ea9cdb assets/refinedstorage/blockstates/cyan_fluid_grid.json\ne2c86885cf2995be56fdc0728e9e900021583cd5 assets/refinedstorage/blockstates/cyan_grid.json\n349ef6721ac006319818a900a9f2fef402b9c1c1 assets/refinedstorage/blockstates/cyan_network_receiver.json\n02875332d7cc05994f93f7d08d7f33f5f4692575 assets/refinedstorage/blockstates/cyan_network_transmitter.json\nb0452599b5e58599d488d497f1d64f2086d8f045 assets/refinedstorage/blockstates/cyan_pattern_grid.json\nf03e4611123ae67fb17aadc4ea23c00b94724e06 assets/refinedstorage/blockstates/cyan_relay.json\nbf496398c00ca9e5421afa96a3c309b2b9a09b78 assets/refinedstorage/blockstates/cyan_security_manager.json\n9cc1f2365298c5d92edc078988c162ca12ee1b58 assets/refinedstorage/blockstates/cyan_wireless_transmitter.json\n54c8d36899d719e379d0f45c48aae5938711825c assets/refinedstorage/blockstates/detector.json\n6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/disk_manipulator.json\ndad2436c0b678d06dc5568506c83f8acc3227e09 assets/refinedstorage/blockstates/fluid_grid.json\nbbadd742d5662d38447d6d8242c074816e227242 assets/refinedstorage/blockstates/gray_controller.json\n547ef6ae4c9797e02bc0ebe3c6f51c9959bd7a0b assets/refinedstorage/blockstates/gray_crafter.json\n45995d7e5902cf8f93c679df972915d6af8970a9 assets/refinedstorage/blockstates/gray_crafter_manager.json\n5bc03e1cb45ffa4e68813dfdb6a08c83275d519a assets/refinedstorage/blockstates/gray_crafting_grid.json\n3e50d6bc784f38230a670ca079c48a9313047b00 assets/refinedstorage/blockstates/gray_crafting_monitor.json\nbbadd742d5662d38447d6d8242c074816e227242 assets/refinedstorage/blockstates/gray_creative_controller.json\naa366bb135b9ea8f5015a16d31bb044634186baa assets/refinedstorage/blockstates/gray_detector.json\n6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/gray_disk_manipulator.json\n67fee64c36afe0e98dc75921c7a3f59d712fb194 assets/refinedstorage/blockstates/gray_fluid_grid.json\n19e248101a9be45e302512a47bd047da7799474f assets/refinedstorage/blockstates/gray_grid.json\nf7f6f6c790e006776bf86b69646d1ff40e77b077 assets/refinedstorage/blockstates/gray_network_receiver.json\n82e103363281a88aeec3677838c92835f2377b89 assets/refinedstorage/blockstates/gray_network_transmitter.json\n80604de4035aca7788b911888d33d1c4d73c73e6 assets/refinedstorage/blockstates/gray_pattern_grid.json\nd3b748f6d6499cb1d25b75f0416672007e2c8427 assets/refinedstorage/blockstates/gray_relay.json\nfde90f14de4329db7c8acff70e03d5807435af90 assets/refinedstorage/blockstates/gray_security_manager.json\n66c222b50b4bca71aa058b708259efd7b4a5515d assets/refinedstorage/blockstates/gray_wireless_transmitter.json\neaedbfdf6c84624f585530b187613d35da49220e assets/refinedstorage/blockstates/green_controller.json\n40a39c28577f7c8754ccef601cf271d36c013c75 assets/refinedstorage/blockstates/green_crafter.json\n12414cdabaf1ea9c9a48afce88f0535ac63218a1 assets/refinedstorage/blockstates/green_crafter_manager.json\n118ccfc4cb3ba98ade2f85771b8fa7850a8b39d5 assets/refinedstorage/blockstates/green_crafting_grid.json\na9391e55df0b63c7223e21c71f867c19ec87091a assets/refinedstorage/blockstates/green_crafting_monitor.json\neaedbfdf6c84624f585530b187613d35da49220e assets/refinedstorage/blockstates/green_creative_controller.json\n671bdde024f725835b8d7c70294666d67d013905 assets/refinedstorage/blockstates/green_detector.json\n6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/green_disk_manipulator.json\n9ae0a3edbd87718686e42978e70725e170cd2e3a assets/refinedstorage/blockstates/green_fluid_grid.json\n5d5a7cdf0fafae953b3a6d7bc0773eafd0bb36d1 assets/refinedstorage/blockstates/green_grid.json\n1f68b48cce41bb6bef4c1499b4cf82873f3f4d23 assets/refinedstorage/blockstates/green_network_receiver.json\nad9ae867a12847c3a33451c315459660133f988e assets/refinedstorage/blockstates/green_network_transmitter.json\ncb26162f351bf30aed31b993851156334371beac assets/refinedstorage/blockstates/green_pattern_grid.json\n2df12e30a33dfe832a61465727cedc1ce9d4a808 assets/refinedstorage/blockstates/green_relay.json\nc9bfb5d4002df591d9ac35054e719340799e7f52 assets/refinedstorage/blockstates/green_security_manager.json\n53d5e92bf89fdf857816ebc8af61763c5aca0fa1 assets/refinedstorage/blockstates/green_wireless_transmitter.json\nb3389b5e12d6bf8f1a4aab9281b5c3dee442da75 assets/refinedstorage/blockstates/grid.json\n47f2adbd7d2a25cd564556f44b028459306d17d9 assets/refinedstorage/blockstates/light_gray_controller.json\n9947ef84be868d3d911e386c09519db9eb5a87f5 assets/refinedstorage/blockstates/light_gray_crafter.json\n0f66d91089d5e55e652ce8b7aee06bb0710bf2c3 assets/refinedstorage/blockstates/light_gray_crafter_manager.json\n62f1453961eb0aa4bde17417a6d74759489c7db6 assets/refinedstorage/blockstates/light_gray_crafting_grid.json\n4f49c3a2ed3fb80739efaa40c590bacee28ccd18 assets/refinedstorage/blockstates/light_gray_crafting_monitor.json\n47f2adbd7d2a25cd564556f44b028459306d17d9 assets/refinedstorage/blockstates/light_gray_creative_controller.json\n29d62af6861ef704d341f156e2b8ba422d2bc815 assets/refinedstorage/blockstates/light_gray_detector.json\n6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/light_gray_disk_manipulator.json\n0b83619570c7fd6276e63db434ab586964001e49 assets/refinedstorage/blockstates/light_gray_fluid_grid.json\n58c51e122a1a6dc3ae49236e51b5ced8dd65f025 assets/refinedstorage/blockstates/light_gray_grid.json\n291eca6f29ecb96d444d2239296681f06863abc2 assets/refinedstorage/blockstates/light_gray_network_receiver.json\n7e9130f18c7c65a21040770b227062514cb64fe1 assets/refinedstorage/blockstates/light_gray_network_transmitter.json\n2f51485ac6f31c6fc7f2c4b40dd6512ed191f441 assets/refinedstorage/blockstates/light_gray_pattern_grid.json\n8d872d41d7c5d7938323ed7f1c0dfeb052e475d1 assets/refinedstorage/blockstates/light_gray_relay.json\n568c5af660f6e73cbed6a0d71c1e7cd104789f38 assets/refinedstorage/blockstates/light_gray_security_manager.json\ne04c8bfa9649765ff0faa30e8399786d56082006 assets/refinedstorage/blockstates/light_gray_wireless_transmitter.json\n9664192d13467956a09e888ca2842539beb097dd assets/refinedstorage/blockstates/lime_controller.json\n569b62896e4ae49fd7979d028950a7c908eade31 assets/refinedstorage/blockstates/lime_crafter.json\nf05e8def107036b057cfadd75cfc52f08da5978b assets/refinedstorage/blockstates/lime_crafter_manager.json\nb01d62bbba055517755be182585aec9972775111 assets/refinedstorage/blockstates/lime_crafting_grid.json\n1d5b0778259ae1c2f1ca523f8f1b6e6353935d51 assets/refinedstorage/blockstates/lime_crafting_monitor.json\n9664192d13467956a09e888ca2842539beb097dd assets/refinedstorage/blockstates/lime_creative_controller.json\nad9f60051001a52e0b10b12e37f6210b05e2cc8d assets/refinedstorage/blockstates/lime_detector.json\n6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/lime_disk_manipulator.json\n4521dfe3f69c6168e1d72fff247ee3a3d361ff0d assets/refinedstorage/blockstates/lime_fluid_grid.json\n6b5b6be70adbbc6eea356f00d7395dd2d181359c assets/refinedstorage/blockstates/lime_grid.json\nf1af8de9b654aac6c1e67ad5e6cd03ab7ad36b2d assets/refinedstorage/blockstates/lime_network_receiver.json\necd69149921b551c1dc18f6df43d703e83a68109 assets/refinedstorage/blockstates/lime_network_transmitter.json\nf0bbcee38acf700e7598ec2256dec30359f6dade assets/refinedstorage/blockstates/lime_pattern_grid.json\n50bcc8668c59ea7cc18307dc9a66710bb64a01a8 assets/refinedstorage/blockstates/lime_relay.json\n186f9f08d55c7eed41bdf20224a29c1da86116b1 assets/refinedstorage/blockstates/lime_security_manager.json\n31f6b78d9517e14f2eaee154b2bd016b8d122e99 assets/refinedstorage/blockstates/lime_wireless_transmitter.json\n260ee50fd5b48a884478722a48d1a30718011b71 assets/refinedstorage/blockstates/magenta_controller.json\na4fd0d98391e23b4fb5eeb263aa4b3a4a0e8463c assets/refinedstorage/blockstates/magenta_crafter.json\n334f9cd98067974c61d760b955499868cade5541 assets/refinedstorage/blockstates/magenta_crafter_manager.json\n6120e96957450ae3ddae9f45159144d6bd5eba88 assets/refinedstorage/blockstates/magenta_crafting_grid.json\nf37fd6d2cf884ea50df0e3498d4a1c79ab119643 assets/refinedstorage/blockstates/magenta_crafting_monitor.json\n260ee50fd5b48a884478722a48d1a30718011b71 assets/refinedstorage/blockstates/magenta_creative_controller.json\nbe4821c7ef7e2e092182daeae240ca64ac64109c assets/refinedstorage/blockstates/magenta_detector.json\n6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/magenta_disk_manipulator.json\n015ec2f4a5391216b726c6f3a04e207aef8eb73f assets/refinedstorage/blockstates/magenta_fluid_grid.json\n4df8d4e340437e044e274b93cbd3f530481b9a9c assets/refinedstorage/blockstates/magenta_grid.json\n52ba7a0be6c7745dcf6c8dce2ee714c3e435a6be assets/refinedstorage/blockstates/magenta_network_receiver.json\n10dd4186b77550077274cf71093f9ed5e669f6f7 assets/refinedstorage/blockstates/magenta_network_transmitter.json\n0cd180c166969d567fd19b20335b3a79c58a5b5a assets/refinedstorage/blockstates/magenta_pattern_grid.json\ncd0a58993fd70d4f45125bba65df310cf636e8b6 assets/refinedstorage/blockstates/magenta_relay.json\n97be2ff3849c198bb435104273d6242b2394ed26 assets/refinedstorage/blockstates/magenta_security_manager.json\n448d11572eb6e83a9c83bdc59a5db04b0bdf4055 assets/refinedstorage/blockstates/magenta_wireless_transmitter.json\nc02181173dfdc836b36270f2d53047e768bd4d65 assets/refinedstorage/blockstates/network_receiver.json\nd7ceb07865dd4532faa78a2292e35c6b47d5b5af assets/refinedstorage/blockstates/network_transmitter.json\n59cbfcaabd03f853aca3f60329a7c95cb787c8e6 assets/refinedstorage/blockstates/orange_controller.json\nc2e934d8f8332b9ef9f4860e0c5f5fc3e437fa9c assets/refinedstorage/blockstates/orange_crafter.json\n827f42cfab50b0dd2ed5b5d9f76094028c9be5b3 assets/refinedstorage/blockstates/orange_crafter_manager.json\nc770a2427a6474bdd86d98494c8685fca33ee741 assets/refinedstorage/blockstates/orange_crafting_grid.json\nc979c60e1dfc954dd55ec707707f0ff6e892c4de assets/refinedstorage/blockstates/orange_crafting_monitor.json\n59cbfcaabd03f853aca3f60329a7c95cb787c8e6 assets/refinedstorage/blockstates/orange_creative_controller.json\nc33a89682e5a55748c59b150cada12a9d1b9c55d assets/refinedstorage/blockstates/orange_detector.json\n6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/orange_disk_manipulator.json\nc32fe65c75f75ef6d2b2f6b88022d950403f4a69 assets/refinedstorage/blockstates/orange_fluid_grid.json\n2df3a077ef494d1296f566de4023d26569b31eee assets/refinedstorage/blockstates/orange_grid.json\n46f988c8980d2ef48ae7abd74c79dd5e7e017f8d assets/refinedstorage/blockstates/orange_network_receiver.json\n62ccc839c105f9668dc3c12f6ea696006fd2362d assets/refinedstorage/blockstates/orange_network_transmitter.json\n0433e6562309eb58a721431184c99a52842a5386 assets/refinedstorage/blockstates/orange_pattern_grid.json\n94b7f4ea5bfec14b016f8994659f37cc725f1481 assets/refinedstorage/blockstates/orange_relay.json\n52977b1a88ecd1065a83ada462b5a8a550abd549 assets/refinedstorage/blockstates/orange_security_manager.json\n93ad3d01bc10971f9e4f5c2d83f267fd458fb4b0 assets/refinedstorage/blockstates/orange_wireless_transmitter.json\n853d43993b0ff5412f8664107e4602f7c9108670 assets/refinedstorage/blockstates/pattern_grid.json\ne124d2cc9470854729e26e8bc95e82c8d12d66b3 assets/refinedstorage/blockstates/pink_controller.json\n72d722e540d986a161de430d090812cbb6bec108 assets/refinedstorage/blockstates/pink_crafter.json\nba83f5db4d49f98108667801a53b8dffd59bd984 assets/refinedstorage/blockstates/pink_crafter_manager.json\n8648689ae33328eaefbfcf5bd4c52b61afb38138 assets/refinedstorage/blockstates/pink_crafting_grid.json\n66584320c7486816c3fcf9b28ed7af70a146a235 assets/refinedstorage/blockstates/pink_crafting_monitor.json\ne124d2cc9470854729e26e8bc95e82c8d12d66b3 assets/refinedstorage/blockstates/pink_creative_controller.json\n69fd216404681bf23ad1c7c117e4f7976a355ad8 assets/refinedstorage/blockstates/pink_detector.json\n6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/pink_disk_manipulator.json\nb67fc2fcdb0a21fd36d258e53516cd9f876d4dfb assets/refinedstorage/blockstates/pink_fluid_grid.json\n73dbf1f3d783ebe6e191b4646b56cdab6b3f6e2e assets/refinedstorage/blockstates/pink_grid.json\n10e8d8a00049240ae65eeae04c95701f632245fc assets/refinedstorage/blockstates/pink_network_receiver.json\n3e808dbbcb61a670355520bed140d12952b74915 assets/refinedstorage/blockstates/pink_network_transmitter.json\n0bf4783a34fc70b08f825fc1884afeafaec1c2eb assets/refinedstorage/blockstates/pink_pattern_grid.json\nb408e8eb93f9bb1c384ab447af269e1d6291f359 assets/refinedstorage/blockstates/pink_relay.json\n3c5ce44160aa8718c9c703ee9088949b8c0592f0 assets/refinedstorage/blockstates/pink_security_manager.json\nc005a1b1d19d4d8a0bd5554ea0bdfc0215dcf22f assets/refinedstorage/blockstates/pink_wireless_transmitter.json\n49b1d9978995934a26559798c700dcc6f62f07ce assets/refinedstorage/blockstates/purple_controller.json\n17cf9e787325d128382838783327f03664c81700 assets/refinedstorage/blockstates/purple_crafter.json\n975ad7db8e483731a66f57cfb06f579fff2d2611 assets/refinedstorage/blockstates/purple_crafter_manager.json\n926110729d03c21d259ef4f44d43dc17e6e5c828 assets/refinedstorage/blockstates/purple_crafting_grid.json\n34180be7994fcb0700b90090cb2a73f18506e28c assets/refinedstorage/blockstates/purple_crafting_monitor.json\n49b1d9978995934a26559798c700dcc6f62f07ce assets/refinedstorage/blockstates/purple_creative_controller.json\n47fe9b00de7749597a2846508c2dc423ca53c943 assets/refinedstorage/blockstates/purple_detector.json\n6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/purple_disk_manipulator.json\nf7bad620df59f5fdc15bd7648e29ff56c58fdcb2 assets/refinedstorage/blockstates/purple_fluid_grid.json\n8dbb3d3793866969367ceb33c5d0fa2a57114f89 assets/refinedstorage/blockstates/purple_grid.json\nb5b0f4e65c5729b3d291b2a180eef162d6065368 assets/refinedstorage/blockstates/purple_network_receiver.json\nbc53f00fe156eb3e7fda7cc515c32c5e325a8574 assets/refinedstorage/blockstates/purple_network_transmitter.json\nfafd9a507ac856250fe79ebf77591aa48978517d assets/refinedstorage/blockstates/purple_pattern_grid.json\n42e4fdd1f5c123b3857c94cd27a376998f5f4c99 assets/refinedstorage/blockstates/purple_relay.json\nc70b3c0c23bd2f910a185d8c1704b10e4d7e7f55 assets/refinedstorage/blockstates/purple_security_manager.json\n6191786c1b4688b83ce872b46998e2769fe315a9 assets/refinedstorage/blockstates/purple_wireless_transmitter.json\n0af344822971927dbabc9a3248c4b065f57380da assets/refinedstorage/blockstates/red_controller.json\nd15483f33e14d52b696c148fc35074555ac34dc2 assets/refinedstorage/blockstates/red_crafter.json\n01bbcbd3539bae6de40adb47e0f718c77d12fe0e assets/refinedstorage/blockstates/red_crafter_manager.json\n9587b8ed2ad59cc4701de701117dae551bfa9f28 assets/refinedstorage/blockstates/red_crafting_grid.json\nccb731fe0e6f98f5ba987f1f628c0c643b43d2bc assets/refinedstorage/blockstates/red_crafting_monitor.json\n0af344822971927dbabc9a3248c4b065f57380da assets/refinedstorage/blockstates/red_creative_controller.json\n3535214510b28671e75e83091ed892a2ace93fe2 assets/refinedstorage/blockstates/red_detector.json\n6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/red_disk_manipulator.json\n2b0831c043a5db5801a83056db001bc9bea3e10d assets/refinedstorage/blockstates/red_fluid_grid.json\n08ea6c75ab709d59b644a9b6f851b30297709c37 assets/refinedstorage/blockstates/red_grid.json\n54c11f3818805a1f8c642fe9b39f8172cd0dbe9d assets/refinedstorage/blockstates/red_network_receiver.json\n306ea9c1b5e720034d4a64216a246f66ff378374 assets/refinedstorage/blockstates/red_network_transmitter.json\n0c146705612be3767b5580be6bdd2191da080f6d assets/refinedstorage/blockstates/red_pattern_grid.json\n7824d4a6b0a909bd130b3c9b03499d5303c00d48 assets/refinedstorage/blockstates/red_relay.json\n11a0de95d22a08e07cb7bccb5ee11b6998910aa8 assets/refinedstorage/blockstates/red_security_manager.json\n568aa0fb5ede635323c6fccdc4f07f4242a02eab assets/refinedstorage/blockstates/red_wireless_transmitter.json\nbe302ad36912be59948baac2e7ec7d458f7ba790 assets/refinedstorage/blockstates/relay.json\neca4522120aade2750f46407dd0c4f3a622481f9 assets/refinedstorage/blockstates/security_manager.json\n91dc10e68eccb57db9c8ba9c8740a586858d6b1d assets/refinedstorage/blockstates/white_controller.json\n5af23026e097081db875ac14160d957c84ffb683 assets/refinedstorage/blockstates/white_crafter.json\nc8db46d5b6688983ca6713252b618c8b854f6c48 assets/refinedstorage/blockstates/white_crafter_manager.json\n65d789e8e0c1b327477301f435bfd4f02e987379 assets/refinedstorage/blockstates/white_crafting_grid.json\n5e9fb377bcb1d89b7911e730121c575d42aee270 assets/refinedstorage/blockstates/white_crafting_monitor.json\n91dc10e68eccb57db9c8ba9c8740a586858d6b1d assets/refinedstorage/blockstates/white_creative_controller.json\n0841cf91a7f73f743fe3163044a10200cf1e1d2c assets/refinedstorage/blockstates/white_detector.json\n6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/white_disk_manipulator.json\n790778184e42c85287c157671786d4bddbb46859 assets/refinedstorage/blockstates/white_fluid_grid.json\nc1cc1d5d09eaa77e3e2063f5fc67c938ae73bc1e assets/refinedstorage/blockstates/white_grid.json\n6c0bd32d1ef222adf37252e798941269db9561d0 assets/refinedstorage/blockstates/white_network_receiver.json\nef79c48970c517a4466bca9c79a3f72ee94b2739 assets/refinedstorage/blockstates/white_network_transmitter.json\n9582df2542be982efafea176a8a95f8f4ee33ae7 assets/refinedstorage/blockstates/white_pattern_grid.json\n452c484028c224bbed3d37e630f87d9c47025557 assets/refinedstorage/blockstates/white_relay.json\n3959a8de59e67d553d87f85b02563d49fd7024ae assets/refinedstorage/blockstates/white_security_manager.json\nfdd7b224242f0c9d725fe4fe856359a19cde73e8 assets/refinedstorage/blockstates/white_wireless_transmitter.json\n1bb50b333ed68b51fb4068ad1a294a1721afe6fb assets/refinedstorage/blockstates/wireless_transmitter.json\n354e5098e85da4653b9f75a96f3bbae3b39cd4dc assets/refinedstorage/blockstates/yellow_controller.json\n7f5ef4baae9693d421b3b4eef67cfbb6fcb86efd assets/refinedstorage/blockstates/yellow_crafter.json\n1cb9354c8fc7094f9329fd21d0d6d8de6ebe70c2 assets/refinedstorage/blockstates/yellow_crafter_manager.json\n698d185106d288e3e7b5162298d1cdb2719ebad1 assets/refinedstorage/blockstates/yellow_crafting_grid.json\n893f864c644153a9883f6bedff779622057afd8d assets/refinedstorage/blockstates/yellow_crafting_monitor.json\n354e5098e85da4653b9f75a96f3bbae3b39cd4dc assets/refinedstorage/blockstates/yellow_creative_controller.json\n2ab0f370e0f93617df8f9244bd147d2ca03cb418 assets/refinedstorage/blockstates/yellow_detector.json\n6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/yellow_disk_manipulator.json\na53c34950d398e238e5e00f846ab7b9f5613b137 assets/refinedstorage/blockstates/yellow_fluid_grid.json\nf1a1ea426ae7caf8668631858f2943cdeba922c1 assets/refinedstorage/blockstates/yellow_grid.json\n3df04e5fd0be4f4bc3f590aa7b18cfc2e62a6970 assets/refinedstorage/blockstates/yellow_network_receiver.json\n9b04ef1034b8f0f53a331fca4a7a7f853b219f53 assets/refinedstorage/blockstates/yellow_network_transmitter.json\ncb0c6edbce8a2ce0255c8b3a3a9cd1cc8741a71a assets/refinedstorage/blockstates/yellow_pattern_grid.json\nfe89e69e7c6bf1e1863f8e9ee2fe3cacf27c3bf4 assets/refinedstorage/blockstates/yellow_relay.json\n3cce759ae50cb0c471c9e0173dc3d8beb18e7c5b assets/refinedstorage/blockstates/yellow_security_manager.json\n37ef58994e615ff1285ef554521dc1c5dc7f68aa assets/refinedstorage/blockstates/yellow_wireless_transmitter.json\n7dd4d790b7ab67ac05a5465e93a5df75f0a19a7f assets/refinedstorage/models/block/controller/black.json\n7ce5a4227982e3dbed579e8c9efe192ec3a46814 assets/refinedstorage/models/block/controller/blue.json\n35aa8942bfca9ebb5593b06192b1337298a91566 assets/refinedstorage/models/block/controller/brown.json\n4a7bc6807440bdacaf4a388001fff0af2178055d assets/refinedstorage/models/block/controller/cyan.json\n59f918515830678508a58682d629ade5c7f127a6 assets/refinedstorage/models/block/controller/gray.json\n533baa9de3602004178156576cc1c50b82970253 assets/refinedstorage/models/block/controller/green.json\n55ffca09db55f6ff3651df021853cb4c67971d4c assets/refinedstorage/models/block/controller/light_blue.json\n48afa16ef64605e47f8ef0718a04fe0ea4497be8 assets/refinedstorage/models/block/controller/light_gray.json\ne25236415255c8e84e8425cd5ef5068af2e90bf5 assets/refinedstorage/models/block/controller/lime.json\n719f9943433757fe6d544facfad02cf5c863b128 assets/refinedstorage/models/block/controller/magenta.json\nac1cb6e399a675e681a5c32be92cf2bbbabb845e assets/refinedstorage/models/block/controller/nearly_off.json\ndf5ef8ae2db4d693376007210753f08e8ed9aa1f assets/refinedstorage/models/block/controller/nearly_on.json\n649b3ac449fa858abcf8771bc91fe9ce04949989 assets/refinedstorage/models/block/controller/off.json\n197c8d6037075f2a32aa361a573a86a93b71d178 assets/refinedstorage/models/block/controller/orange.json\nb5d54a0751d165ea36f32a545cd0d74cfec96138 assets/refinedstorage/models/block/controller/pink.json\nf6f6681357c6759a6de3baac9116c45f4027ed0b assets/refinedstorage/models/block/controller/purple.json\nd940dae104b67d6bb4eaadfa5c196d174cea0dd9 assets/refinedstorage/models/block/controller/red.json\nc5377c73ba6e75dcfd191f1c28769bc380aa4447 assets/refinedstorage/models/block/controller/white.json\nd5b65da238fd3119c615a589bcab6c32b93a2838 assets/refinedstorage/models/block/controller/yellow.json\na3fc2ae7524e81e7ac41d116f23dfcfe58fcca9a assets/refinedstorage/models/block/crafter/black.json\nca9f47ac28aa1e6779613d426b837526b50ae0e2 assets/refinedstorage/models/block/crafter/blue.json\n58a500649c2d2a496f7228b9fa537802baf15a20 assets/refinedstorage/models/block/crafter/brown.json\ncce737a93507d1eb58d51d2ddac6428c695c6b23 assets/refinedstorage/models/block/crafter/cyan.json\n9a012e8377cf60c903a5d42918f3b2bde17539d2 assets/refinedstorage/models/block/crafter/disconnected.json\n7c6c30838702c3e43f7c9e62319d2cd486d1498a assets/refinedstorage/models/block/crafter/gray.json\nc495e9d2fc43e5e6094b4799609961445d391927 assets/refinedstorage/models/block/crafter/green.json\n8c493f345d1a6af778087a49cf36588954bb84fe assets/refinedstorage/models/block/crafter/light_blue.json\nce28ae9ae0553978724a134087ec1e836d1d7b84 assets/refinedstorage/models/block/crafter/light_gray.json\n6d79cebd8c01ae4fd0f13914a9a0f15ed91fd8f0 assets/refinedstorage/models/block/crafter/lime.json\n08d8c9040d77c717581b2ae3d485e0ffc5dd0d83 assets/refinedstorage/models/block/crafter/magenta.json\n6952bdf6763143f35b9d80a42e3cc354cc4da15d assets/refinedstorage/models/block/crafter/orange.json\ndd40faae420cdb526883f24a052992bf9b5c17a5 assets/refinedstorage/models/block/crafter/pink.json\n3bcb7dcb9b8a6c8d6425d788e794ce84a62a1f91 assets/refinedstorage/models/block/crafter/purple.json\nda30ebf53613bc7a7add1af2fd149f3497ad394a assets/refinedstorage/models/block/crafter/red.json\n6c4add52ccbfc051ed8deda52c3664c35a96cc36 assets/refinedstorage/models/block/crafter/white.json\nead08d7a0ba6b368d8c9afb2907f3495ebc0238f assets/refinedstorage/models/block/crafter/yellow.json\nc1ab462d97a36b71baa6d03b0aefab777377aa80 assets/refinedstorage/models/block/crafter_manager/black.json\n947d1cacb3f457c5f9985961bf9a2cb64392f9c6 assets/refinedstorage/models/block/crafter_manager/blue.json\nbdf1b91bb479fdc377250a925dd569c222b8b983 assets/refinedstorage/models/block/crafter_manager/brown.json\n41746225550b6f965c0bcb2168aef5afa6ac5780 assets/refinedstorage/models/block/crafter_manager/cyan.json\n006345975c1de5fb804ad47027d66730f13676d9 assets/refinedstorage/models/block/crafter_manager/disconnected.json\n7470d98e9ed8ab00a4cac8b651d095dbc33a787a assets/refinedstorage/models/block/crafter_manager/gray.json\na6b801087e0e0311fa660ae060879aede938bfa0 assets/refinedstorage/models/block/crafter_manager/green.json\ne6d7a1289f13a29a429db62287ac6c3143a9565a assets/refinedstorage/models/block/crafter_manager/light_blue.json\n77c0967108d7a410b69ebdc3d2b5606b653aca4f assets/refinedstorage/models/block/crafter_manager/light_gray.json\n341e45f850f25ba40d3af0ae3b269782c345db7e assets/refinedstorage/models/block/crafter_manager/lime.json\nec810637edf5e6cd5a52c21d7d01d76c0e12a5d0 assets/refinedstorage/models/block/crafter_manager/magenta.json\ne20e3f306648768835867ba976b0ba1f6ab7d48e assets/refinedstorage/models/block/crafter_manager/orange.json\na67381c44b22482008ab6f9b7474987764b838ea assets/refinedstorage/models/block/crafter_manager/pink.json\nc5b8ef34fd2b4c39efe5dfe3eff38f2631be9233 assets/refinedstorage/models/block/crafter_manager/purple.json\ncc006d4e8b49165ab3d3dc584f7e68415dffb36c assets/refinedstorage/models/block/crafter_manager/red.json\n6dbf08216a746ed970af93d43870cf9aff8e9398 assets/refinedstorage/models/block/crafter_manager/white.json\na65b6a6e90137b5b6d061637daca39cf0230a756 assets/refinedstorage/models/block/crafter_manager/yellow.json\n4f4c3f024920850c65a87faeac77dd3659915287 assets/refinedstorage/models/block/crafting_grid/black.json\nf1beacefdaf9aae0aaafc5a3c5e865e84173c2d4 assets/refinedstorage/models/block/crafting_grid/blue.json\n3f85170b187def3b075ec11982f91775c72ea2bb assets/refinedstorage/models/block/crafting_grid/brown.json\ne3a6ddbf8c7348f8f0678b7b88d7309c1c2048fb assets/refinedstorage/models/block/crafting_grid/cyan.json\n6cc5581bebc7eaa3b6ab156aec032534afa56b89 assets/refinedstorage/models/block/crafting_grid/disconnected.json\nc483c28bc8d003c214cd9d2c7de40500d9a14a5e assets/refinedstorage/models/block/crafting_grid/gray.json\n53c5036ea2fd4bc481bccdcd3f37f4b4a3c0e25f assets/refinedstorage/models/block/crafting_grid/green.json\n034ce68bb933818291cc7b28b6c5da5471c16f01 assets/refinedstorage/models/block/crafting_grid/light_blue.json\n40ff2912140c39bd37734b18941d595d6308aac8 assets/refinedstorage/models/block/crafting_grid/light_gray.json\nde80e07454eb9b8ad33af7a722d0fb0edc39ff56 assets/refinedstorage/models/block/crafting_grid/lime.json\n1e02f68733741502624b4726ed521063efa3373b assets/refinedstorage/models/block/crafting_grid/magenta.json\n60030a6c0d21492b10b027495cdec7d551592778 assets/refinedstorage/models/block/crafting_grid/orange.json\n35609d8acbf324629aa92ac49ae0f64f9126989b assets/refinedstorage/models/block/crafting_grid/pink.json\na43ebf377c637ae6a90699ef5895241645d75020 assets/refinedstorage/models/block/crafting_grid/purple.json\n8e685875e33fa52f88ddef1de0c370bbc1fc0717 assets/refinedstorage/models/block/crafting_grid/red.json\nbfb178e21d7b46750737a1451ea29d57456d1763 assets/refinedstorage/models/block/crafting_grid/white.json\na69aa2d1c9aa0c0670d60c0f88cfa07ebe8d258c assets/refinedstorage/models/block/crafting_grid/yellow.json\ne40a7af2d99a7ff0847a13865339fa00a3ebc439 assets/refinedstorage/models/block/crafting_monitor/black.json\n52a2c625eb84f7586bdb98d8f709ffb3c17e4ee9 assets/refinedstorage/models/block/crafting_monitor/blue.json\n9c8ceeee7c2dc1512e23d3798c51fa75387d411c assets/refinedstorage/models/block/crafting_monitor/brown.json\n1d071a43fa223ffd8261704132df37b8ee916a1d assets/refinedstorage/models/block/crafting_monitor/cyan.json\n8cc27a1d4bf9f12010581454f1d78aa1d982b3ac assets/refinedstorage/models/block/crafting_monitor/disconnected.json\n1e2f04d1521c27e31f06940684c1ca7306fa3524 assets/refinedstorage/models/block/crafting_monitor/gray.json\nddf85353932580ced34a09ce5cd5fc121828e90d assets/refinedstorage/models/block/crafting_monitor/green.json\na161a5fa71b287a0eb7ff801458ad5c76a55a7c5 assets/refinedstorage/models/block/crafting_monitor/light_blue.json\n8066136befa4b7e2d5cefdf9350f64b995051226 assets/refinedstorage/models/block/crafting_monitor/light_gray.json\n3671b90902d442e18c4fb13d3e50756d7532be8e assets/refinedstorage/models/block/crafting_monitor/lime.json\nd94ce990ec267a992686830fbcf10a43c23196cc assets/refinedstorage/models/block/crafting_monitor/magenta.json\ncf4753ad43dbf73db3696dd4c19849e6a2b9a33c assets/refinedstorage/models/block/crafting_monitor/orange.json\ncc142ac9d63ebe6bc9a8f94a39ac89d71565d569 assets/refinedstorage/models/block/crafting_monitor/pink.json\n5c0ff643784ef39a297f050e4bdff46ca2b1cce5 assets/refinedstorage/models/block/crafting_monitor/purple.json\nf1e3b6c58f99ac64ab48d2c735b8d675f9c74a0e assets/refinedstorage/models/block/crafting_monitor/red.json\n08fe3f165275166eee5557a0c6edfbd4035eae8b assets/refinedstorage/models/block/crafting_monitor/white.json\nb99b33fed141c1c979c4f68ac0e656ddacb7b041 assets/refinedstorage/models/block/crafting_monitor/yellow.json\n2b8f350a8b1fb249e9b835aab5969f4bd76a6ea7 assets/refinedstorage/models/block/detector/black.json\nc7298157a39315ff38d1310b4ebe77c708cf8a82 assets/refinedstorage/models/block/detector/blue.json\n298af9d65b3e2334de2519ef7e19c78756c1ab99 assets/refinedstorage/models/block/detector/brown.json\nd764ac8e477068bbb296c3854ad76a7b80d1d44a assets/refinedstorage/models/block/detector/cyan.json\n50d618e3cb55a96d67dcc9a6b42bd17c58e1870c assets/refinedstorage/models/block/detector/gray.json\n7845acde95c218ca098ec30a2e568b3334f09944 assets/refinedstorage/models/block/detector/green.json\nc735ce9091c7a5ab2eb0c7b162af77c2ffac2ad8 assets/refinedstorage/models/block/detector/light_blue.json\nb462ca74227c62a9e8567ab7461f45e5e95425d8 assets/refinedstorage/models/block/detector/light_gray.json\n4f52368581621adf1d799660c42f108207217575 assets/refinedstorage/models/block/detector/lime.json\n170d5328b3f1d9c05c2f6af3191a42d734e89e2b assets/refinedstorage/models/block/detector/magenta.json\nf50f9956dc7bdd3cac13a6473a45906050667a78 assets/refinedstorage/models/block/detector/off.json\n2c735eca8fcf7770558758a49f7f8ea469225897 assets/refinedstorage/models/block/detector/orange.json\nd795e18038baa420972781d7206c1809c7297ae8 assets/refinedstorage/models/block/detector/pink.json\n0fe0d9e192b473fdb4cc8a5844ca44de22364e43 assets/refinedstorage/models/block/detector/purple.json\nd07f6cedd294574ead99b3b024206c0126b26896 assets/refinedstorage/models/block/detector/red.json\na792d3daf2709048bf14ee378c7362b05c938bff assets/refinedstorage/models/block/detector/white.json\nbb3725144c25a75f4e0e0a47e7efd174b7211261 assets/refinedstorage/models/block/detector/yellow.json\n1785659b9e89cb0d4f027bc97e3a5812c8b1ccdb assets/refinedstorage/models/block/disk_manipulator/black.json\n08feb52f08c96567bbdc6cd0ab9f289748c3bd1c assets/refinedstorage/models/block/disk_manipulator/blue.json\n5050a32ef1afdb15f31f169d257596a29cf0e46d assets/refinedstorage/models/block/disk_manipulator/brown.json\n9900ae5b9004204fea75cad20e4b18a6d8d3ec37 assets/refinedstorage/models/block/disk_manipulator/cyan.json\n46b21908098b41f5a6a4229d941dd4732ef1dd76 assets/refinedstorage/models/block/disk_manipulator/disconnected.json\n8f78635bbb9015e9b3c710418adec9b96570b133 assets/refinedstorage/models/block/disk_manipulator/gray.json\n588bb56e49677311063aa0eee9ebbb864e528fc0 assets/refinedstorage/models/block/disk_manipulator/green.json\n46677b54fec1f540a8d63e8037bbf164f755b995 assets/refinedstorage/models/block/disk_manipulator/light_blue.json\n2dc951c9ebb27963eab8bd4e311da3e3f6ad99e9 assets/refinedstorage/models/block/disk_manipulator/light_gray.json\n08cf44fa79c6e90f420e3eeb2e02c52f875c06ff assets/refinedstorage/models/block/disk_manipulator/lime.json\n72d202c30b016055cecc9084d61e5bbadfa0a761 assets/refinedstorage/models/block/disk_manipulator/loader.json\nb4355a9e686dece664cd7a2129724823e0315abc assets/refinedstorage/models/block/disk_manipulator/magenta.json\n577215970d538ba411e951ee561c71edf4719876 assets/refinedstorage/models/block/disk_manipulator/orange.json\nb6a061ad8d84445979b2eddda4851ea7fe4557f2 assets/refinedstorage/models/block/disk_manipulator/pink.json\n4296e50c7de8c775143eb16d5e75c3804b0ee19c assets/refinedstorage/models/block/disk_manipulator/purple.json\n28244ffee47ac3ef6ccbd3228d7db8ffe8f8f00f assets/refinedstorage/models/block/disk_manipulator/red.json\nd7c7712fe9dc02e0bde2ed57f5e886698b5d1d65 assets/refinedstorage/models/block/disk_manipulator/white.json\n15c40e7373bff9f0a9e254aaf6d4aa9e3d2a1d53 assets/refinedstorage/models/block/disk_manipulator/yellow.json\n7af6b31d785047fff3d4716c81fbf550a38f292b assets/refinedstorage/models/block/fluid_grid/black.json\n2cc6db45ec512f617d3dfc74e56c812700e8c9be assets/refinedstorage/models/block/fluid_grid/blue.json\n043ee02c82d506d6f5024246fafdf467bcba50f4 assets/refinedstorage/models/block/fluid_grid/brown.json\n92c6f3c28c41f179c507434f9e13c41fb6713942 assets/refinedstorage/models/block/fluid_grid/cyan.json\n8715a94eb3b672cf941e471c5883cc9ddebff362 assets/refinedstorage/models/block/fluid_grid/disconnected.json\n328db8a51dac5c943b005dd8178f70de0e69b03d assets/refinedstorage/models/block/fluid_grid/gray.json\n3a012b462e69bdca95c5bb3e030d8dea2d438539 assets/refinedstorage/models/block/fluid_grid/green.json\n7f05d7725b608fdb70ba2ae4c6ade712912b5d30 assets/refinedstorage/models/block/fluid_grid/light_blue.json\n95d50b03de3385f617aa2d9641af547fbed68ae3 assets/refinedstorage/models/block/fluid_grid/light_gray.json\n536cd514850a06a78582bc93f44fb1fe81460ccc assets/refinedstorage/models/block/fluid_grid/lime.json\n511ea39721de8eaf9de4962eb0a953f460445c98 assets/refinedstorage/models/block/fluid_grid/magenta.json\n93073d28da8386afb465c093c7c9a805faa5e843 assets/refinedstorage/models/block/fluid_grid/orange.json\n34070d257c6e5fa057a914ace02db59fc4317c15 assets/refinedstorage/models/block/fluid_grid/pink.json\n2d400582419ad444bf5950deac5da692cb1ad9ae assets/refinedstorage/models/block/fluid_grid/purple.json\n6361903f6b6ff8f817e4511601b47990599f1edc assets/refinedstorage/models/block/fluid_grid/red.json\n6886951919ccfce485e851045fa23ff7deddf9be assets/refinedstorage/models/block/fluid_grid/white.json\n37e31039cba0204a03df2fa2130dc2383d303d29 assets/refinedstorage/models/block/fluid_grid/yellow.json\ne845c4a37c72d5ad426fac7203353a9665648a46 assets/refinedstorage/models/block/grid/black.json\n589f51309dbecb1964c070a70496b79ae1c4ebcb assets/refinedstorage/models/block/grid/blue.json\n437076a560cbafb39c685b88e6fd2073c7c158d0 assets/refinedstorage/models/block/grid/brown.json\n49f3eb8374ee309b81f9242bd048f66421eaa75e assets/refinedstorage/models/block/grid/cyan.json\n97d78c65ba856ead9ff344625e37ed4f6f880516 assets/refinedstorage/models/block/grid/disconnected.json\n3ad1130e18a706495810f1cc32e2658b4910607a assets/refinedstorage/models/block/grid/gray.json\n83b393342de4c5aee81c50715479ec78efb21667 assets/refinedstorage/models/block/grid/green.json\n3fb70b9aba3dbe38bc0279f1b2789695f8e0a784 assets/refinedstorage/models/block/grid/light_blue.json\n0ea1bb0f7196763e843c2bfe7b6a24356af72768 assets/refinedstorage/models/block/grid/light_gray.json\n0aa895ec1c87aa4d982f8ff244d7a9efa541183e assets/refinedstorage/models/block/grid/lime.json\n3fdd4ff86575596e397c27025b12b78475c6a0af assets/refinedstorage/models/block/grid/magenta.json\n700fdb55791027e838a317d60296ba99dcece579 assets/refinedstorage/models/block/grid/orange.json\n63797a1d7f8c29bf803200cd6e20565e4fe6e56e assets/refinedstorage/models/block/grid/pink.json\n1dab675f1583f789f2677c597bfd42cd1d310be1 assets/refinedstorage/models/block/grid/purple.json\n06a1e40dd45c7650699eead04d99397f745cd39b assets/refinedstorage/models/block/grid/red.json\n329229e786e1a6e0f36c547bd8f7e8e3adcd5f08 assets/refinedstorage/models/block/grid/white.json\nb6ad5c9d362ca9c4cbb5727be2a3ea38f03e0a64 assets/refinedstorage/models/block/grid/yellow.json\n79526257476cca709b95852c87d9e193ae645074 assets/refinedstorage/models/block/network_receiver/black.json\n521b606adc714ae111325cfb4b86c2f00fc49838 assets/refinedstorage/models/block/network_receiver/blue.json\ne988e5bf8a325e3ed5e80e5615e8d5b337e92892 assets/refinedstorage/models/block/network_receiver/brown.json\n9feb023af7e1f64c0586fcaa67059743deb3da04 assets/refinedstorage/models/block/network_receiver/cyan.json\n978191a2fcbf46cfd70fe9e4bfa564a3b1b89336 assets/refinedstorage/models/block/network_receiver/disconnected.json\n44587865547f9c2e58421ea0a880ff51cf8b8fbf assets/refinedstorage/models/block/network_receiver/gray.json\n180555a0b56ddbe2def2b86d44ad8d8747bffbea assets/refinedstorage/models/block/network_receiver/green.json\ncd3a8952d2246b8ae436f6b6b66ee7f7f3f51fa7 assets/refinedstorage/models/block/network_receiver/light_blue.json\n46a376a32289cef91d22fddc292ebff32ca4d2cb assets/refinedstorage/models/block/network_receiver/light_gray.json\n09a5924b295c3b1a3668cd9523c2bb9f46a320bc assets/refinedstorage/models/block/network_receiver/lime.json\n9233ffacf2b28e6feaa1b119996d4eb2cdfa1363 assets/refinedstorage/models/block/network_receiver/magenta.json\n16e69b8fee05153dc0664b24b88cf954c6b20fb6 assets/refinedstorage/models/block/network_receiver/orange.json\n2c0a43f2a69b4d78493d9af87b056f38b0c9b6b3 assets/refinedstorage/models/block/network_receiver/pink.json\n1ada9d35a3ed9942d5e50346f21dbcafc3b9199e assets/refinedstorage/models/block/network_receiver/purple.json\nacc750e5d48c10a4c638f0c86d3f721c75333606 assets/refinedstorage/models/block/network_receiver/red.json\n4067e93a775337668dbfb612b2d4fb411b43a6a9 assets/refinedstorage/models/block/network_receiver/white.json\n6d8e8c64a39485cba7b479337426f4f7319b8d77 assets/refinedstorage/models/block/network_receiver/yellow.json\nc17ae790076c791a6f51b86f307c71452a47e5b9 assets/refinedstorage/models/block/network_transmitter/black.json\nc4e1615846d83ab4c806b6b24373be722261d1f3 assets/refinedstorage/models/block/network_transmitter/blue.json\n0f59245da158e77b1cf84cfab5164eeb8814384d assets/refinedstorage/models/block/network_transmitter/brown.json\nd1dd664110221c97fe2d22a111800cd2b6df6982 assets/refinedstorage/models/block/network_transmitter/cyan.json\n7fad44f8c99b39fa763f603e3f30fa67abebd566 assets/refinedstorage/models/block/network_transmitter/disconnected.json\n8d516cc91c6e1bd3fb8e2eee31e268bf10b590df assets/refinedstorage/models/block/network_transmitter/gray.json\nce9afe78c7f30a826630135797ca4c90f7cccbb8 assets/refinedstorage/models/block/network_transmitter/green.json\n3a230a4a14c2151ac1de52072514b622a4fac746 assets/refinedstorage/models/block/network_transmitter/light_blue.json\n754dee3959694a095c12735306116793453d34d0 assets/refinedstorage/models/block/network_transmitter/light_gray.json\n363224b570a61889ec29ec9744a8d1a0d85ccb27 assets/refinedstorage/models/block/network_transmitter/lime.json\nfcce3c3813f180f8158038f90f20d49bee3e0f11 assets/refinedstorage/models/block/network_transmitter/magenta.json\nc1ece04fd664cf9748c06f945e9c20037d215346 assets/refinedstorage/models/block/network_transmitter/orange.json\n260f3dc7a7da3073e7ebd39e646f484a9a78c366 assets/refinedstorage/models/block/network_transmitter/pink.json\n137cb226c908a271b70748685a385b54e63d16ae assets/refinedstorage/models/block/network_transmitter/purple.json\nef2ca4a218be25d42a994a308d3a684f82aeb3e8 assets/refinedstorage/models/block/network_transmitter/red.json\n49ca8fa27667cfdd1d696d0deb56c376be3a8170 assets/refinedstorage/models/block/network_transmitter/white.json\n594e5350dd5d3d02769a7ba72f066545ec9d3ad8 assets/refinedstorage/models/block/network_transmitter/yellow.json\n92cbce2a0d88d653d3efa0ffb517b44dfe21fe33 assets/refinedstorage/models/block/pattern_grid/black.json\n09d8500c01a62a454e8e1a817a82e1ad19deace2 assets/refinedstorage/models/block/pattern_grid/blue.json\n50406c5a5a65c0d46e91ef389cd3fd23a2b2599b assets/refinedstorage/models/block/pattern_grid/brown.json\n6ce91be1821a684898a59d3a8cfbe13ba4f6b707 assets/refinedstorage/models/block/pattern_grid/cyan.json\n1dfe91631ef1f12dcecc7e0e45ec7f5e9aeb53f0 assets/refinedstorage/models/block/pattern_grid/disconnected.json\n3257be294252ab0a567fc96486e30b028ba6009d assets/refinedstorage/models/block/pattern_grid/gray.json\nb0713d7de5cd75e371bc83e9abd33e842702f1cc assets/refinedstorage/models/block/pattern_grid/green.json\n5412d15ff025c0ba4bf04e74cbecb765932cb697 assets/refinedstorage/models/block/pattern_grid/light_blue.json\n3abffd3cc264e735317ecb712b1db01f1d381c91 assets/refinedstorage/models/block/pattern_grid/light_gray.json\nfc8cf5e162ee8f030011f5e09a3fb5373c497e08 assets/refinedstorage/models/block/pattern_grid/lime.json\ne32a45b233d1786edb383080382a5025c6cb502c assets/refinedstorage/models/block/pattern_grid/magenta.json\n57e784c0b36a70aba86e137b541198934a3e8719 assets/refinedstorage/models/block/pattern_grid/orange.json\n58bc5125052ca7ce23db697ac29acea919e33ee7 assets/refinedstorage/models/block/pattern_grid/pink.json\n80126ef472a778e8aa64c20c7828aa033de4b3cf assets/refinedstorage/models/block/pattern_grid/purple.json\neee9128ba674f306ff5f6795468b07a1593f6431 assets/refinedstorage/models/block/pattern_grid/red.json\n0ea80f03eb7eca83ec65634635f0164bfa053524 assets/refinedstorage/models/block/pattern_grid/white.json\ne6b978a202ab3b7096443862fc70418fab92d528 assets/refinedstorage/models/block/pattern_grid/yellow.json\n35968a567e5abe3851f3833477c6b1ee8462d423 assets/refinedstorage/models/block/relay/black.json\n3918e0f6307e76c72f112b9e5a26977e4b32bb1a assets/refinedstorage/models/block/relay/blue.json\n2e79077645de1d34de0d3f01102d5242a577440d assets/refinedstorage/models/block/relay/brown.json\na683b28b4b41949b663208e28c393746419e5f1f assets/refinedstorage/models/block/relay/cyan.json\nb66ed29783c7a24a7112af3d58cfb903d14535bd assets/refinedstorage/models/block/relay/disconnected.json\n9705e6e41a83a5349f74e4478284f6fe8b63a6dd assets/refinedstorage/models/block/relay/gray.json\n2d21af4bfa0fade473addf82032db9e3187af096 assets/refinedstorage/models/block/relay/green.json\nf53061187c76cce0787d11c6b800745dfd48b36a assets/refinedstorage/models/block/relay/light_blue.json\na85088b47aaef37ebd03eaec92b3818f02de8463 assets/refinedstorage/models/block/relay/light_gray.json\n8502941d07ca9e6ac70c02b2e03b2a870c94e92f assets/refinedstorage/models/block/relay/lime.json\n81bff5b425404e1f01f6e4e815fce9eae20299cb assets/refinedstorage/models/block/relay/magenta.json\ne940a4ba52e06c3033c43a29fa092506fa3dd683 assets/refinedstorage/models/block/relay/orange.json\n9c48be51ec6d911626bebcdea25bbfe4171c02f1 assets/refinedstorage/models/block/relay/pink.json\n28844a3913a24f63b7d202e8b55a081ed3cf9301 assets/refinedstorage/models/block/relay/purple.json\nc3223281fef269d54225e938165d3ef4742673a0 assets/refinedstorage/models/block/relay/red.json\n9bd4c02a1e524d88b722a2b81ee49fa47beb9261 assets/refinedstorage/models/block/relay/white.json\nd6e52eb671800d61b5565e502f395f91c5b650a0 assets/refinedstorage/models/block/relay/yellow.json\n995ac6124cb9667fa89fb87eb8cf8485e7b7e197 assets/refinedstorage/models/block/security_manager/black.json\ne6dcfb1bfa2cd2ce4f3d3dc2aae7da3ad344bbda assets/refinedstorage/models/block/security_manager/blue.json\ncacca03ecf0de2bce557ca841401033c45cf4cc1 assets/refinedstorage/models/block/security_manager/brown.json\ne241938c7d93a4fc12a09fa9a1ee847d129e92b9 assets/refinedstorage/models/block/security_manager/cyan.json\nc47c799fca836d8d3ee2022acd5347c3e84836f1 assets/refinedstorage/models/block/security_manager/disconnected.json\n5fcb0264b7cc0d4132cf9f18deafa366c6066f53 assets/refinedstorage/models/block/security_manager/gray.json\n871b6c7a028d339a551e10d432a936e316f7910e assets/refinedstorage/models/block/security_manager/green.json\nf068112ed910080dfc74f2309228f2d5c41ea1b6 assets/refinedstorage/models/block/security_manager/light_blue.json\n2d7bf81078298c7cb9a9d0091fc219e7253c16d5 assets/refinedstorage/models/block/security_manager/light_gray.json\n7ca8fa49596d79f4d4eb61f34462cd8baad63221 assets/refinedstorage/models/block/security_manager/lime.json\n449ceab92dbc8b14edc8b0fe8fbd0648910c8a38 assets/refinedstorage/models/block/security_manager/magenta.json\n5b0a97090b976df2388119ffb8a8f5a4c5eae78d assets/refinedstorage/models/block/security_manager/orange.json\nda7ef346c5d9f2da82bfc0f15ba7cf8594bf9c40 assets/refinedstorage/models/block/security_manager/pink.json\n859171bc7c84c43ef6406b3749bf235011f4bc23 assets/refinedstorage/models/block/security_manager/purple.json\n04198d42366f1a9278466585994f388fc2d01fe9 assets/refinedstorage/models/block/security_manager/red.json\na865ead60de383ea8e84c5c16ffdcc2fcbd2791a assets/refinedstorage/models/block/security_manager/white.json\n291f61f7abfe33116b5a0c915d84160cb0db2fbb assets/refinedstorage/models/block/security_manager/yellow.json\n382ba985cb3eb98190df982cf81e85f1d00d0f98 assets/refinedstorage/models/block/wireless_transmitter/black.json\nf338756587a7c6bce14677030543f7399aee9259 assets/refinedstorage/models/block/wireless_transmitter/blue.json\n667bad1eaa409dbd56bb9db7048a029a610dc5c0 assets/refinedstorage/models/block/wireless_transmitter/brown.json\neeb75332e2a0a9a10b1f5d47b8621340c3913877 assets/refinedstorage/models/block/wireless_transmitter/cyan.json\n7d8cdce240042937a7a9ad14390f02f978e3b38f assets/refinedstorage/models/block/wireless_transmitter/disconnected.json\n732c1094b53f66b96e04630b2e3549f1ae3f3d3e assets/refinedstorage/models/block/wireless_transmitter/gray.json\n2cb3ccf208c6144c461f8b6d05e45360f88e31f1 assets/refinedstorage/models/block/wireless_transmitter/green.json\nf0c6cd01aa8af1558c43033433096942fdda103e assets/refinedstorage/models/block/wireless_transmitter/light_blue.json\nb1e599007cf64e1a4140a4180ea642c3e208d41c assets/refinedstorage/models/block/wireless_transmitter/light_gray.json\ne329e6a86f119589ba724bc4036922bce1f0e716 assets/refinedstorage/models/block/wireless_transmitter/lime.json\nefbe23834aaae087892464faccad675b344c35af assets/refinedstorage/models/block/wireless_transmitter/magenta.json\n578a2d53d7d7a800200525b04d91f356e3340014 assets/refinedstorage/models/block/wireless_transmitter/orange.json\nc2e51f822376d1968fc07e6987f70ff069d460d4 assets/refinedstorage/models/block/wireless_transmitter/pink.json\n495be998c5278225bebc0d6340640e7904e1f4cb assets/refinedstorage/models/block/wireless_transmitter/purple.json\n747ea39519e81abea94ca278f2e610e7c55d342e assets/refinedstorage/models/block/wireless_transmitter/red.json\nc6258775f847e0957a14fdfd24dcce3116d90acc assets/refinedstorage/models/block/wireless_transmitter/white.json\n556c8e5da522c6e27f8a6ee8de69fc95fafb504e assets/refinedstorage/models/block/wireless_transmitter/yellow.json\n0fb53d70880b97a55241dbb04f49b9ad39048920 assets/refinedstorage/models/item/black_controller.json\n942d718968e1b8d27b203bc661801d37d154b5f2 assets/refinedstorage/models/item/black_crafter.json\n75ac21fb6def11be4568d2ac5ff2651f3564f25d assets/refinedstorage/models/item/black_crafter_manager.json\n28891a28805f96c47409a34943342830a15e6690 assets/refinedstorage/models/item/black_crafting_grid.json\nddb0a90214bf85dc8e188068f73ae2b20f82150f assets/refinedstorage/models/item/black_crafting_monitor.json\n0fb53d70880b97a55241dbb04f49b9ad39048920 assets/refinedstorage/models/item/black_creative_controller.json\n241b9b206acf6f4c9ac3151c4044dac213bc0670 assets/refinedstorage/models/item/black_detector.json\nac9dc77f9d6ba5ee90101187aa09e406c0d14fbd assets/refinedstorage/models/item/black_disk_manipulator.json\n876fc7ec3dda3568c1fd1e8d2b6ceb200d1380ab assets/refinedstorage/models/item/black_fluid_grid.json\n17c651836f3308723635b7a7a1f9e879098b33c5 assets/refinedstorage/models/item/black_grid.json\nfac0c63adf0b1c802ebd5cdd9fc5c9dec030b35e assets/refinedstorage/models/item/black_network_receiver.json\nd823ba7bc1affa7af633185834d1ff582882f2e6 assets/refinedstorage/models/item/black_network_transmitter.json\n6c30fa933b83c1c01d2e069167729e91ed249ec7 assets/refinedstorage/models/item/black_pattern_grid.json\n61861f588ea12538786c06129c3d0a1040394f16 assets/refinedstorage/models/item/black_relay.json\nc634efc545854df54c57dd2bf61d6e03448742e6 assets/refinedstorage/models/item/black_security_manager.json\n6a1e27442bf1512ba949fafaf135502ae0420169 assets/refinedstorage/models/item/black_wireless_transmitter.json\n1df94eb9089e76129d911d793c26402ff9313880 assets/refinedstorage/models/item/blue_controller.json\n2de69e179294ad396ebe181228c3e9c1787ab550 assets/refinedstorage/models/item/blue_crafter.json\ncdea55152a48642717bdc630f74ee6fcf1d8f667 assets/refinedstorage/models/item/blue_crafter_manager.json\nc75d3ac7fb95df1b57ae997f5bf9ed7aad112eb0 assets/refinedstorage/models/item/blue_crafting_grid.json\n4fba5520838ccf9f88f51853ad95b9bd6c6c9b9c assets/refinedstorage/models/item/blue_crafting_monitor.json\n1df94eb9089e76129d911d793c26402ff9313880 assets/refinedstorage/models/item/blue_creative_controller.json\nf59b716bc576eed79556110ef355fa28cf92d10a assets/refinedstorage/models/item/blue_detector.json\n5f8275097f6478a4f23e1ce55dde36a5dc2e5407 assets/refinedstorage/models/item/blue_disk_manipulator.json\n675c756edd54900ab155bc45d5a7134cf6dac3a3 assets/refinedstorage/models/item/blue_fluid_grid.json\n99c3ceae65e98ca0eab0ab04c7739a872102bee0 assets/refinedstorage/models/item/blue_grid.json\n41c944af80509024d3de1ed1c5ab74336d3787e8 assets/refinedstorage/models/item/blue_network_receiver.json\n0af6f3152bc7fcd1ca79fd0adf77d1a52e098b6f assets/refinedstorage/models/item/blue_network_transmitter.json\n8053c22618e7d51150fab4172a1cb2e3c9d36b4c assets/refinedstorage/models/item/blue_pattern_grid.json\n763ebca22b3642be09f396deac9cd9c54b90e58f assets/refinedstorage/models/item/blue_relay.json\n5abbfde1e5a947ae44fde121c3294f9fb2b60e7d assets/refinedstorage/models/item/blue_security_manager.json\ne38c127e67a2ef649d7ed595577947c93473d3d2 assets/refinedstorage/models/item/blue_wireless_transmitter.json\nf27acd12556251b68e10d33d55cb90bcee40ab07 assets/refinedstorage/models/item/brown_controller.json\n0fb2cc9e3e05d19d9fcc5e04c6baeaa2cb04265c assets/refinedstorage/models/item/brown_crafter.json\n022322ce32ac742f4ce5498d3da128741fe0767d assets/refinedstorage/models/item/brown_crafter_manager.json\neb37e649bbb3f087df69a30c22215418b3fc901d assets/refinedstorage/models/item/brown_crafting_grid.json\n4556f504e89f87de6ab73c12259b73eb151e8d7a assets/refinedstorage/models/item/brown_crafting_monitor.json\nf27acd12556251b68e10d33d55cb90bcee40ab07 assets/refinedstorage/models/item/brown_creative_controller.json\n470afaeaaaec68a1474b2efcb2e027382b6d4069 assets/refinedstorage/models/item/brown_detector.json\n12c9098c38f118056d9576671287b9783e50be98 assets/refinedstorage/models/item/brown_disk_manipulator.json\n7fcf4b0092b4a6e733046548217f8cd40a0b0c01 assets/refinedstorage/models/item/brown_fluid_grid.json\n67016265a1d6961ef06211484795a61cc310e6b4 assets/refinedstorage/models/item/brown_grid.json\ndb89e452a0539344eafd946085a171bfd104a9cd assets/refinedstorage/models/item/brown_network_receiver.json\n293b7ae86745d49806b8cf07d9f7f3fb900129f8 assets/refinedstorage/models/item/brown_network_transmitter.json\na852eda91b130409a8127af77cf1a00b2aab81c8 assets/refinedstorage/models/item/brown_pattern_grid.json\n023fb3d3d0164e237d6d8c83028e66ffb080905f assets/refinedstorage/models/item/brown_relay.json\n45c70a18a9b27b3a0f7cd41a450ba23ba4b97faf assets/refinedstorage/models/item/brown_security_manager.json\n3c329581c36a66b21409184843a78e90eae25c50 assets/refinedstorage/models/item/brown_wireless_transmitter.json\n9af89e77d470eaf03b34847b568e0fcd0cfeb2ca assets/refinedstorage/models/item/controller.json\n712a2408676f6ce1208b196d0cfe065136d612fe assets/refinedstorage/models/item/crafter.json\n2adb1c2ed2c30890df2492069293f20c085eddf2 assets/refinedstorage/models/item/crafter_manager.json\n2ef1da280a960eafd61369b67ea1647966fdcc0c assets/refinedstorage/models/item/crafting_grid.json\nea61beccbf6896f3fdf99b8d4787be67573595dc assets/refinedstorage/models/item/crafting_monitor.json\n9af89e77d470eaf03b34847b568e0fcd0cfeb2ca assets/refinedstorage/models/item/creative_controller.json\nd3d25cbac485889dd6766253c3fb96a1827963a9 assets/refinedstorage/models/item/cyan_controller.json\n5b3089cc0257509445e335427fcee15a0c6d19e4 assets/refinedstorage/models/item/cyan_crafter.json\n734e1865d2b25eda65d72541f7db30b277d3cf73 assets/refinedstorage/models/item/cyan_crafter_manager.json\nc4fc9d67c903d107548d25237173d1df0dfad2ee assets/refinedstorage/models/item/cyan_crafting_grid.json\n133a84e4fd76123350bffc37cab6156ae6a0f61f assets/refinedstorage/models/item/cyan_crafting_monitor.json\nd3d25cbac485889dd6766253c3fb96a1827963a9 assets/refinedstorage/models/item/cyan_creative_controller.json\n3e224af44dddb95f804967974a776f3d39e14f79 assets/refinedstorage/models/item/cyan_detector.json\ndb51d1db8c2ef34f4ca03499081995031fc9bd75 assets/refinedstorage/models/item/cyan_disk_manipulator.json\n959e0627277816d1d5a0a529bee59631aa2cbd59 assets/refinedstorage/models/item/cyan_fluid_grid.json\n5e4dec30d4dffc887cd8e8b967ca0d43e5f53d18 assets/refinedstorage/models/item/cyan_grid.json\neb2db4269ca283c9665b9fa5e1235862af32b000 assets/refinedstorage/models/item/cyan_network_receiver.json\n6a5dfd3fc40fda27327da49c895775099d0406bb assets/refinedstorage/models/item/cyan_network_transmitter.json\nf404bf86051e76eb736827ecb9a7acbb78a86a0c assets/refinedstorage/models/item/cyan_pattern_grid.json\n2c6119b52833d26535d5c9c826f806b1a799745c assets/refinedstorage/models/item/cyan_relay.json\nc3bcb743cd9b551b8e3e07dd16a039ccce65167f assets/refinedstorage/models/item/cyan_security_manager.json\n9ab085f44867d2c6e6431914ee0b8d5b20f1f6ea assets/refinedstorage/models/item/cyan_wireless_transmitter.json\na14c5f121b112f80f018eb39e4017a044f5176c2 assets/refinedstorage/models/item/detector.json\nb864dd2a574cb0ff0f87373ba145b7e7c4b6a315 assets/refinedstorage/models/item/disk_manipulator.json\nb6f77a02dc8f84c8dc50af0e3ca8d4a2597894fb assets/refinedstorage/models/item/fluid_grid.json\n2793400d4b735f12ca00a38d89ce230de4882728 assets/refinedstorage/models/item/gray_controller.json\nf201a4dc689054fbf5afa4cd9318059b45e34fac assets/refinedstorage/models/item/gray_crafter.json\nd699ea44dc8ba183d453f865bb5dd816cae8a628 assets/refinedstorage/models/item/gray_crafter_manager.json\ne8beb5658c198903aa882e818e9f1a12fb219ed2 assets/refinedstorage/models/item/gray_crafting_grid.json\na24b4fb9353df1c8b9ba48ec7cda1402a0d18e06 assets/refinedstorage/models/item/gray_crafting_monitor.json\n2793400d4b735f12ca00a38d89ce230de4882728 assets/refinedstorage/models/item/gray_creative_controller.json\n3a62caa71a381e853fb8e1fd09e6eca16de95b8c assets/refinedstorage/models/item/gray_detector.json\n876cf3b8ad044945e93a2dcf595e5ee851a95801 assets/refinedstorage/models/item/gray_disk_manipulator.json\n4eb03c2834f4d92be29707d3a7e3412d2e5afae7 assets/refinedstorage/models/item/gray_fluid_grid.json\n1ba67cee521c3d178eae56d0ee44c13dc244ecc6 assets/refinedstorage/models/item/gray_grid.json\ndd9a85970dd5e0f4f7f0da196cda01b3f1156007 assets/refinedstorage/models/item/gray_network_receiver.json\nd549169a533feee23ee8f3e1b39b7c4bcf23b475 assets/refinedstorage/models/item/gray_network_transmitter.json\n558bee5f5c8415c73aae98e67851e9f192ab7157 assets/refinedstorage/models/item/gray_pattern_grid.json\n39bd74ec45ffe304d1e339d184b2164117d88b5f assets/refinedstorage/models/item/gray_relay.json\n9db80d9e795dbe5edff7a565671cf0095a7c4973 assets/refinedstorage/models/item/gray_security_manager.json\nbe60c25b51488e5a1f5db9aa0b8ce834b4f843b6 assets/refinedstorage/models/item/gray_wireless_transmitter.json\na6dccc5437fa6c15a9a032e7862c4c5653849dd8 assets/refinedstorage/models/item/green_controller.json\n36aec4f5a603dddd1817a815a612a4eb7190e222 assets/refinedstorage/models/item/green_crafter.json\n6fce1c029999c014a5d9bd0ac7b2b24838dc0cf6 assets/refinedstorage/models/item/green_crafter_manager.json\n3d835f157f4ace96a84a0e990276fe03fe1758c4 assets/refinedstorage/models/item/green_crafting_grid.json\ncbb61098395bda16b743c82f56529a00d91a708a assets/refinedstorage/models/item/green_crafting_monitor.json\na6dccc5437fa6c15a9a032e7862c4c5653849dd8 assets/refinedstorage/models/item/green_creative_controller.json\n7ec5ba813db5c1ae5663bebfa659b53c8e75096c assets/refinedstorage/models/item/green_detector.json\n7b0b74419933a23e3921672b49edc8830d1b3045 assets/refinedstorage/models/item/green_disk_manipulator.json\na8c70489b145ecafc07040195946c329ae30da41 assets/refinedstorage/models/item/green_fluid_grid.json\n5e5828f3f71c072a6b5aea5d219123eb392fb7b3 assets/refinedstorage/models/item/green_grid.json\na0b8687000680d8d8a55a7d6e21a6a5b8c3ba935 assets/refinedstorage/models/item/green_network_receiver.json\n9be69ecfb8d48aa8b7a1dfe97e428ab50b261864 assets/refinedstorage/models/item/green_network_transmitter.json\nffa8411a90dd0a79f72936c46b1514340c561fdc assets/refinedstorage/models/item/green_pattern_grid.json\nca9981a8b7c74fbdea91c12409b1c56929f829a2 assets/refinedstorage/models/item/green_relay.json\n29860d74f6f59ebabc4534eb3e437c50d82e6d75 assets/refinedstorage/models/item/green_security_manager.json\n0f626e543261b13e2d9021d09fc804236b9c9ca5 assets/refinedstorage/models/item/green_wireless_transmitter.json\n8e62b1170a93f317a3a0463eb2dc331bc6a29fc8 assets/refinedstorage/models/item/grid.json\ndbcc2e910fd5029dd5061fc018b0c21bee0aa0b0 assets/refinedstorage/models/item/light_gray_controller.json\n1280d243a5ee781a911776123a92280f6871e92b assets/refinedstorage/models/item/light_gray_crafter.json\n63d91aa91f0b04bc56661d77cba3802a028b14c3 assets/refinedstorage/models/item/light_gray_crafter_manager.json\n5447f9412ac89a2453495f7012906936556f3f97 assets/refinedstorage/models/item/light_gray_crafting_grid.json\n589f1eab82f17738f7c84408250051526612166c assets/refinedstorage/models/item/light_gray_crafting_monitor.json\ndbcc2e910fd5029dd5061fc018b0c21bee0aa0b0 assets/refinedstorage/models/item/light_gray_creative_controller.json\nc0fe9601a0b96cb28e05777646e8b1fa06dff11c assets/refinedstorage/models/item/light_gray_detector.json\na015d9065f13234987d35e242922e19a39cda358 assets/refinedstorage/models/item/light_gray_disk_manipulator.json\n792b2649c17462ffad43035187f9ae62faf2f741 assets/refinedstorage/models/item/light_gray_fluid_grid.json\n7a93c48e5851c4d45de5a6d138c16556faee7090 assets/refinedstorage/models/item/light_gray_grid.json\nd7492fb5ea426b156d29d90cac3c068a69257993 assets/refinedstorage/models/item/light_gray_network_receiver.json\n180ce6ef10d59c8495a35a00dd05ba68011f0238 assets/refinedstorage/models/item/light_gray_network_transmitter.json\n0574aa946a4db136d2141b599587b5e06b4cb5f4 assets/refinedstorage/models/item/light_gray_pattern_grid.json\n4b04ebd4de4cc44d66f69595a15e19c986bd89c5 assets/refinedstorage/models/item/light_gray_relay.json\n72c8be165eead23444e70fd27b214fbe4b4c8f5c assets/refinedstorage/models/item/light_gray_security_manager.json\ncf8a25b86388ed35135d6f7abc84c9db2f8c3147 assets/refinedstorage/models/item/light_gray_wireless_transmitter.json\n191c24b9824b3c218963d8ec68c79a25600cd04e assets/refinedstorage/models/item/lime_controller.json\nb5fe18a5faa8b19bca2356055bed26e3c4b7d6da assets/refinedstorage/models/item/lime_crafter.json\nc06a4c91f48f582ec7bbddf1992632496f628052 assets/refinedstorage/models/item/lime_crafter_manager.json\n5cd081548f10fccc38406afa4e62211a67068868 assets/refinedstorage/models/item/lime_crafting_grid.json\nd42a9b602a6b3e8ca87f44093bd5dbb8d025b83b assets/refinedstorage/models/item/lime_crafting_monitor.json\n191c24b9824b3c218963d8ec68c79a25600cd04e assets/refinedstorage/models/item/lime_creative_controller.json\nacc983f06040f4785c84fca542678df7bf93eba6 assets/refinedstorage/models/item/lime_detector.json\n19e1e36a546b3ec487a2a4356d85b0f0d72ad69d assets/refinedstorage/models/item/lime_disk_manipulator.json\n2d485286e0757a593ca7ce9cd37ce34ba036fc4f assets/refinedstorage/models/item/lime_fluid_grid.json\n16d5987ef2c508c6ce6c4b06d79d34ae5e43a985 assets/refinedstorage/models/item/lime_grid.json\n2bca4fdbc24291df49aed6c594df508b01b32a24 assets/refinedstorage/models/item/lime_network_receiver.json\na9be76a8a262a6a315f1227d33c8d7304b21f04a assets/refinedstorage/models/item/lime_network_transmitter.json\n9c3504533314ded4447251d7321f662e651587f7 assets/refinedstorage/models/item/lime_pattern_grid.json\n95676494b1360458129336fb1c89a827d9887d9a assets/refinedstorage/models/item/lime_relay.json\nc06aaadeb1e8573ee6a8f4d66c47a908df9df070 assets/refinedstorage/models/item/lime_security_manager.json\n4ac21895d402f5824f599daeae315330deeeb5cc assets/refinedstorage/models/item/lime_wireless_transmitter.json\ned8cd700afa7ce785453398f1739fa69b544306b assets/refinedstorage/models/item/magenta_controller.json\n7ae69165d5905f17a5e837de77d22941f3f22181 assets/refinedstorage/models/item/magenta_crafter.json\n97a0c41ddb54000647c33b56095215033b7f364a assets/refinedstorage/models/item/magenta_crafter_manager.json\nfea6df9eea90ca27131d5b9e37b08d50b1cb3618 assets/refinedstorage/models/item/magenta_crafting_grid.json\n3bf88ca8bbd2ebe7eba52cd6a90a81d4af0391b0 assets/refinedstorage/models/item/magenta_crafting_monitor.json\ned8cd700afa7ce785453398f1739fa69b544306b assets/refinedstorage/models/item/magenta_creative_controller.json\n5fdee8b4342e1b1b8e09a8ab300fcb9dbdcf8530 assets/refinedstorage/models/item/magenta_detector.json\n44ff4ad0e90b6b4bc72653d833e04e5352241304 assets/refinedstorage/models/item/magenta_disk_manipulator.json\n220ab0b014958d16917799de11a951e9ab8b207c assets/refinedstorage/models/item/magenta_fluid_grid.json\n8e3ea806407ae7ec6dd0619f8bdb2edf0c6fe0aa assets/refinedstorage/models/item/magenta_grid.json\n89da8c0449d5c16adbf793f08fa64e78ad320018 assets/refinedstorage/models/item/magenta_network_receiver.json\n6228fdb00897e8e25454017336570fe15410ee4c assets/refinedstorage/models/item/magenta_network_transmitter.json\n1aeb5a567564f664893434a89d95c640006c3d0e assets/refinedstorage/models/item/magenta_pattern_grid.json\n7cde3959bc32026f58cdc12755d1c9ecedb74f51 assets/refinedstorage/models/item/magenta_relay.json\nd7bcf381a5d9689d554438184f0fec0012f65f05 assets/refinedstorage/models/item/magenta_security_manager.json\n833c0a8c3e209c604cad8146468143470693f42a assets/refinedstorage/models/item/magenta_wireless_transmitter.json\n6dbbe55fd346aaa8eec23b2808ffd18d5840d832 assets/refinedstorage/models/item/network_receiver.json\n54f8841b6832f05b8e5076cfb5a714ef66c4b159 assets/refinedstorage/models/item/network_transmitter.json\n62a9e346d5e83e3b4c1c947d7ef5316d93b168a6 assets/refinedstorage/models/item/orange_controller.json\n2a934a32a43fd58110eebc7b3e4b05f71c21b76c assets/refinedstorage/models/item/orange_crafter.json\n3e7fbb114a1270c3e2cf2d79f043c62e869de2dc assets/refinedstorage/models/item/orange_crafter_manager.json\n4f35a7cc88dff4dc4ee066261024f14f123f8227 assets/refinedstorage/models/item/orange_crafting_grid.json\n0c7188e1968be58e1797720861a5d104f7dae2a4 assets/refinedstorage/models/item/orange_crafting_monitor.json\n62a9e346d5e83e3b4c1c947d7ef5316d93b168a6 assets/refinedstorage/models/item/orange_creative_controller.json\n833cc370275e91e9088bba3505b52e9199beafca assets/refinedstorage/models/item/orange_detector.json\ncc94b04311c3c1089dc1e488464540f5ef04b448 assets/refinedstorage/models/item/orange_disk_manipulator.json\n846a0e2b574b4518a392916902564fc692b72994 assets/refinedstorage/models/item/orange_fluid_grid.json\n862b3b4e3b1eaddb034cb8b4384c1cf7374a0778 assets/refinedstorage/models/item/orange_grid.json\n7d58c259c555a33cad472a3edfc3bd33f4160c66 assets/refinedstorage/models/item/orange_network_receiver.json\n0e1f7e25ce5bbc1369116550f3f7c095cff3df12 assets/refinedstorage/models/item/orange_network_transmitter.json\ncae021973ae73db4f26907bc20af071b4788a7d1 assets/refinedstorage/models/item/orange_pattern_grid.json\n8dab67d1e96096cdc41c4b62dcabfd81019b518c assets/refinedstorage/models/item/orange_relay.json\nfc333d59e066c62ef6bad598dfaadcc030655f23 assets/refinedstorage/models/item/orange_security_manager.json\n27557f3fd10361a51c867fe8211073807576f040 assets/refinedstorage/models/item/orange_wireless_transmitter.json\n4368418d5b92cbaa041d20e6f25d06ab3f24fd6f assets/refinedstorage/models/item/pattern_grid.json\n0514638803a2e3805e5078001fb4f53ceb7d1a41 assets/refinedstorage/models/item/pink_controller.json\n3b472cd0ed96b6eb64c7695429cc7a76e629f1a6 assets/refinedstorage/models/item/pink_crafter.json\n03a29baf74da2cbf3d7ee5ae8d9925d19c34e8f3 assets/refinedstorage/models/item/pink_crafter_manager.json\ne0710739ed2c8c74147585c990fe62d9fdb18ab0 assets/refinedstorage/models/item/pink_crafting_grid.json\n71045a36761dca453325aced8d84cff206c81817 assets/refinedstorage/models/item/pink_crafting_monitor.json\n0514638803a2e3805e5078001fb4f53ceb7d1a41 assets/refinedstorage/models/item/pink_creative_controller.json\n6c67a4fc7796172f625c4862cf616c86bf8cba79 assets/refinedstorage/models/item/pink_detector.json\n75c748b9473e195554615573406e1571b5ccac10 assets/refinedstorage/models/item/pink_disk_manipulator.json\nc3b2796d126d95f9141472a0c0009d88bd7cb855 assets/refinedstorage/models/item/pink_fluid_grid.json\n9af67ec1885b0215227dcd252606a5893eb04302 assets/refinedstorage/models/item/pink_grid.json\nb376b5e220c3ae55cf3ecfb69495d57b554f9223 assets/refinedstorage/models/item/pink_network_receiver.json\nba12ed9891fa73b2336ff93ab4bfd0d3b1492652 assets/refinedstorage/models/item/pink_network_transmitter.json\n869f05efe6e5d262b6094b68913c99472c11895d assets/refinedstorage/models/item/pink_pattern_grid.json\n6d6d9cd242688e2891cd6fc8c74eb19dcf36ac19 assets/refinedstorage/models/item/pink_relay.json\nfe2fc6e128f619dddc5d9f04486264a245c2b457 assets/refinedstorage/models/item/pink_security_manager.json\n332f608a7dc84019b8b0fa2a5e44ad9f78e430de assets/refinedstorage/models/item/pink_wireless_transmitter.json\n0f11e9205719c6fe582e96bd4205ac7c93bfd209 assets/refinedstorage/models/item/purple_controller.json\n506b89f03df977db6eb43c09d39b8aa8d7fcc28a assets/refinedstorage/models/item/purple_crafter.json\nb3b6be54491ba314822a6b47b20a55955b81a986 assets/refinedstorage/models/item/purple_crafter_manager.json\n413fffa72205e3c3f50106162bf88e8d18cad8ab assets/refinedstorage/models/item/purple_crafting_grid.json\nac159f10aab33c9e95009384d994a46caf4e9c5b assets/refinedstorage/models/item/purple_crafting_monitor.json\n0f11e9205719c6fe582e96bd4205ac7c93bfd209 assets/refinedstorage/models/item/purple_creative_controller.json\na137fc45d5f9b891ef00d75a2855258a88177668 assets/refinedstorage/models/item/purple_detector.json\n525576087501ad8483619e8339a614951eada2b6 assets/refinedstorage/models/item/purple_disk_manipulator.json\n80fb0c7bc38471d990c1623918a96db182bbe93b assets/refinedstorage/models/item/purple_fluid_grid.json\n87e4943c1c019cac11083c479a4c5f563051ddd2 assets/refinedstorage/models/item/purple_grid.json\nf319ca93c15a56a7927d022c123608dfb1a91f21 assets/refinedstorage/models/item/purple_network_receiver.json\n46eb95a94c5d12503bcfbcdaf849a03a176974b9 assets/refinedstorage/models/item/purple_network_transmitter.json\nc5a01a9ddace2e421e32b12c83d7a0b384be75fa assets/refinedstorage/models/item/purple_pattern_grid.json\ne2efaf0e99c7dc1125b32370201be809a67c25d9 assets/refinedstorage/models/item/purple_relay.json\n3c3ed303d605e0e9345940fc1756e2ecd1c48287 assets/refinedstorage/models/item/purple_security_manager.json\nef7d480ea1f08c1a2a7c2aebcbe3ca751df9f9b6 assets/refinedstorage/models/item/purple_wireless_transmitter.json\n004e6cf370c1b7ad3d243a358494bb1af2fdee8d assets/refinedstorage/models/item/red_controller.json\n6804c531235f5c7cd13f0c734a30aa58855c66d8 assets/refinedstorage/models/item/red_crafter.json\nf2804c202120637bff89dd8b2ab8e43ba1f5aafc assets/refinedstorage/models/item/red_crafter_manager.json\nacddcd41152a23916905fd85ad62081f5cb8c90c assets/refinedstorage/models/item/red_crafting_grid.json\n5a93d02b15f7ef2d9803ef0d004930ed1766707b assets/refinedstorage/models/item/red_crafting_monitor.json\n004e6cf370c1b7ad3d243a358494bb1af2fdee8d assets/refinedstorage/models/item/red_creative_controller.json\n4c1c2a7322dada203e2521225d80c5b516cacb62 assets/refinedstorage/models/item/red_detector.json\n262bdaf7a4a2a587dc88e3fb5c72c22e16829998 assets/refinedstorage/models/item/red_disk_manipulator.json\n67e092b9a6df25cb4396d3ae4464dd3c009c60b2 assets/refinedstorage/models/item/red_fluid_grid.json\nbeb09fb2b90d4a5d0e2debb2b496f7cc5e1906af assets/refinedstorage/models/item/red_grid.json\nc2f491455989b852e1c40a2e2003aeb482b5a628 assets/refinedstorage/models/item/red_network_receiver.json\nd2127558a02a6cb0a6c58a1feb8a4b9eb251d544 assets/refinedstorage/models/item/red_network_transmitter.json\n591164ab827c9f7fd0cfa0f7e7b42c94f801fac6 assets/refinedstorage/models/item/red_pattern_grid.json\n4eaa387e037be30d51852c185d80ee1eea03559f assets/refinedstorage/models/item/red_relay.json\n37b2c3f4b626765fb97a1aada4c0cc5b60ffac67 assets/refinedstorage/models/item/red_security_manager.json\n05e22d0e5fafbbe8c6864c896a05907b1808c4cf assets/refinedstorage/models/item/red_wireless_transmitter.json\n58e008aea088a9e1903885a2bc6e14d9f0b2c333 assets/refinedstorage/models/item/relay.json\ne0546ec6993e456e7ef61a35cccc862382b15fd5 assets/refinedstorage/models/item/security_manager.json\n9b37576964ccce28c9396299400a78a0a9d9ee04 assets/refinedstorage/models/item/white_controller.json\nc6e5a16319d0fad19ac8ede0108b658cd4028146 assets/refinedstorage/models/item/white_crafter.json\ne6194df137b2c614d6402d6dc672beae80430d38 assets/refinedstorage/models/item/white_crafter_manager.json\n399926c00694fa7abefd1709cc3da37d7eb0c5af assets/refinedstorage/models/item/white_crafting_grid.json\necff06abfe1465fb6630f027f9253965ceb2ed60 assets/refinedstorage/models/item/white_crafting_monitor.json\n9b37576964ccce28c9396299400a78a0a9d9ee04 assets/refinedstorage/models/item/white_creative_controller.json\n5f1ae8346d30d2e4f6b5aed97504d35ec05eecfe assets/refinedstorage/models/item/white_detector.json\n0eec3932d36ed9e265a48b90fc1ae83bb95a3aa3 assets/refinedstorage/models/item/white_disk_manipulator.json\nca0c7707acf771758db0194f30f1247d4721ae50 assets/refinedstorage/models/item/white_fluid_grid.json\n42e10b1a94e013425fc1ff146d9cdc07c4b242b4 assets/refinedstorage/models/item/white_grid.json\n39d06d08ba1e35d8322386345828d14eb16ac0d8 assets/refinedstorage/models/item/white_network_receiver.json\n4c147f69e564648441aaeecee3c2fc132501fc05 assets/refinedstorage/models/item/white_network_transmitter.json\n6a4add44bd9ff08a7d30fc79d38c45f9f9aa55da assets/refinedstorage/models/item/white_pattern_grid.json\n8fc4acd3d401ce6496db2af111ab2b97716349bf assets/refinedstorage/models/item/white_relay.json\n42c146254c8c634eb9f79f29b909535b0504d6a5 assets/refinedstorage/models/item/white_security_manager.json\ndffc5e13406d4370d1cc3fcc69c7556029406e98 assets/refinedstorage/models/item/white_wireless_transmitter.json\n08797906f5356ea0ccc061347d188bab0c63c02d assets/refinedstorage/models/item/wireless_transmitter.json\n2fca7b8b45c98bc01de598dd53f0f80f2e547dd4 assets/refinedstorage/models/item/yellow_controller.json\n1bf5a3d8d72edcd34ddf8266caaac89717a02ecb assets/refinedstorage/models/item/yellow_crafter.json\n6b33ac9d2c729a4ea8dd42efb8feeb553a434d70 assets/refinedstorage/models/item/yellow_crafter_manager.json\nb628289d264ed316cd2d88c297fb8712f8bbffd2 assets/refinedstorage/models/item/yellow_crafting_grid.json\n496e7503c51cf826e718301641235d07ddb24de7 assets/refinedstorage/models/item/yellow_crafting_monitor.json\n2fca7b8b45c98bc01de598dd53f0f80f2e547dd4 assets/refinedstorage/models/item/yellow_creative_controller.json\n04e4c31f56373507a46da2deccc4890305fe671e assets/refinedstorage/models/item/yellow_detector.json\n6412b4000a8034e4b5e019b9a6d9c32085cda263 assets/refinedstorage/models/item/yellow_disk_manipulator.json\n5b6b9685ed940cdfcede5c4df4b6836fbd748895 assets/refinedstorage/models/item/yellow_fluid_grid.json\nbf3386182b6e8b29a9e4e8f72eaeec17169a39e5 assets/refinedstorage/models/item/yellow_grid.json\ne0283cdc201bd14bf272859692be8f71c0f9cbeb assets/refinedstorage/models/item/yellow_network_receiver.json\n29a2c43527626231f73d53badc08a9f6f11f7615 assets/refinedstorage/models/item/yellow_network_transmitter.json\nb9bfe30d83136faf826f2391fb7a3ed3742ae22e assets/refinedstorage/models/item/yellow_pattern_grid.json\nbd7660f94971400544ee3ea14876efab3f493b96 assets/refinedstorage/models/item/yellow_relay.json\nfc534d01e53b660bf69498968487d1dae1b6de02 assets/refinedstorage/models/item/yellow_security_manager.json\ne6c24f334bd8249c5c629b86fc761d92d9f901e5 assets/refinedstorage/models/item/yellow_wireless_transmitter.json\n"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/black_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/black\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/black_crafter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\"\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/black\",\n      \"x\": 180\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/black\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/black\",\n      \"x\": 90\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/black\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/black\"\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/black\",\n      \"x\": 90,\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/black_crafter_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/black\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/black\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/black\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/black\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/black_crafting_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/black\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/black\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/black\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/black\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/black_crafting_monitor.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/black\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/black\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/black\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/black\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/black_creative_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/black\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/black_detector.json",
    "content": "{\n  \"variants\": {\n    \"powered=false\": {\n      \"model\": \"refinedstorage:block/detector/off\"\n    },\n    \"powered=true\": {\n      \"model\": \"refinedstorage:block/detector/black\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/black_disk_manipulator.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/disk_manipulator/loader\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/black_fluid_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/black\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/black\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/black\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/black\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/black_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/black\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/black\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/black\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/black\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/black_network_receiver.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_receiver/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_receiver/black\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/black_network_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_transmitter/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_transmitter/black\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/black_pattern_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/black\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/black\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/black\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/black\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/black_relay.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/relay/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/relay/black\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/black_security_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/black\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/black\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/black\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/black\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/black_wireless_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\"\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/black\"\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/black\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/black\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/black\",\n      \"x\": 90\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/black\",\n      \"x\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/black\",\n      \"x\": 90,\n      \"y\": 90\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/blue_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/blue\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/blue_crafter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\"\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/blue\",\n      \"x\": 180\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/blue\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/blue\",\n      \"x\": 90\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/blue\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/blue\"\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/blue\",\n      \"x\": 90,\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/blue_crafter_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/blue\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/blue\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/blue\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/blue\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/blue_crafting_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/blue\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/blue\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/blue\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/blue\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/blue_crafting_monitor.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/blue\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/blue\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/blue\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/blue\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/blue_creative_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/blue\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/blue_detector.json",
    "content": "{\n  \"variants\": {\n    \"powered=false\": {\n      \"model\": \"refinedstorage:block/detector/off\"\n    },\n    \"powered=true\": {\n      \"model\": \"refinedstorage:block/detector/blue\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/blue_disk_manipulator.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/disk_manipulator/loader\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/blue_fluid_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/blue\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/blue\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/blue\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/blue\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/blue_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/blue\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/blue\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/blue\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/blue\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/blue_network_receiver.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_receiver/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_receiver/blue\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/blue_network_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_transmitter/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_transmitter/blue\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/blue_pattern_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/blue\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/blue\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/blue\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/blue\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/blue_relay.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/relay/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/relay/blue\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/blue_security_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/blue\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/blue\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/blue\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/blue\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/blue_wireless_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\"\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/blue\"\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/blue\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/blue\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/blue\",\n      \"x\": 90\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/blue\",\n      \"x\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/blue\",\n      \"x\": 90,\n      \"y\": 90\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/brown_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/brown\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/brown_crafter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\"\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/brown\",\n      \"x\": 180\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/brown\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/brown\",\n      \"x\": 90\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/brown\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/brown\"\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/brown\",\n      \"x\": 90,\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/brown_crafter_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/brown\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/brown\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/brown\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/brown\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/brown_crafting_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/brown\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/brown\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/brown\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/brown\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/brown_crafting_monitor.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/brown\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/brown\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/brown\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/brown\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/brown_creative_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/brown\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/brown_detector.json",
    "content": "{\n  \"variants\": {\n    \"powered=false\": {\n      \"model\": \"refinedstorage:block/detector/off\"\n    },\n    \"powered=true\": {\n      \"model\": \"refinedstorage:block/detector/brown\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/brown_disk_manipulator.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/disk_manipulator/loader\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/brown_fluid_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/brown\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/brown\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/brown\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/brown\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/brown_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/brown\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/brown\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/brown\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/brown\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/brown_network_receiver.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_receiver/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_receiver/brown\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/brown_network_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_transmitter/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_transmitter/brown\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/brown_pattern_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/brown\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/brown\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/brown\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/brown\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/brown_relay.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/relay/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/relay/brown\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/brown_security_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/brown\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/brown\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/brown\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/brown\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/brown_wireless_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\"\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/brown\"\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/brown\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/brown\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/brown\",\n      \"x\": 90\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/brown\",\n      \"x\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/brown\",\n      \"x\": 90,\n      \"y\": 90\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/light_blue\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/crafter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\"\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/light_blue\",\n      \"x\": 180\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/light_blue\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/light_blue\",\n      \"x\": 90\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/light_blue\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/light_blue\"\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/light_blue\",\n      \"x\": 90,\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/crafter_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/light_blue\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/light_blue\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/light_blue\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/light_blue\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/crafting_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/light_blue\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/light_blue\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/light_blue\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/light_blue\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/crafting_monitor.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/light_blue\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/light_blue\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/light_blue\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/light_blue\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/creative_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/light_blue\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/cyan_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/cyan\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/cyan_crafter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\"\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/cyan\",\n      \"x\": 180\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/cyan\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/cyan\",\n      \"x\": 90\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/cyan\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/cyan\"\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/cyan\",\n      \"x\": 90,\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/cyan_crafter_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/cyan\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/cyan\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/cyan\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/cyan\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/cyan_crafting_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/cyan\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/cyan\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/cyan\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/cyan\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/cyan_crafting_monitor.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/cyan\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/cyan\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/cyan\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/cyan\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/cyan_creative_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/cyan\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/cyan_detector.json",
    "content": "{\n  \"variants\": {\n    \"powered=false\": {\n      \"model\": \"refinedstorage:block/detector/off\"\n    },\n    \"powered=true\": {\n      \"model\": \"refinedstorage:block/detector/cyan\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/cyan_disk_manipulator.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/disk_manipulator/loader\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/cyan_fluid_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/cyan\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/cyan\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/cyan\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/cyan\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/cyan_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/cyan\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/cyan\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/cyan\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/cyan\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/cyan_network_receiver.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_receiver/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_receiver/cyan\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/cyan_network_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_transmitter/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_transmitter/cyan\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/cyan_pattern_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/cyan\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/cyan\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/cyan\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/cyan\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/cyan_relay.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/relay/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/relay/cyan\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/cyan_security_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/cyan\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/cyan\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/cyan\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/cyan\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/cyan_wireless_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\"\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/cyan\"\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/cyan\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/cyan\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/cyan\",\n      \"x\": 90\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/cyan\",\n      \"x\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/cyan\",\n      \"x\": 90,\n      \"y\": 90\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/detector.json",
    "content": "{\n  \"variants\": {\n    \"powered=false\": {\n      \"model\": \"refinedstorage:block/detector/off\"\n    },\n    \"powered=true\": {\n      \"model\": \"refinedstorage:block/detector/light_blue\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/disk_manipulator.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/disk_manipulator/loader\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/fluid_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/light_blue\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/light_blue\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/light_blue\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/light_blue\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/gray_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/gray\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/gray_crafter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\"\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/gray\",\n      \"x\": 180\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/gray\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/gray\",\n      \"x\": 90\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/gray\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/gray\"\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/gray\",\n      \"x\": 90,\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/gray_crafter_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/gray\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/gray\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/gray\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/gray\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/gray_crafting_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/gray\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/gray\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/gray\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/gray\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/gray_crafting_monitor.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/gray\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/gray\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/gray\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/gray\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/gray_creative_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/gray\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/gray_detector.json",
    "content": "{\n  \"variants\": {\n    \"powered=false\": {\n      \"model\": \"refinedstorage:block/detector/off\"\n    },\n    \"powered=true\": {\n      \"model\": \"refinedstorage:block/detector/gray\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/gray_disk_manipulator.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/disk_manipulator/loader\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/gray_fluid_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/gray\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/gray\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/gray\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/gray\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/gray_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/gray\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/gray\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/gray\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/gray\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/gray_network_receiver.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_receiver/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_receiver/gray\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/gray_network_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_transmitter/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_transmitter/gray\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/gray_pattern_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/gray\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/gray\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/gray\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/gray\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/gray_relay.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/relay/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/relay/gray\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/gray_security_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/gray\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/gray\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/gray\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/gray\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/gray_wireless_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\"\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/gray\"\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/gray\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/gray\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/gray\",\n      \"x\": 90\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/gray\",\n      \"x\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/gray\",\n      \"x\": 90,\n      \"y\": 90\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/green_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/green\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/green_crafter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\"\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/green\",\n      \"x\": 180\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/green\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/green\",\n      \"x\": 90\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/green\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/green\"\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/green\",\n      \"x\": 90,\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/green_crafter_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/green\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/green\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/green\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/green\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/green_crafting_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/green\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/green\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/green\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/green\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/green_crafting_monitor.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/green\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/green\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/green\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/green\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/green_creative_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/green\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/green_detector.json",
    "content": "{\n  \"variants\": {\n    \"powered=false\": {\n      \"model\": \"refinedstorage:block/detector/off\"\n    },\n    \"powered=true\": {\n      \"model\": \"refinedstorage:block/detector/green\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/green_disk_manipulator.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/disk_manipulator/loader\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/green_fluid_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/green\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/green\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/green\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/green\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/green_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/green\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/green\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/green\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/green\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/green_network_receiver.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_receiver/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_receiver/green\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/green_network_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_transmitter/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_transmitter/green\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/green_pattern_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/green\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/green\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/green\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/green\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/green_relay.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/relay/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/relay/green\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/green_security_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/green\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/green\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/green\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/green\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/green_wireless_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\"\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/green\"\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/green\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/green\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/green\",\n      \"x\": 90\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/green\",\n      \"x\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/green\",\n      \"x\": 90,\n      \"y\": 90\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/light_blue\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/light_blue\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/light_blue\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/light_blue\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/light_gray_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/light_gray\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/light_gray_crafter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\"\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/light_gray\",\n      \"x\": 180\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/light_gray\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/light_gray\",\n      \"x\": 90\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/light_gray\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/light_gray\"\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/light_gray\",\n      \"x\": 90,\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/light_gray_crafter_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/light_gray\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/light_gray\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/light_gray\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/light_gray\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/light_gray_crafting_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/light_gray\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/light_gray\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/light_gray\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/light_gray\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/light_gray_crafting_monitor.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/light_gray\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/light_gray\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/light_gray\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/light_gray\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/light_gray_creative_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/light_gray\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/light_gray_detector.json",
    "content": "{\n  \"variants\": {\n    \"powered=false\": {\n      \"model\": \"refinedstorage:block/detector/off\"\n    },\n    \"powered=true\": {\n      \"model\": \"refinedstorage:block/detector/light_gray\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/light_gray_disk_manipulator.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/disk_manipulator/loader\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/light_gray_fluid_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/light_gray\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/light_gray\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/light_gray\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/light_gray\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/light_gray_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/light_gray\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/light_gray\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/light_gray\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/light_gray\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/light_gray_network_receiver.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_receiver/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_receiver/light_gray\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/light_gray_network_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_transmitter/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_transmitter/light_gray\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/light_gray_pattern_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/light_gray\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/light_gray\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/light_gray\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/light_gray\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/light_gray_relay.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/relay/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/relay/light_gray\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/light_gray_security_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/light_gray\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/light_gray\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/light_gray\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/light_gray\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/light_gray_wireless_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\"\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/light_gray\"\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/light_gray\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/light_gray\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/light_gray\",\n      \"x\": 90\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/light_gray\",\n      \"x\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/light_gray\",\n      \"x\": 90,\n      \"y\": 90\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/lime_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/lime\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/lime_crafter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\"\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/lime\",\n      \"x\": 180\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/lime\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/lime\",\n      \"x\": 90\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/lime\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/lime\"\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/lime\",\n      \"x\": 90,\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/lime_crafter_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/lime\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/lime\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/lime\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/lime\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/lime_crafting_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/lime\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/lime\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/lime\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/lime\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/lime_crafting_monitor.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/lime\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/lime\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/lime\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/lime\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/lime_creative_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/lime\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/lime_detector.json",
    "content": "{\n  \"variants\": {\n    \"powered=false\": {\n      \"model\": \"refinedstorage:block/detector/off\"\n    },\n    \"powered=true\": {\n      \"model\": \"refinedstorage:block/detector/lime\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/lime_disk_manipulator.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/disk_manipulator/loader\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/lime_fluid_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/lime\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/lime\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/lime\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/lime\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/lime_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/lime\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/lime\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/lime\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/lime\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/lime_network_receiver.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_receiver/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_receiver/lime\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/lime_network_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_transmitter/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_transmitter/lime\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/lime_pattern_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/lime\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/lime\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/lime\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/lime\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/lime_relay.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/relay/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/relay/lime\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/lime_security_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/lime\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/lime\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/lime\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/lime\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/lime_wireless_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\"\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/lime\"\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/lime\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/lime\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/lime\",\n      \"x\": 90\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/lime\",\n      \"x\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/lime\",\n      \"x\": 90,\n      \"y\": 90\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/magenta_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/magenta\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/magenta_crafter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\"\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/magenta\",\n      \"x\": 180\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/magenta\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/magenta\",\n      \"x\": 90\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/magenta\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/magenta\"\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/magenta\",\n      \"x\": 90,\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/magenta_crafter_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/magenta\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/magenta\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/magenta\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/magenta\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/magenta_crafting_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/magenta\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/magenta\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/magenta\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/magenta\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/magenta_crafting_monitor.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/magenta\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/magenta\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/magenta\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/magenta\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/magenta_creative_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/magenta\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/magenta_detector.json",
    "content": "{\n  \"variants\": {\n    \"powered=false\": {\n      \"model\": \"refinedstorage:block/detector/off\"\n    },\n    \"powered=true\": {\n      \"model\": \"refinedstorage:block/detector/magenta\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/magenta_disk_manipulator.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/disk_manipulator/loader\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/magenta_fluid_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/magenta\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/magenta\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/magenta\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/magenta\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/magenta_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/magenta\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/magenta\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/magenta\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/magenta\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/magenta_network_receiver.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_receiver/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_receiver/magenta\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/magenta_network_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_transmitter/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_transmitter/magenta\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/magenta_pattern_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/magenta\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/magenta\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/magenta\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/magenta\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/magenta_relay.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/relay/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/relay/magenta\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/magenta_security_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/magenta\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/magenta\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/magenta\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/magenta\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/magenta_wireless_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\"\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/magenta\"\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/magenta\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/magenta\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/magenta\",\n      \"x\": 90\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/magenta\",\n      \"x\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/magenta\",\n      \"x\": 90,\n      \"y\": 90\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/network_receiver.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_receiver/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_receiver/light_blue\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/network_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_transmitter/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_transmitter/light_blue\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/orange_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/orange\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/orange_crafter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\"\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/orange\",\n      \"x\": 180\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/orange\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/orange\",\n      \"x\": 90\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/orange\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/orange\"\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/orange\",\n      \"x\": 90,\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/orange_crafter_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/orange\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/orange\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/orange\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/orange\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/orange_crafting_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/orange\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/orange\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/orange\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/orange\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/orange_crafting_monitor.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/orange\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/orange\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/orange\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/orange\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/orange_creative_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/orange\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/orange_detector.json",
    "content": "{\n  \"variants\": {\n    \"powered=false\": {\n      \"model\": \"refinedstorage:block/detector/off\"\n    },\n    \"powered=true\": {\n      \"model\": \"refinedstorage:block/detector/orange\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/orange_disk_manipulator.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/disk_manipulator/loader\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/orange_fluid_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/orange\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/orange\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/orange\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/orange\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/orange_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/orange\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/orange\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/orange\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/orange\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/orange_network_receiver.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_receiver/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_receiver/orange\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/orange_network_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_transmitter/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_transmitter/orange\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/orange_pattern_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/orange\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/orange\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/orange\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/orange\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/orange_relay.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/relay/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/relay/orange\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/orange_security_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/orange\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/orange\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/orange\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/orange\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/orange_wireless_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\"\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/orange\"\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/orange\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/orange\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/orange\",\n      \"x\": 90\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/orange\",\n      \"x\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/orange\",\n      \"x\": 90,\n      \"y\": 90\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/pattern_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/light_blue\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/light_blue\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/light_blue\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/light_blue\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/pink_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/pink\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/pink_crafter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\"\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/pink\",\n      \"x\": 180\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/pink\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/pink\",\n      \"x\": 90\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/pink\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/pink\"\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/pink\",\n      \"x\": 90,\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/pink_crafter_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/pink\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/pink\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/pink\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/pink\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/pink_crafting_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/pink\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/pink\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/pink\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/pink\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/pink_crafting_monitor.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/pink\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/pink\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/pink\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/pink\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/pink_creative_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/pink\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/pink_detector.json",
    "content": "{\n  \"variants\": {\n    \"powered=false\": {\n      \"model\": \"refinedstorage:block/detector/off\"\n    },\n    \"powered=true\": {\n      \"model\": \"refinedstorage:block/detector/pink\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/pink_disk_manipulator.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/disk_manipulator/loader\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/pink_fluid_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/pink\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/pink\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/pink\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/pink\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/pink_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/pink\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/pink\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/pink\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/pink\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/pink_network_receiver.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_receiver/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_receiver/pink\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/pink_network_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_transmitter/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_transmitter/pink\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/pink_pattern_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/pink\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/pink\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/pink\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/pink\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/pink_relay.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/relay/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/relay/pink\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/pink_security_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/pink\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/pink\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/pink\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/pink\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/pink_wireless_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\"\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/pink\"\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/pink\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/pink\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/pink\",\n      \"x\": 90\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/pink\",\n      \"x\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/pink\",\n      \"x\": 90,\n      \"y\": 90\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/purple_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/purple\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/purple_crafter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\"\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/purple\",\n      \"x\": 180\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/purple\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/purple\",\n      \"x\": 90\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/purple\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/purple\"\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/purple\",\n      \"x\": 90,\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/purple_crafter_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/purple\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/purple\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/purple\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/purple\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/purple_crafting_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/purple\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/purple\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/purple\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/purple\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/purple_crafting_monitor.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/purple\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/purple\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/purple\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/purple\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/purple_creative_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/purple\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/purple_detector.json",
    "content": "{\n  \"variants\": {\n    \"powered=false\": {\n      \"model\": \"refinedstorage:block/detector/off\"\n    },\n    \"powered=true\": {\n      \"model\": \"refinedstorage:block/detector/purple\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/purple_disk_manipulator.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/disk_manipulator/loader\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/purple_fluid_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/purple\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/purple\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/purple\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/purple\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/purple_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/purple\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/purple\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/purple\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/purple\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/purple_network_receiver.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_receiver/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_receiver/purple\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/purple_network_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_transmitter/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_transmitter/purple\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/purple_pattern_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/purple\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/purple\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/purple\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/purple\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/purple_relay.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/relay/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/relay/purple\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/purple_security_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/purple\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/purple\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/purple\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/purple\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/purple_wireless_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\"\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/purple\"\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/purple\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/purple\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/purple\",\n      \"x\": 90\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/purple\",\n      \"x\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/purple\",\n      \"x\": 90,\n      \"y\": 90\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/red_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/red\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/red_crafter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\"\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/red\",\n      \"x\": 180\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/red\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/red\",\n      \"x\": 90\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/red\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/red\"\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/red\",\n      \"x\": 90,\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/red_crafter_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/red\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/red\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/red\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/red\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/red_crafting_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/red\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/red\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/red\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/red\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/red_crafting_monitor.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/red\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/red\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/red\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/red\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/red_creative_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/red\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/red_detector.json",
    "content": "{\n  \"variants\": {\n    \"powered=false\": {\n      \"model\": \"refinedstorage:block/detector/off\"\n    },\n    \"powered=true\": {\n      \"model\": \"refinedstorage:block/detector/red\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/red_disk_manipulator.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/disk_manipulator/loader\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/red_fluid_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/red\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/red\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/red\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/red\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/red_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/red\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/red\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/red\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/red\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/red_network_receiver.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_receiver/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_receiver/red\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/red_network_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_transmitter/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_transmitter/red\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/red_pattern_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/red\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/red\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/red\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/red\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/red_relay.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/relay/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/relay/red\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/red_security_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/red\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/red\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/red\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/red\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/red_wireless_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\"\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/red\"\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/red\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/red\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/red\",\n      \"x\": 90\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/red\",\n      \"x\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/red\",\n      \"x\": 90,\n      \"y\": 90\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/relay.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/relay/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/relay/light_blue\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/security_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/light_blue\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/light_blue\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/light_blue\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/light_blue\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/white_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/white\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/white_crafter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\"\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/white\",\n      \"x\": 180\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/white\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/white\",\n      \"x\": 90\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/white\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/white\"\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/white\",\n      \"x\": 90,\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/white_crafter_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/white\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/white\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/white\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/white\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/white_crafting_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/white\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/white\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/white\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/white\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/white_crafting_monitor.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/white\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/white\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/white\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/white\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/white_creative_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/white\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/white_detector.json",
    "content": "{\n  \"variants\": {\n    \"powered=false\": {\n      \"model\": \"refinedstorage:block/detector/off\"\n    },\n    \"powered=true\": {\n      \"model\": \"refinedstorage:block/detector/white\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/white_disk_manipulator.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/disk_manipulator/loader\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/white_fluid_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/white\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/white\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/white\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/white\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/white_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/white\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/white\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/white\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/white\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/white_network_receiver.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_receiver/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_receiver/white\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/white_network_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_transmitter/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_transmitter/white\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/white_pattern_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/white\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/white\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/white\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/white\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/white_relay.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/relay/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/relay/white\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/white_security_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/white\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/white\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/white\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/white\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/white_wireless_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\"\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/white\"\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/white\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/white\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/white\",\n      \"x\": 90\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/white\",\n      \"x\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/white\",\n      \"x\": 90,\n      \"y\": 90\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/wireless_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\"\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/light_blue\"\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/light_blue\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/light_blue\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/light_blue\",\n      \"x\": 90\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/light_blue\",\n      \"x\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/light_blue\",\n      \"x\": 90,\n      \"y\": 90\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/yellow_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/yellow\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/yellow_crafter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\"\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/crafter/yellow\",\n      \"x\": 180\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter/yellow\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter/yellow\",\n      \"x\": 90\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter/yellow\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/crafter/yellow\"\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter/yellow\",\n      \"x\": 90,\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/yellow_crafter_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafter_manager/yellow\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafter_manager/yellow\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafter_manager/yellow\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafter_manager/yellow\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/yellow_crafting_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_grid/yellow\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_grid/yellow\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_grid/yellow\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_grid/yellow\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/yellow_crafting_monitor.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/yellow\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/yellow\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/yellow\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/crafting_monitor/yellow\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/yellow_creative_controller.json",
    "content": "{\n  \"variants\": {\n    \"energy_type=nearly_off\": {\n      \"model\": \"refinedstorage:block/controller/nearly_off\"\n    },\n    \"energy_type=nearly_on\": {\n      \"model\": \"refinedstorage:block/controller/nearly_on\"\n    },\n    \"energy_type=off\": {\n      \"model\": \"refinedstorage:block/controller/off\"\n    },\n    \"energy_type=on\": {\n      \"model\": \"refinedstorage:block/controller/yellow\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/yellow_detector.json",
    "content": "{\n  \"variants\": {\n    \"powered=false\": {\n      \"model\": \"refinedstorage:block/detector/off\"\n    },\n    \"powered=true\": {\n      \"model\": \"refinedstorage:block/detector/yellow\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/yellow_disk_manipulator.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/disk_manipulator/loader\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/yellow_fluid_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/fluid_grid/yellow\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/fluid_grid/yellow\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/fluid_grid/yellow\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/fluid_grid/yellow\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/yellow_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/grid/yellow\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/grid/yellow\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/grid/yellow\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/grid/yellow\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/yellow_network_receiver.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_receiver/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_receiver/yellow\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/yellow_network_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/network_transmitter/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/network_transmitter/yellow\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/yellow_pattern_grid.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/pattern_grid/yellow\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/pattern_grid/yellow\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/pattern_grid/yellow\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/pattern_grid/yellow\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/yellow_relay.json",
    "content": "{\n  \"variants\": {\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/relay/disconnected\"\n    },\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/relay/yellow\"\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/yellow_security_manager.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 90\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\"\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/disconnected\",\n      \"y\": 270\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/security_manager/yellow\",\n      \"y\": 90\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/security_manager/yellow\"\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/security_manager/yellow\",\n      \"y\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/security_manager/yellow\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/blockstates/yellow_wireless_transmitter.json",
    "content": "{\n  \"variants\": {\n    \"connected=false,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\"\n    },\n    \"connected=false,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=false,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=false,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90\n    },\n    \"connected=false,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 180\n    },\n    \"connected=false,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/disconnected\",\n      \"x\": 90,\n      \"y\": 90\n    },\n    \"connected=true,direction=down\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/yellow\"\n    },\n    \"connected=true,direction=east\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/yellow\",\n      \"x\": 90,\n      \"y\": 270\n    },\n    \"connected=true,direction=north\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/yellow\",\n      \"x\": 90,\n      \"y\": 180\n    },\n    \"connected=true,direction=south\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/yellow\",\n      \"x\": 90\n    },\n    \"connected=true,direction=up\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/yellow\",\n      \"x\": 180\n    },\n    \"connected=true,direction=west\": {\n      \"model\": \"refinedstorage:block/wireless_transmitter/yellow\",\n      \"x\": 90,\n      \"y\": 90\n    }\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/controller/black.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/controller/on\",\n    \"cutout\": \"refinedstorage:block/controller/cutouts/black\",\n    \"particle\": \"refinedstorage:block/controller/off\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/controller/blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/controller/on\",\n    \"cutout\": \"refinedstorage:block/controller/cutouts/blue\",\n    \"particle\": \"refinedstorage:block/controller/off\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/controller/brown.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/controller/on\",\n    \"cutout\": \"refinedstorage:block/controller/cutouts/brown\",\n    \"particle\": \"refinedstorage:block/controller/off\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/controller/cyan.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/controller/on\",\n    \"cutout\": \"refinedstorage:block/controller/cutouts/cyan\",\n    \"particle\": \"refinedstorage:block/controller/off\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/controller/gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/controller/on\",\n    \"cutout\": \"refinedstorage:block/controller/cutouts/gray\",\n    \"particle\": \"refinedstorage:block/controller/off\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/controller/green.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/controller/on\",\n    \"cutout\": \"refinedstorage:block/controller/cutouts/green\",\n    \"particle\": \"refinedstorage:block/controller/off\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/controller/light_blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/controller/on\",\n    \"cutout\": \"refinedstorage:block/controller/cutouts/light_blue\",\n    \"particle\": \"refinedstorage:block/controller/off\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/controller/light_gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/controller/on\",\n    \"cutout\": \"refinedstorage:block/controller/cutouts/light_gray\",\n    \"particle\": \"refinedstorage:block/controller/off\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/controller/lime.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/controller/on\",\n    \"cutout\": \"refinedstorage:block/controller/cutouts/lime\",\n    \"particle\": \"refinedstorage:block/controller/off\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/controller/magenta.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/controller/on\",\n    \"cutout\": \"refinedstorage:block/controller/cutouts/magenta\",\n    \"particle\": \"refinedstorage:block/controller/off\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/controller/nearly_off.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/controller_nearly\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/controller/on\",\n    \"cutout\": \"refinedstorage:block/controller/cutouts/nearly_off_gray\",\n    \"cutout_gray\": \"refinedstorage:block/controller/cutouts/nearly_off\",\n    \"particle\": \"refinedstorage:block/controller/off\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/controller/nearly_on.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/controller_nearly\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/controller/on\",\n    \"cutout\": \"refinedstorage:block/controller/cutouts/nearly_on_gray\",\n    \"cutout_gray\": \"refinedstorage:block/controller/cutouts/nearly_on\",\n    \"particle\": \"refinedstorage:block/controller/off\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/controller/off.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout_nonemissive\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/controller/off\",\n    \"cutout\": \"refinedstorage:block/controller/cutouts/off\",\n    \"particle\": \"refinedstorage:block/controller/off\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/controller/orange.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/controller/on\",\n    \"cutout\": \"refinedstorage:block/controller/cutouts/orange\",\n    \"particle\": \"refinedstorage:block/controller/off\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/controller/pink.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/controller/on\",\n    \"cutout\": \"refinedstorage:block/controller/cutouts/pink\",\n    \"particle\": \"refinedstorage:block/controller/off\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/controller/purple.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/controller/on\",\n    \"cutout\": \"refinedstorage:block/controller/cutouts/purple\",\n    \"particle\": \"refinedstorage:block/controller/off\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/controller/red.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/controller/on\",\n    \"cutout\": \"refinedstorage:block/controller/cutouts/red\",\n    \"particle\": \"refinedstorage:block/controller/off\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/controller/white.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/controller/on\",\n    \"cutout\": \"refinedstorage:block/controller/cutouts/white\",\n    \"particle\": \"refinedstorage:block/controller/off\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/controller/yellow.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/controller/on\",\n    \"cutout\": \"refinedstorage:block/controller/cutouts/yellow\",\n    \"particle\": \"refinedstorage:block/controller/off\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter/black.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/crafter/cutouts/side_black\",\n    \"cutout_north\": \"refinedstorage:block/crafter/cutouts/side_black\",\n    \"cutout_south\": \"refinedstorage:block/crafter/cutouts/side_black\",\n    \"cutout_up\": \"refinedstorage:block/crafter/cutouts/top_black\",\n    \"cutout_west\": \"refinedstorage:block/crafter/cutouts/side_black\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter/side\",\n    \"north\": \"refinedstorage:block/crafter/side\",\n    \"particle\": \"refinedstorage:block/crafter/side\",\n    \"south\": \"refinedstorage:block/crafter/side\",\n    \"up\": \"refinedstorage:block/crafter/top\",\n    \"west\": \"refinedstorage:block/crafter/side\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter/blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/crafter/cutouts/side_blue\",\n    \"cutout_north\": \"refinedstorage:block/crafter/cutouts/side_blue\",\n    \"cutout_south\": \"refinedstorage:block/crafter/cutouts/side_blue\",\n    \"cutout_up\": \"refinedstorage:block/crafter/cutouts/top_blue\",\n    \"cutout_west\": \"refinedstorage:block/crafter/cutouts/side_blue\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter/side\",\n    \"north\": \"refinedstorage:block/crafter/side\",\n    \"particle\": \"refinedstorage:block/crafter/side\",\n    \"south\": \"refinedstorage:block/crafter/side\",\n    \"up\": \"refinedstorage:block/crafter/top\",\n    \"west\": \"refinedstorage:block/crafter/side\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter/brown.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/crafter/cutouts/side_brown\",\n    \"cutout_north\": \"refinedstorage:block/crafter/cutouts/side_brown\",\n    \"cutout_south\": \"refinedstorage:block/crafter/cutouts/side_brown\",\n    \"cutout_up\": \"refinedstorage:block/crafter/cutouts/top_brown\",\n    \"cutout_west\": \"refinedstorage:block/crafter/cutouts/side_brown\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter/side\",\n    \"north\": \"refinedstorage:block/crafter/side\",\n    \"particle\": \"refinedstorage:block/crafter/side\",\n    \"south\": \"refinedstorage:block/crafter/side\",\n    \"up\": \"refinedstorage:block/crafter/top\",\n    \"west\": \"refinedstorage:block/crafter/side\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter/cyan.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/crafter/cutouts/side_cyan\",\n    \"cutout_north\": \"refinedstorage:block/crafter/cutouts/side_cyan\",\n    \"cutout_south\": \"refinedstorage:block/crafter/cutouts/side_cyan\",\n    \"cutout_up\": \"refinedstorage:block/crafter/cutouts/top_cyan\",\n    \"cutout_west\": \"refinedstorage:block/crafter/cutouts/side_cyan\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter/side\",\n    \"north\": \"refinedstorage:block/crafter/side\",\n    \"particle\": \"refinedstorage:block/crafter/side\",\n    \"south\": \"refinedstorage:block/crafter/side\",\n    \"up\": \"refinedstorage:block/crafter/top\",\n    \"west\": \"refinedstorage:block/crafter/side\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter/disconnected.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout_nonemissive\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/crafter/cutouts/side_disconnected\",\n    \"cutout_north\": \"refinedstorage:block/crafter/cutouts/side_disconnected\",\n    \"cutout_south\": \"refinedstorage:block/crafter/cutouts/side_disconnected\",\n    \"cutout_up\": \"refinedstorage:block/crafter/cutouts/top_disconnected\",\n    \"cutout_west\": \"refinedstorage:block/crafter/cutouts/side_disconnected\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter/side\",\n    \"north\": \"refinedstorage:block/crafter/side\",\n    \"particle\": \"refinedstorage:block/crafter/side\",\n    \"south\": \"refinedstorage:block/crafter/side\",\n    \"up\": \"refinedstorage:block/crafter/top\",\n    \"west\": \"refinedstorage:block/crafter/side\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter/gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/crafter/cutouts/side_gray\",\n    \"cutout_north\": \"refinedstorage:block/crafter/cutouts/side_gray\",\n    \"cutout_south\": \"refinedstorage:block/crafter/cutouts/side_gray\",\n    \"cutout_up\": \"refinedstorage:block/crafter/cutouts/top_gray\",\n    \"cutout_west\": \"refinedstorage:block/crafter/cutouts/side_gray\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter/side\",\n    \"north\": \"refinedstorage:block/crafter/side\",\n    \"particle\": \"refinedstorage:block/crafter/side\",\n    \"south\": \"refinedstorage:block/crafter/side\",\n    \"up\": \"refinedstorage:block/crafter/top\",\n    \"west\": \"refinedstorage:block/crafter/side\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter/green.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/crafter/cutouts/side_green\",\n    \"cutout_north\": \"refinedstorage:block/crafter/cutouts/side_green\",\n    \"cutout_south\": \"refinedstorage:block/crafter/cutouts/side_green\",\n    \"cutout_up\": \"refinedstorage:block/crafter/cutouts/top_green\",\n    \"cutout_west\": \"refinedstorage:block/crafter/cutouts/side_green\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter/side\",\n    \"north\": \"refinedstorage:block/crafter/side\",\n    \"particle\": \"refinedstorage:block/crafter/side\",\n    \"south\": \"refinedstorage:block/crafter/side\",\n    \"up\": \"refinedstorage:block/crafter/top\",\n    \"west\": \"refinedstorage:block/crafter/side\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter/light_blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/crafter/cutouts/side_light_blue\",\n    \"cutout_north\": \"refinedstorage:block/crafter/cutouts/side_light_blue\",\n    \"cutout_south\": \"refinedstorage:block/crafter/cutouts/side_light_blue\",\n    \"cutout_up\": \"refinedstorage:block/crafter/cutouts/top_light_blue\",\n    \"cutout_west\": \"refinedstorage:block/crafter/cutouts/side_light_blue\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter/side\",\n    \"north\": \"refinedstorage:block/crafter/side\",\n    \"particle\": \"refinedstorage:block/crafter/side\",\n    \"south\": \"refinedstorage:block/crafter/side\",\n    \"up\": \"refinedstorage:block/crafter/top\",\n    \"west\": \"refinedstorage:block/crafter/side\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter/light_gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/crafter/cutouts/side_light_gray\",\n    \"cutout_north\": \"refinedstorage:block/crafter/cutouts/side_light_gray\",\n    \"cutout_south\": \"refinedstorage:block/crafter/cutouts/side_light_gray\",\n    \"cutout_up\": \"refinedstorage:block/crafter/cutouts/top_light_gray\",\n    \"cutout_west\": \"refinedstorage:block/crafter/cutouts/side_light_gray\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter/side\",\n    \"north\": \"refinedstorage:block/crafter/side\",\n    \"particle\": \"refinedstorage:block/crafter/side\",\n    \"south\": \"refinedstorage:block/crafter/side\",\n    \"up\": \"refinedstorage:block/crafter/top\",\n    \"west\": \"refinedstorage:block/crafter/side\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter/lime.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/crafter/cutouts/side_lime\",\n    \"cutout_north\": \"refinedstorage:block/crafter/cutouts/side_lime\",\n    \"cutout_south\": \"refinedstorage:block/crafter/cutouts/side_lime\",\n    \"cutout_up\": \"refinedstorage:block/crafter/cutouts/top_lime\",\n    \"cutout_west\": \"refinedstorage:block/crafter/cutouts/side_lime\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter/side\",\n    \"north\": \"refinedstorage:block/crafter/side\",\n    \"particle\": \"refinedstorage:block/crafter/side\",\n    \"south\": \"refinedstorage:block/crafter/side\",\n    \"up\": \"refinedstorage:block/crafter/top\",\n    \"west\": \"refinedstorage:block/crafter/side\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter/magenta.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/crafter/cutouts/side_magenta\",\n    \"cutout_north\": \"refinedstorage:block/crafter/cutouts/side_magenta\",\n    \"cutout_south\": \"refinedstorage:block/crafter/cutouts/side_magenta\",\n    \"cutout_up\": \"refinedstorage:block/crafter/cutouts/top_magenta\",\n    \"cutout_west\": \"refinedstorage:block/crafter/cutouts/side_magenta\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter/side\",\n    \"north\": \"refinedstorage:block/crafter/side\",\n    \"particle\": \"refinedstorage:block/crafter/side\",\n    \"south\": \"refinedstorage:block/crafter/side\",\n    \"up\": \"refinedstorage:block/crafter/top\",\n    \"west\": \"refinedstorage:block/crafter/side\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter/orange.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/crafter/cutouts/side_orange\",\n    \"cutout_north\": \"refinedstorage:block/crafter/cutouts/side_orange\",\n    \"cutout_south\": \"refinedstorage:block/crafter/cutouts/side_orange\",\n    \"cutout_up\": \"refinedstorage:block/crafter/cutouts/top_orange\",\n    \"cutout_west\": \"refinedstorage:block/crafter/cutouts/side_orange\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter/side\",\n    \"north\": \"refinedstorage:block/crafter/side\",\n    \"particle\": \"refinedstorage:block/crafter/side\",\n    \"south\": \"refinedstorage:block/crafter/side\",\n    \"up\": \"refinedstorage:block/crafter/top\",\n    \"west\": \"refinedstorage:block/crafter/side\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter/pink.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/crafter/cutouts/side_pink\",\n    \"cutout_north\": \"refinedstorage:block/crafter/cutouts/side_pink\",\n    \"cutout_south\": \"refinedstorage:block/crafter/cutouts/side_pink\",\n    \"cutout_up\": \"refinedstorage:block/crafter/cutouts/top_pink\",\n    \"cutout_west\": \"refinedstorage:block/crafter/cutouts/side_pink\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter/side\",\n    \"north\": \"refinedstorage:block/crafter/side\",\n    \"particle\": \"refinedstorage:block/crafter/side\",\n    \"south\": \"refinedstorage:block/crafter/side\",\n    \"up\": \"refinedstorage:block/crafter/top\",\n    \"west\": \"refinedstorage:block/crafter/side\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter/purple.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/crafter/cutouts/side_purple\",\n    \"cutout_north\": \"refinedstorage:block/crafter/cutouts/side_purple\",\n    \"cutout_south\": \"refinedstorage:block/crafter/cutouts/side_purple\",\n    \"cutout_up\": \"refinedstorage:block/crafter/cutouts/top_purple\",\n    \"cutout_west\": \"refinedstorage:block/crafter/cutouts/side_purple\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter/side\",\n    \"north\": \"refinedstorage:block/crafter/side\",\n    \"particle\": \"refinedstorage:block/crafter/side\",\n    \"south\": \"refinedstorage:block/crafter/side\",\n    \"up\": \"refinedstorage:block/crafter/top\",\n    \"west\": \"refinedstorage:block/crafter/side\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter/red.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/crafter/cutouts/side_red\",\n    \"cutout_north\": \"refinedstorage:block/crafter/cutouts/side_red\",\n    \"cutout_south\": \"refinedstorage:block/crafter/cutouts/side_red\",\n    \"cutout_up\": \"refinedstorage:block/crafter/cutouts/top_red\",\n    \"cutout_west\": \"refinedstorage:block/crafter/cutouts/side_red\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter/side\",\n    \"north\": \"refinedstorage:block/crafter/side\",\n    \"particle\": \"refinedstorage:block/crafter/side\",\n    \"south\": \"refinedstorage:block/crafter/side\",\n    \"up\": \"refinedstorage:block/crafter/top\",\n    \"west\": \"refinedstorage:block/crafter/side\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter/white.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/crafter/cutouts/side_white\",\n    \"cutout_north\": \"refinedstorage:block/crafter/cutouts/side_white\",\n    \"cutout_south\": \"refinedstorage:block/crafter/cutouts/side_white\",\n    \"cutout_up\": \"refinedstorage:block/crafter/cutouts/top_white\",\n    \"cutout_west\": \"refinedstorage:block/crafter/cutouts/side_white\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter/side\",\n    \"north\": \"refinedstorage:block/crafter/side\",\n    \"particle\": \"refinedstorage:block/crafter/side\",\n    \"south\": \"refinedstorage:block/crafter/side\",\n    \"up\": \"refinedstorage:block/crafter/top\",\n    \"west\": \"refinedstorage:block/crafter/side\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter/yellow.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/crafter/cutouts/side_yellow\",\n    \"cutout_north\": \"refinedstorage:block/crafter/cutouts/side_yellow\",\n    \"cutout_south\": \"refinedstorage:block/crafter/cutouts/side_yellow\",\n    \"cutout_up\": \"refinedstorage:block/crafter/cutouts/top_yellow\",\n    \"cutout_west\": \"refinedstorage:block/crafter/cutouts/side_yellow\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter/side\",\n    \"north\": \"refinedstorage:block/crafter/side\",\n    \"particle\": \"refinedstorage:block/crafter/side\",\n    \"south\": \"refinedstorage:block/crafter/side\",\n    \"up\": \"refinedstorage:block/crafter/top\",\n    \"west\": \"refinedstorage:block/crafter/side\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter_manager/black.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafter_manager/cutouts/black\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter_manager/right\",\n    \"north\": \"refinedstorage:block/crafter_manager/front\",\n    \"particle\": \"refinedstorage:block/crafter_manager/right\",\n    \"south\": \"refinedstorage:block/crafter_manager/back\",\n    \"up\": \"refinedstorage:block/crafter_manager/top\",\n    \"west\": \"refinedstorage:block/crafter_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter_manager/blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafter_manager/cutouts/blue\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter_manager/right\",\n    \"north\": \"refinedstorage:block/crafter_manager/front\",\n    \"particle\": \"refinedstorage:block/crafter_manager/right\",\n    \"south\": \"refinedstorage:block/crafter_manager/back\",\n    \"up\": \"refinedstorage:block/crafter_manager/top\",\n    \"west\": \"refinedstorage:block/crafter_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter_manager/brown.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafter_manager/cutouts/brown\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter_manager/right\",\n    \"north\": \"refinedstorage:block/crafter_manager/front\",\n    \"particle\": \"refinedstorage:block/crafter_manager/right\",\n    \"south\": \"refinedstorage:block/crafter_manager/back\",\n    \"up\": \"refinedstorage:block/crafter_manager/top\",\n    \"west\": \"refinedstorage:block/crafter_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter_manager/cyan.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafter_manager/cutouts/cyan\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter_manager/right\",\n    \"north\": \"refinedstorage:block/crafter_manager/front\",\n    \"particle\": \"refinedstorage:block/crafter_manager/right\",\n    \"south\": \"refinedstorage:block/crafter_manager/back\",\n    \"up\": \"refinedstorage:block/crafter_manager/top\",\n    \"west\": \"refinedstorage:block/crafter_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter_manager/disconnected.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout_nonemissive\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafter_manager/cutouts/disconnected\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter_manager/right\",\n    \"north\": \"refinedstorage:block/crafter_manager/front\",\n    \"particle\": \"refinedstorage:block/crafter_manager/right\",\n    \"south\": \"refinedstorage:block/crafter_manager/back\",\n    \"up\": \"refinedstorage:block/crafter_manager/top\",\n    \"west\": \"refinedstorage:block/crafter_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter_manager/gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafter_manager/cutouts/gray\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter_manager/right\",\n    \"north\": \"refinedstorage:block/crafter_manager/front\",\n    \"particle\": \"refinedstorage:block/crafter_manager/right\",\n    \"south\": \"refinedstorage:block/crafter_manager/back\",\n    \"up\": \"refinedstorage:block/crafter_manager/top\",\n    \"west\": \"refinedstorage:block/crafter_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter_manager/green.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafter_manager/cutouts/green\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter_manager/right\",\n    \"north\": \"refinedstorage:block/crafter_manager/front\",\n    \"particle\": \"refinedstorage:block/crafter_manager/right\",\n    \"south\": \"refinedstorage:block/crafter_manager/back\",\n    \"up\": \"refinedstorage:block/crafter_manager/top\",\n    \"west\": \"refinedstorage:block/crafter_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter_manager/light_blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafter_manager/cutouts/light_blue\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter_manager/right\",\n    \"north\": \"refinedstorage:block/crafter_manager/front\",\n    \"particle\": \"refinedstorage:block/crafter_manager/right\",\n    \"south\": \"refinedstorage:block/crafter_manager/back\",\n    \"up\": \"refinedstorage:block/crafter_manager/top\",\n    \"west\": \"refinedstorage:block/crafter_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter_manager/light_gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafter_manager/cutouts/light_gray\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter_manager/right\",\n    \"north\": \"refinedstorage:block/crafter_manager/front\",\n    \"particle\": \"refinedstorage:block/crafter_manager/right\",\n    \"south\": \"refinedstorage:block/crafter_manager/back\",\n    \"up\": \"refinedstorage:block/crafter_manager/top\",\n    \"west\": \"refinedstorage:block/crafter_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter_manager/lime.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafter_manager/cutouts/lime\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter_manager/right\",\n    \"north\": \"refinedstorage:block/crafter_manager/front\",\n    \"particle\": \"refinedstorage:block/crafter_manager/right\",\n    \"south\": \"refinedstorage:block/crafter_manager/back\",\n    \"up\": \"refinedstorage:block/crafter_manager/top\",\n    \"west\": \"refinedstorage:block/crafter_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter_manager/magenta.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafter_manager/cutouts/magenta\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter_manager/right\",\n    \"north\": \"refinedstorage:block/crafter_manager/front\",\n    \"particle\": \"refinedstorage:block/crafter_manager/right\",\n    \"south\": \"refinedstorage:block/crafter_manager/back\",\n    \"up\": \"refinedstorage:block/crafter_manager/top\",\n    \"west\": \"refinedstorage:block/crafter_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter_manager/orange.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafter_manager/cutouts/orange\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter_manager/right\",\n    \"north\": \"refinedstorage:block/crafter_manager/front\",\n    \"particle\": \"refinedstorage:block/crafter_manager/right\",\n    \"south\": \"refinedstorage:block/crafter_manager/back\",\n    \"up\": \"refinedstorage:block/crafter_manager/top\",\n    \"west\": \"refinedstorage:block/crafter_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter_manager/pink.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafter_manager/cutouts/pink\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter_manager/right\",\n    \"north\": \"refinedstorage:block/crafter_manager/front\",\n    \"particle\": \"refinedstorage:block/crafter_manager/right\",\n    \"south\": \"refinedstorage:block/crafter_manager/back\",\n    \"up\": \"refinedstorage:block/crafter_manager/top\",\n    \"west\": \"refinedstorage:block/crafter_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter_manager/purple.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafter_manager/cutouts/purple\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter_manager/right\",\n    \"north\": \"refinedstorage:block/crafter_manager/front\",\n    \"particle\": \"refinedstorage:block/crafter_manager/right\",\n    \"south\": \"refinedstorage:block/crafter_manager/back\",\n    \"up\": \"refinedstorage:block/crafter_manager/top\",\n    \"west\": \"refinedstorage:block/crafter_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter_manager/red.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafter_manager/cutouts/red\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter_manager/right\",\n    \"north\": \"refinedstorage:block/crafter_manager/front\",\n    \"particle\": \"refinedstorage:block/crafter_manager/right\",\n    \"south\": \"refinedstorage:block/crafter_manager/back\",\n    \"up\": \"refinedstorage:block/crafter_manager/top\",\n    \"west\": \"refinedstorage:block/crafter_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter_manager/white.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafter_manager/cutouts/white\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter_manager/right\",\n    \"north\": \"refinedstorage:block/crafter_manager/front\",\n    \"particle\": \"refinedstorage:block/crafter_manager/right\",\n    \"south\": \"refinedstorage:block/crafter_manager/back\",\n    \"up\": \"refinedstorage:block/crafter_manager/top\",\n    \"west\": \"refinedstorage:block/crafter_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafter_manager/yellow.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafter_manager/cutouts/yellow\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafter_manager/right\",\n    \"north\": \"refinedstorage:block/crafter_manager/front\",\n    \"particle\": \"refinedstorage:block/crafter_manager/right\",\n    \"south\": \"refinedstorage:block/crafter_manager/back\",\n    \"up\": \"refinedstorage:block/crafter_manager/top\",\n    \"west\": \"refinedstorage:block/crafter_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_grid/black.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_grid/cutouts/black\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_grid/right\",\n    \"north\": \"refinedstorage:block/crafting_grid/front\",\n    \"particle\": \"refinedstorage:block/crafting_grid/right\",\n    \"south\": \"refinedstorage:block/crafting_grid/back\",\n    \"up\": \"refinedstorage:block/crafting_grid/top\",\n    \"west\": \"refinedstorage:block/crafting_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_grid/blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_grid/cutouts/blue\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_grid/right\",\n    \"north\": \"refinedstorage:block/crafting_grid/front\",\n    \"particle\": \"refinedstorage:block/crafting_grid/right\",\n    \"south\": \"refinedstorage:block/crafting_grid/back\",\n    \"up\": \"refinedstorage:block/crafting_grid/top\",\n    \"west\": \"refinedstorage:block/crafting_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_grid/brown.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_grid/cutouts/brown\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_grid/right\",\n    \"north\": \"refinedstorage:block/crafting_grid/front\",\n    \"particle\": \"refinedstorage:block/crafting_grid/right\",\n    \"south\": \"refinedstorage:block/crafting_grid/back\",\n    \"up\": \"refinedstorage:block/crafting_grid/top\",\n    \"west\": \"refinedstorage:block/crafting_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_grid/cyan.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_grid/cutouts/cyan\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_grid/right\",\n    \"north\": \"refinedstorage:block/crafting_grid/front\",\n    \"particle\": \"refinedstorage:block/crafting_grid/right\",\n    \"south\": \"refinedstorage:block/crafting_grid/back\",\n    \"up\": \"refinedstorage:block/crafting_grid/top\",\n    \"west\": \"refinedstorage:block/crafting_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_grid/disconnected.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout_nonemissive\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_grid/cutouts/disconnected\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_grid/right\",\n    \"north\": \"refinedstorage:block/crafting_grid/front\",\n    \"particle\": \"refinedstorage:block/crafting_grid/right\",\n    \"south\": \"refinedstorage:block/crafting_grid/back\",\n    \"up\": \"refinedstorage:block/crafting_grid/top\",\n    \"west\": \"refinedstorage:block/crafting_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_grid/gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_grid/cutouts/gray\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_grid/right\",\n    \"north\": \"refinedstorage:block/crafting_grid/front\",\n    \"particle\": \"refinedstorage:block/crafting_grid/right\",\n    \"south\": \"refinedstorage:block/crafting_grid/back\",\n    \"up\": \"refinedstorage:block/crafting_grid/top\",\n    \"west\": \"refinedstorage:block/crafting_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_grid/green.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_grid/cutouts/green\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_grid/right\",\n    \"north\": \"refinedstorage:block/crafting_grid/front\",\n    \"particle\": \"refinedstorage:block/crafting_grid/right\",\n    \"south\": \"refinedstorage:block/crafting_grid/back\",\n    \"up\": \"refinedstorage:block/crafting_grid/top\",\n    \"west\": \"refinedstorage:block/crafting_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_grid/light_blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_grid/cutouts/light_blue\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_grid/right\",\n    \"north\": \"refinedstorage:block/crafting_grid/front\",\n    \"particle\": \"refinedstorage:block/crafting_grid/right\",\n    \"south\": \"refinedstorage:block/crafting_grid/back\",\n    \"up\": \"refinedstorage:block/crafting_grid/top\",\n    \"west\": \"refinedstorage:block/crafting_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_grid/light_gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_grid/cutouts/light_gray\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_grid/right\",\n    \"north\": \"refinedstorage:block/crafting_grid/front\",\n    \"particle\": \"refinedstorage:block/crafting_grid/right\",\n    \"south\": \"refinedstorage:block/crafting_grid/back\",\n    \"up\": \"refinedstorage:block/crafting_grid/top\",\n    \"west\": \"refinedstorage:block/crafting_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_grid/lime.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_grid/cutouts/lime\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_grid/right\",\n    \"north\": \"refinedstorage:block/crafting_grid/front\",\n    \"particle\": \"refinedstorage:block/crafting_grid/right\",\n    \"south\": \"refinedstorage:block/crafting_grid/back\",\n    \"up\": \"refinedstorage:block/crafting_grid/top\",\n    \"west\": \"refinedstorage:block/crafting_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_grid/magenta.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_grid/cutouts/magenta\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_grid/right\",\n    \"north\": \"refinedstorage:block/crafting_grid/front\",\n    \"particle\": \"refinedstorage:block/crafting_grid/right\",\n    \"south\": \"refinedstorage:block/crafting_grid/back\",\n    \"up\": \"refinedstorage:block/crafting_grid/top\",\n    \"west\": \"refinedstorage:block/crafting_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_grid/orange.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_grid/cutouts/orange\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_grid/right\",\n    \"north\": \"refinedstorage:block/crafting_grid/front\",\n    \"particle\": \"refinedstorage:block/crafting_grid/right\",\n    \"south\": \"refinedstorage:block/crafting_grid/back\",\n    \"up\": \"refinedstorage:block/crafting_grid/top\",\n    \"west\": \"refinedstorage:block/crafting_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_grid/pink.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_grid/cutouts/pink\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_grid/right\",\n    \"north\": \"refinedstorage:block/crafting_grid/front\",\n    \"particle\": \"refinedstorage:block/crafting_grid/right\",\n    \"south\": \"refinedstorage:block/crafting_grid/back\",\n    \"up\": \"refinedstorage:block/crafting_grid/top\",\n    \"west\": \"refinedstorage:block/crafting_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_grid/purple.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_grid/cutouts/purple\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_grid/right\",\n    \"north\": \"refinedstorage:block/crafting_grid/front\",\n    \"particle\": \"refinedstorage:block/crafting_grid/right\",\n    \"south\": \"refinedstorage:block/crafting_grid/back\",\n    \"up\": \"refinedstorage:block/crafting_grid/top\",\n    \"west\": \"refinedstorage:block/crafting_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_grid/red.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_grid/cutouts/red\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_grid/right\",\n    \"north\": \"refinedstorage:block/crafting_grid/front\",\n    \"particle\": \"refinedstorage:block/crafting_grid/right\",\n    \"south\": \"refinedstorage:block/crafting_grid/back\",\n    \"up\": \"refinedstorage:block/crafting_grid/top\",\n    \"west\": \"refinedstorage:block/crafting_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_grid/white.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_grid/cutouts/white\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_grid/right\",\n    \"north\": \"refinedstorage:block/crafting_grid/front\",\n    \"particle\": \"refinedstorage:block/crafting_grid/right\",\n    \"south\": \"refinedstorage:block/crafting_grid/back\",\n    \"up\": \"refinedstorage:block/crafting_grid/top\",\n    \"west\": \"refinedstorage:block/crafting_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_grid/yellow.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_grid/cutouts/yellow\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_grid/right\",\n    \"north\": \"refinedstorage:block/crafting_grid/front\",\n    \"particle\": \"refinedstorage:block/crafting_grid/right\",\n    \"south\": \"refinedstorage:block/crafting_grid/back\",\n    \"up\": \"refinedstorage:block/crafting_grid/top\",\n    \"west\": \"refinedstorage:block/crafting_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/black.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_monitor/cutouts/black\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_monitor/right\",\n    \"north\": \"refinedstorage:block/crafting_monitor/front\",\n    \"particle\": \"refinedstorage:block/crafting_monitor/right\",\n    \"south\": \"refinedstorage:block/crafting_monitor/back\",\n    \"up\": \"refinedstorage:block/crafting_monitor/top\",\n    \"west\": \"refinedstorage:block/crafting_monitor/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_monitor/cutouts/blue\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_monitor/right\",\n    \"north\": \"refinedstorage:block/crafting_monitor/front\",\n    \"particle\": \"refinedstorage:block/crafting_monitor/right\",\n    \"south\": \"refinedstorage:block/crafting_monitor/back\",\n    \"up\": \"refinedstorage:block/crafting_monitor/top\",\n    \"west\": \"refinedstorage:block/crafting_monitor/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/brown.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_monitor/cutouts/brown\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_monitor/right\",\n    \"north\": \"refinedstorage:block/crafting_monitor/front\",\n    \"particle\": \"refinedstorage:block/crafting_monitor/right\",\n    \"south\": \"refinedstorage:block/crafting_monitor/back\",\n    \"up\": \"refinedstorage:block/crafting_monitor/top\",\n    \"west\": \"refinedstorage:block/crafting_monitor/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/cyan.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_monitor/cutouts/cyan\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_monitor/right\",\n    \"north\": \"refinedstorage:block/crafting_monitor/front\",\n    \"particle\": \"refinedstorage:block/crafting_monitor/right\",\n    \"south\": \"refinedstorage:block/crafting_monitor/back\",\n    \"up\": \"refinedstorage:block/crafting_monitor/top\",\n    \"west\": \"refinedstorage:block/crafting_monitor/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/disconnected.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout_nonemissive\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_monitor/cutouts/disconnected\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_monitor/right\",\n    \"north\": \"refinedstorage:block/crafting_monitor/front\",\n    \"particle\": \"refinedstorage:block/crafting_monitor/right\",\n    \"south\": \"refinedstorage:block/crafting_monitor/back\",\n    \"up\": \"refinedstorage:block/crafting_monitor/top\",\n    \"west\": \"refinedstorage:block/crafting_monitor/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_monitor/cutouts/gray\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_monitor/right\",\n    \"north\": \"refinedstorage:block/crafting_monitor/front\",\n    \"particle\": \"refinedstorage:block/crafting_monitor/right\",\n    \"south\": \"refinedstorage:block/crafting_monitor/back\",\n    \"up\": \"refinedstorage:block/crafting_monitor/top\",\n    \"west\": \"refinedstorage:block/crafting_monitor/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/green.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_monitor/cutouts/green\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_monitor/right\",\n    \"north\": \"refinedstorage:block/crafting_monitor/front\",\n    \"particle\": \"refinedstorage:block/crafting_monitor/right\",\n    \"south\": \"refinedstorage:block/crafting_monitor/back\",\n    \"up\": \"refinedstorage:block/crafting_monitor/top\",\n    \"west\": \"refinedstorage:block/crafting_monitor/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/light_blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_monitor/cutouts/light_blue\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_monitor/right\",\n    \"north\": \"refinedstorage:block/crafting_monitor/front\",\n    \"particle\": \"refinedstorage:block/crafting_monitor/right\",\n    \"south\": \"refinedstorage:block/crafting_monitor/back\",\n    \"up\": \"refinedstorage:block/crafting_monitor/top\",\n    \"west\": \"refinedstorage:block/crafting_monitor/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/light_gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_monitor/cutouts/light_gray\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_monitor/right\",\n    \"north\": \"refinedstorage:block/crafting_monitor/front\",\n    \"particle\": \"refinedstorage:block/crafting_monitor/right\",\n    \"south\": \"refinedstorage:block/crafting_monitor/back\",\n    \"up\": \"refinedstorage:block/crafting_monitor/top\",\n    \"west\": \"refinedstorage:block/crafting_monitor/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/lime.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_monitor/cutouts/lime\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_monitor/right\",\n    \"north\": \"refinedstorage:block/crafting_monitor/front\",\n    \"particle\": \"refinedstorage:block/crafting_monitor/right\",\n    \"south\": \"refinedstorage:block/crafting_monitor/back\",\n    \"up\": \"refinedstorage:block/crafting_monitor/top\",\n    \"west\": \"refinedstorage:block/crafting_monitor/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/magenta.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_monitor/cutouts/magenta\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_monitor/right\",\n    \"north\": \"refinedstorage:block/crafting_monitor/front\",\n    \"particle\": \"refinedstorage:block/crafting_monitor/right\",\n    \"south\": \"refinedstorage:block/crafting_monitor/back\",\n    \"up\": \"refinedstorage:block/crafting_monitor/top\",\n    \"west\": \"refinedstorage:block/crafting_monitor/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/orange.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_monitor/cutouts/orange\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_monitor/right\",\n    \"north\": \"refinedstorage:block/crafting_monitor/front\",\n    \"particle\": \"refinedstorage:block/crafting_monitor/right\",\n    \"south\": \"refinedstorage:block/crafting_monitor/back\",\n    \"up\": \"refinedstorage:block/crafting_monitor/top\",\n    \"west\": \"refinedstorage:block/crafting_monitor/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/pink.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_monitor/cutouts/pink\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_monitor/right\",\n    \"north\": \"refinedstorage:block/crafting_monitor/front\",\n    \"particle\": \"refinedstorage:block/crafting_monitor/right\",\n    \"south\": \"refinedstorage:block/crafting_monitor/back\",\n    \"up\": \"refinedstorage:block/crafting_monitor/top\",\n    \"west\": \"refinedstorage:block/crafting_monitor/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/purple.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_monitor/cutouts/purple\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_monitor/right\",\n    \"north\": \"refinedstorage:block/crafting_monitor/front\",\n    \"particle\": \"refinedstorage:block/crafting_monitor/right\",\n    \"south\": \"refinedstorage:block/crafting_monitor/back\",\n    \"up\": \"refinedstorage:block/crafting_monitor/top\",\n    \"west\": \"refinedstorage:block/crafting_monitor/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/red.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_monitor/cutouts/red\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_monitor/right\",\n    \"north\": \"refinedstorage:block/crafting_monitor/front\",\n    \"particle\": \"refinedstorage:block/crafting_monitor/right\",\n    \"south\": \"refinedstorage:block/crafting_monitor/back\",\n    \"up\": \"refinedstorage:block/crafting_monitor/top\",\n    \"west\": \"refinedstorage:block/crafting_monitor/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/white.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_monitor/cutouts/white\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_monitor/right\",\n    \"north\": \"refinedstorage:block/crafting_monitor/front\",\n    \"particle\": \"refinedstorage:block/crafting_monitor/right\",\n    \"south\": \"refinedstorage:block/crafting_monitor/back\",\n    \"up\": \"refinedstorage:block/crafting_monitor/top\",\n    \"west\": \"refinedstorage:block/crafting_monitor/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/yellow.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/crafting_monitor/cutouts/yellow\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/crafting_monitor/right\",\n    \"north\": \"refinedstorage:block/crafting_monitor/front\",\n    \"particle\": \"refinedstorage:block/crafting_monitor/right\",\n    \"south\": \"refinedstorage:block/crafting_monitor/back\",\n    \"up\": \"refinedstorage:block/crafting_monitor/top\",\n    \"west\": \"refinedstorage:block/crafting_monitor/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/detector/black.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector\",\n  \"textures\": {\n    \"torch\": \"refinedstorage:block/detector/cutouts/black\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/detector/blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector\",\n  \"textures\": {\n    \"torch\": \"refinedstorage:block/detector/cutouts/blue\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/detector/brown.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector\",\n  \"textures\": {\n    \"torch\": \"refinedstorage:block/detector/cutouts/brown\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/detector/cyan.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector\",\n  \"textures\": {\n    \"torch\": \"refinedstorage:block/detector/cutouts/cyan\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/detector/gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector\",\n  \"textures\": {\n    \"torch\": \"refinedstorage:block/detector/cutouts/gray\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/detector/green.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector\",\n  \"textures\": {\n    \"torch\": \"refinedstorage:block/detector/cutouts/green\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/detector/light_blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector\",\n  \"textures\": {\n    \"torch\": \"refinedstorage:block/detector/cutouts/light_blue\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/detector/light_gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector\",\n  \"textures\": {\n    \"torch\": \"refinedstorage:block/detector/cutouts/light_gray\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/detector/lime.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector\",\n  \"textures\": {\n    \"torch\": \"refinedstorage:block/detector/cutouts/lime\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/detector/magenta.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector\",\n  \"textures\": {\n    \"torch\": \"refinedstorage:block/detector/cutouts/magenta\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/detector/off.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector_nonemissive\",\n  \"textures\": {\n    \"torch\": \"refinedstorage:block/detector/cutouts/off\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/detector/orange.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector\",\n  \"textures\": {\n    \"torch\": \"refinedstorage:block/detector/cutouts/orange\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/detector/pink.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector\",\n  \"textures\": {\n    \"torch\": \"refinedstorage:block/detector/cutouts/pink\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/detector/purple.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector\",\n  \"textures\": {\n    \"torch\": \"refinedstorage:block/detector/cutouts/purple\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/detector/red.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector\",\n  \"textures\": {\n    \"torch\": \"refinedstorage:block/detector/cutouts/red\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/detector/white.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector\",\n  \"textures\": {\n    \"torch\": \"refinedstorage:block/detector/cutouts/white\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/detector/yellow.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector\",\n  \"textures\": {\n    \"torch\": \"refinedstorage:block/detector/cutouts/yellow\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/black.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/disk_manipulator/cutouts/black\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/disk_manipulator/right\",\n    \"north\": \"refinedstorage:block/disk_manipulator/front\",\n    \"particle\": \"refinedstorage:block/disk_manipulator/right\",\n    \"south\": \"refinedstorage:block/disk_manipulator/back\",\n    \"up\": \"refinedstorage:block/disk_manipulator/top\",\n    \"west\": \"refinedstorage:block/disk_manipulator/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/disk_manipulator/cutouts/blue\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/disk_manipulator/right\",\n    \"north\": \"refinedstorage:block/disk_manipulator/front\",\n    \"particle\": \"refinedstorage:block/disk_manipulator/right\",\n    \"south\": \"refinedstorage:block/disk_manipulator/back\",\n    \"up\": \"refinedstorage:block/disk_manipulator/top\",\n    \"west\": \"refinedstorage:block/disk_manipulator/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/brown.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/disk_manipulator/cutouts/brown\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/disk_manipulator/right\",\n    \"north\": \"refinedstorage:block/disk_manipulator/front\",\n    \"particle\": \"refinedstorage:block/disk_manipulator/right\",\n    \"south\": \"refinedstorage:block/disk_manipulator/back\",\n    \"up\": \"refinedstorage:block/disk_manipulator/top\",\n    \"west\": \"refinedstorage:block/disk_manipulator/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/cyan.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/disk_manipulator/cutouts/cyan\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/disk_manipulator/right\",\n    \"north\": \"refinedstorage:block/disk_manipulator/front\",\n    \"particle\": \"refinedstorage:block/disk_manipulator/right\",\n    \"south\": \"refinedstorage:block/disk_manipulator/back\",\n    \"up\": \"refinedstorage:block/disk_manipulator/top\",\n    \"west\": \"refinedstorage:block/disk_manipulator/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/disconnected.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout_nonemissive\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/disk_manipulator/cutouts/disconnected\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/disk_manipulator/right\",\n    \"north\": \"refinedstorage:block/disk_manipulator/front\",\n    \"particle\": \"refinedstorage:block/disk_manipulator/right\",\n    \"south\": \"refinedstorage:block/disk_manipulator/back\",\n    \"up\": \"refinedstorage:block/disk_manipulator/top\",\n    \"west\": \"refinedstorage:block/disk_manipulator/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/disk_manipulator/cutouts/gray\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/disk_manipulator/right\",\n    \"north\": \"refinedstorage:block/disk_manipulator/front\",\n    \"particle\": \"refinedstorage:block/disk_manipulator/right\",\n    \"south\": \"refinedstorage:block/disk_manipulator/back\",\n    \"up\": \"refinedstorage:block/disk_manipulator/top\",\n    \"west\": \"refinedstorage:block/disk_manipulator/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/green.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/disk_manipulator/cutouts/green\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/disk_manipulator/right\",\n    \"north\": \"refinedstorage:block/disk_manipulator/front\",\n    \"particle\": \"refinedstorage:block/disk_manipulator/right\",\n    \"south\": \"refinedstorage:block/disk_manipulator/back\",\n    \"up\": \"refinedstorage:block/disk_manipulator/top\",\n    \"west\": \"refinedstorage:block/disk_manipulator/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/light_blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/disk_manipulator/cutouts/light_blue\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/disk_manipulator/right\",\n    \"north\": \"refinedstorage:block/disk_manipulator/front\",\n    \"particle\": \"refinedstorage:block/disk_manipulator/right\",\n    \"south\": \"refinedstorage:block/disk_manipulator/back\",\n    \"up\": \"refinedstorage:block/disk_manipulator/top\",\n    \"west\": \"refinedstorage:block/disk_manipulator/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/light_gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/disk_manipulator/cutouts/light_gray\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/disk_manipulator/right\",\n    \"north\": \"refinedstorage:block/disk_manipulator/front\",\n    \"particle\": \"refinedstorage:block/disk_manipulator/right\",\n    \"south\": \"refinedstorage:block/disk_manipulator/back\",\n    \"up\": \"refinedstorage:block/disk_manipulator/top\",\n    \"west\": \"refinedstorage:block/disk_manipulator/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/lime.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/disk_manipulator/cutouts/lime\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/disk_manipulator/right\",\n    \"north\": \"refinedstorage:block/disk_manipulator/front\",\n    \"particle\": \"refinedstorage:block/disk_manipulator/right\",\n    \"south\": \"refinedstorage:block/disk_manipulator/back\",\n    \"up\": \"refinedstorage:block/disk_manipulator/top\",\n    \"west\": \"refinedstorage:block/disk_manipulator/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/loader.json",
    "content": "{\n  \"loader\": \"refinedstorage:disk_manipulator\",\n  \"render_type\": \"minecraft:cutout\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/magenta.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/disk_manipulator/cutouts/magenta\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/disk_manipulator/right\",\n    \"north\": \"refinedstorage:block/disk_manipulator/front\",\n    \"particle\": \"refinedstorage:block/disk_manipulator/right\",\n    \"south\": \"refinedstorage:block/disk_manipulator/back\",\n    \"up\": \"refinedstorage:block/disk_manipulator/top\",\n    \"west\": \"refinedstorage:block/disk_manipulator/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/orange.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/disk_manipulator/cutouts/orange\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/disk_manipulator/right\",\n    \"north\": \"refinedstorage:block/disk_manipulator/front\",\n    \"particle\": \"refinedstorage:block/disk_manipulator/right\",\n    \"south\": \"refinedstorage:block/disk_manipulator/back\",\n    \"up\": \"refinedstorage:block/disk_manipulator/top\",\n    \"west\": \"refinedstorage:block/disk_manipulator/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/pink.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/disk_manipulator/cutouts/pink\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/disk_manipulator/right\",\n    \"north\": \"refinedstorage:block/disk_manipulator/front\",\n    \"particle\": \"refinedstorage:block/disk_manipulator/right\",\n    \"south\": \"refinedstorage:block/disk_manipulator/back\",\n    \"up\": \"refinedstorage:block/disk_manipulator/top\",\n    \"west\": \"refinedstorage:block/disk_manipulator/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/purple.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/disk_manipulator/cutouts/purple\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/disk_manipulator/right\",\n    \"north\": \"refinedstorage:block/disk_manipulator/front\",\n    \"particle\": \"refinedstorage:block/disk_manipulator/right\",\n    \"south\": \"refinedstorage:block/disk_manipulator/back\",\n    \"up\": \"refinedstorage:block/disk_manipulator/top\",\n    \"west\": \"refinedstorage:block/disk_manipulator/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/red.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/disk_manipulator/cutouts/red\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/disk_manipulator/right\",\n    \"north\": \"refinedstorage:block/disk_manipulator/front\",\n    \"particle\": \"refinedstorage:block/disk_manipulator/right\",\n    \"south\": \"refinedstorage:block/disk_manipulator/back\",\n    \"up\": \"refinedstorage:block/disk_manipulator/top\",\n    \"west\": \"refinedstorage:block/disk_manipulator/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/white.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/disk_manipulator/cutouts/white\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/disk_manipulator/right\",\n    \"north\": \"refinedstorage:block/disk_manipulator/front\",\n    \"particle\": \"refinedstorage:block/disk_manipulator/right\",\n    \"south\": \"refinedstorage:block/disk_manipulator/back\",\n    \"up\": \"refinedstorage:block/disk_manipulator/top\",\n    \"west\": \"refinedstorage:block/disk_manipulator/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/yellow.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/disk_manipulator/cutouts/yellow\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/disk_manipulator/right\",\n    \"north\": \"refinedstorage:block/disk_manipulator/front\",\n    \"particle\": \"refinedstorage:block/disk_manipulator/right\",\n    \"south\": \"refinedstorage:block/disk_manipulator/back\",\n    \"up\": \"refinedstorage:block/disk_manipulator/top\",\n    \"west\": \"refinedstorage:block/disk_manipulator/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/fluid_grid/black.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/fluid_grid/cutouts/black\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/fluid_grid/right\",\n    \"north\": \"refinedstorage:block/fluid_grid/front\",\n    \"particle\": \"refinedstorage:block/fluid_grid/right\",\n    \"south\": \"refinedstorage:block/fluid_grid/back\",\n    \"up\": \"refinedstorage:block/fluid_grid/top\",\n    \"west\": \"refinedstorage:block/fluid_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/fluid_grid/blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/fluid_grid/cutouts/blue\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/fluid_grid/right\",\n    \"north\": \"refinedstorage:block/fluid_grid/front\",\n    \"particle\": \"refinedstorage:block/fluid_grid/right\",\n    \"south\": \"refinedstorage:block/fluid_grid/back\",\n    \"up\": \"refinedstorage:block/fluid_grid/top\",\n    \"west\": \"refinedstorage:block/fluid_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/fluid_grid/brown.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/fluid_grid/cutouts/brown\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/fluid_grid/right\",\n    \"north\": \"refinedstorage:block/fluid_grid/front\",\n    \"particle\": \"refinedstorage:block/fluid_grid/right\",\n    \"south\": \"refinedstorage:block/fluid_grid/back\",\n    \"up\": \"refinedstorage:block/fluid_grid/top\",\n    \"west\": \"refinedstorage:block/fluid_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/fluid_grid/cyan.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/fluid_grid/cutouts/cyan\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/fluid_grid/right\",\n    \"north\": \"refinedstorage:block/fluid_grid/front\",\n    \"particle\": \"refinedstorage:block/fluid_grid/right\",\n    \"south\": \"refinedstorage:block/fluid_grid/back\",\n    \"up\": \"refinedstorage:block/fluid_grid/top\",\n    \"west\": \"refinedstorage:block/fluid_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/fluid_grid/disconnected.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout_nonemissive\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/fluid_grid/cutouts/disconnected\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/fluid_grid/right\",\n    \"north\": \"refinedstorage:block/fluid_grid/front\",\n    \"particle\": \"refinedstorage:block/fluid_grid/right\",\n    \"south\": \"refinedstorage:block/fluid_grid/back\",\n    \"up\": \"refinedstorage:block/fluid_grid/top\",\n    \"west\": \"refinedstorage:block/fluid_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/fluid_grid/gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/fluid_grid/cutouts/gray\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/fluid_grid/right\",\n    \"north\": \"refinedstorage:block/fluid_grid/front\",\n    \"particle\": \"refinedstorage:block/fluid_grid/right\",\n    \"south\": \"refinedstorage:block/fluid_grid/back\",\n    \"up\": \"refinedstorage:block/fluid_grid/top\",\n    \"west\": \"refinedstorage:block/fluid_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/fluid_grid/green.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/fluid_grid/cutouts/green\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/fluid_grid/right\",\n    \"north\": \"refinedstorage:block/fluid_grid/front\",\n    \"particle\": \"refinedstorage:block/fluid_grid/right\",\n    \"south\": \"refinedstorage:block/fluid_grid/back\",\n    \"up\": \"refinedstorage:block/fluid_grid/top\",\n    \"west\": \"refinedstorage:block/fluid_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/fluid_grid/light_blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/fluid_grid/cutouts/light_blue\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/fluid_grid/right\",\n    \"north\": \"refinedstorage:block/fluid_grid/front\",\n    \"particle\": \"refinedstorage:block/fluid_grid/right\",\n    \"south\": \"refinedstorage:block/fluid_grid/back\",\n    \"up\": \"refinedstorage:block/fluid_grid/top\",\n    \"west\": \"refinedstorage:block/fluid_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/fluid_grid/light_gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/fluid_grid/cutouts/light_gray\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/fluid_grid/right\",\n    \"north\": \"refinedstorage:block/fluid_grid/front\",\n    \"particle\": \"refinedstorage:block/fluid_grid/right\",\n    \"south\": \"refinedstorage:block/fluid_grid/back\",\n    \"up\": \"refinedstorage:block/fluid_grid/top\",\n    \"west\": \"refinedstorage:block/fluid_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/fluid_grid/lime.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/fluid_grid/cutouts/lime\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/fluid_grid/right\",\n    \"north\": \"refinedstorage:block/fluid_grid/front\",\n    \"particle\": \"refinedstorage:block/fluid_grid/right\",\n    \"south\": \"refinedstorage:block/fluid_grid/back\",\n    \"up\": \"refinedstorage:block/fluid_grid/top\",\n    \"west\": \"refinedstorage:block/fluid_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/fluid_grid/magenta.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/fluid_grid/cutouts/magenta\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/fluid_grid/right\",\n    \"north\": \"refinedstorage:block/fluid_grid/front\",\n    \"particle\": \"refinedstorage:block/fluid_grid/right\",\n    \"south\": \"refinedstorage:block/fluid_grid/back\",\n    \"up\": \"refinedstorage:block/fluid_grid/top\",\n    \"west\": \"refinedstorage:block/fluid_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/fluid_grid/orange.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/fluid_grid/cutouts/orange\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/fluid_grid/right\",\n    \"north\": \"refinedstorage:block/fluid_grid/front\",\n    \"particle\": \"refinedstorage:block/fluid_grid/right\",\n    \"south\": \"refinedstorage:block/fluid_grid/back\",\n    \"up\": \"refinedstorage:block/fluid_grid/top\",\n    \"west\": \"refinedstorage:block/fluid_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/fluid_grid/pink.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/fluid_grid/cutouts/pink\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/fluid_grid/right\",\n    \"north\": \"refinedstorage:block/fluid_grid/front\",\n    \"particle\": \"refinedstorage:block/fluid_grid/right\",\n    \"south\": \"refinedstorage:block/fluid_grid/back\",\n    \"up\": \"refinedstorage:block/fluid_grid/top\",\n    \"west\": \"refinedstorage:block/fluid_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/fluid_grid/purple.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/fluid_grid/cutouts/purple\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/fluid_grid/right\",\n    \"north\": \"refinedstorage:block/fluid_grid/front\",\n    \"particle\": \"refinedstorage:block/fluid_grid/right\",\n    \"south\": \"refinedstorage:block/fluid_grid/back\",\n    \"up\": \"refinedstorage:block/fluid_grid/top\",\n    \"west\": \"refinedstorage:block/fluid_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/fluid_grid/red.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/fluid_grid/cutouts/red\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/fluid_grid/right\",\n    \"north\": \"refinedstorage:block/fluid_grid/front\",\n    \"particle\": \"refinedstorage:block/fluid_grid/right\",\n    \"south\": \"refinedstorage:block/fluid_grid/back\",\n    \"up\": \"refinedstorage:block/fluid_grid/top\",\n    \"west\": \"refinedstorage:block/fluid_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/fluid_grid/white.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/fluid_grid/cutouts/white\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/fluid_grid/right\",\n    \"north\": \"refinedstorage:block/fluid_grid/front\",\n    \"particle\": \"refinedstorage:block/fluid_grid/right\",\n    \"south\": \"refinedstorage:block/fluid_grid/back\",\n    \"up\": \"refinedstorage:block/fluid_grid/top\",\n    \"west\": \"refinedstorage:block/fluid_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/fluid_grid/yellow.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/fluid_grid/cutouts/yellow\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/fluid_grid/right\",\n    \"north\": \"refinedstorage:block/fluid_grid/front\",\n    \"particle\": \"refinedstorage:block/fluid_grid/right\",\n    \"south\": \"refinedstorage:block/fluid_grid/back\",\n    \"up\": \"refinedstorage:block/fluid_grid/top\",\n    \"west\": \"refinedstorage:block/fluid_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/grid/black.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/grid/cutouts/black\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/grid/right\",\n    \"north\": \"refinedstorage:block/grid/front\",\n    \"particle\": \"refinedstorage:block/grid/right\",\n    \"south\": \"refinedstorage:block/grid/back\",\n    \"up\": \"refinedstorage:block/grid/top\",\n    \"west\": \"refinedstorage:block/grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/grid/blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/grid/cutouts/blue\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/grid/right\",\n    \"north\": \"refinedstorage:block/grid/front\",\n    \"particle\": \"refinedstorage:block/grid/right\",\n    \"south\": \"refinedstorage:block/grid/back\",\n    \"up\": \"refinedstorage:block/grid/top\",\n    \"west\": \"refinedstorage:block/grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/grid/brown.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/grid/cutouts/brown\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/grid/right\",\n    \"north\": \"refinedstorage:block/grid/front\",\n    \"particle\": \"refinedstorage:block/grid/right\",\n    \"south\": \"refinedstorage:block/grid/back\",\n    \"up\": \"refinedstorage:block/grid/top\",\n    \"west\": \"refinedstorage:block/grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/grid/cyan.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/grid/cutouts/cyan\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/grid/right\",\n    \"north\": \"refinedstorage:block/grid/front\",\n    \"particle\": \"refinedstorage:block/grid/right\",\n    \"south\": \"refinedstorage:block/grid/back\",\n    \"up\": \"refinedstorage:block/grid/top\",\n    \"west\": \"refinedstorage:block/grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/grid/disconnected.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout_nonemissive\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/grid/cutouts/disconnected\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/grid/right\",\n    \"north\": \"refinedstorage:block/grid/front\",\n    \"particle\": \"refinedstorage:block/grid/right\",\n    \"south\": \"refinedstorage:block/grid/back\",\n    \"up\": \"refinedstorage:block/grid/top\",\n    \"west\": \"refinedstorage:block/grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/grid/gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/grid/cutouts/gray\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/grid/right\",\n    \"north\": \"refinedstorage:block/grid/front\",\n    \"particle\": \"refinedstorage:block/grid/right\",\n    \"south\": \"refinedstorage:block/grid/back\",\n    \"up\": \"refinedstorage:block/grid/top\",\n    \"west\": \"refinedstorage:block/grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/grid/green.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/grid/cutouts/green\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/grid/right\",\n    \"north\": \"refinedstorage:block/grid/front\",\n    \"particle\": \"refinedstorage:block/grid/right\",\n    \"south\": \"refinedstorage:block/grid/back\",\n    \"up\": \"refinedstorage:block/grid/top\",\n    \"west\": \"refinedstorage:block/grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/grid/light_blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/grid/cutouts/light_blue\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/grid/right\",\n    \"north\": \"refinedstorage:block/grid/front\",\n    \"particle\": \"refinedstorage:block/grid/right\",\n    \"south\": \"refinedstorage:block/grid/back\",\n    \"up\": \"refinedstorage:block/grid/top\",\n    \"west\": \"refinedstorage:block/grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/grid/light_gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/grid/cutouts/light_gray\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/grid/right\",\n    \"north\": \"refinedstorage:block/grid/front\",\n    \"particle\": \"refinedstorage:block/grid/right\",\n    \"south\": \"refinedstorage:block/grid/back\",\n    \"up\": \"refinedstorage:block/grid/top\",\n    \"west\": \"refinedstorage:block/grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/grid/lime.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/grid/cutouts/lime\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/grid/right\",\n    \"north\": \"refinedstorage:block/grid/front\",\n    \"particle\": \"refinedstorage:block/grid/right\",\n    \"south\": \"refinedstorage:block/grid/back\",\n    \"up\": \"refinedstorage:block/grid/top\",\n    \"west\": \"refinedstorage:block/grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/grid/magenta.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/grid/cutouts/magenta\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/grid/right\",\n    \"north\": \"refinedstorage:block/grid/front\",\n    \"particle\": \"refinedstorage:block/grid/right\",\n    \"south\": \"refinedstorage:block/grid/back\",\n    \"up\": \"refinedstorage:block/grid/top\",\n    \"west\": \"refinedstorage:block/grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/grid/orange.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/grid/cutouts/orange\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/grid/right\",\n    \"north\": \"refinedstorage:block/grid/front\",\n    \"particle\": \"refinedstorage:block/grid/right\",\n    \"south\": \"refinedstorage:block/grid/back\",\n    \"up\": \"refinedstorage:block/grid/top\",\n    \"west\": \"refinedstorage:block/grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/grid/pink.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/grid/cutouts/pink\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/grid/right\",\n    \"north\": \"refinedstorage:block/grid/front\",\n    \"particle\": \"refinedstorage:block/grid/right\",\n    \"south\": \"refinedstorage:block/grid/back\",\n    \"up\": \"refinedstorage:block/grid/top\",\n    \"west\": \"refinedstorage:block/grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/grid/purple.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/grid/cutouts/purple\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/grid/right\",\n    \"north\": \"refinedstorage:block/grid/front\",\n    \"particle\": \"refinedstorage:block/grid/right\",\n    \"south\": \"refinedstorage:block/grid/back\",\n    \"up\": \"refinedstorage:block/grid/top\",\n    \"west\": \"refinedstorage:block/grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/grid/red.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/grid/cutouts/red\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/grid/right\",\n    \"north\": \"refinedstorage:block/grid/front\",\n    \"particle\": \"refinedstorage:block/grid/right\",\n    \"south\": \"refinedstorage:block/grid/back\",\n    \"up\": \"refinedstorage:block/grid/top\",\n    \"west\": \"refinedstorage:block/grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/grid/white.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/grid/cutouts/white\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/grid/right\",\n    \"north\": \"refinedstorage:block/grid/front\",\n    \"particle\": \"refinedstorage:block/grid/right\",\n    \"south\": \"refinedstorage:block/grid/back\",\n    \"up\": \"refinedstorage:block/grid/top\",\n    \"west\": \"refinedstorage:block/grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/grid/yellow.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/grid/cutouts/yellow\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/grid/right\",\n    \"north\": \"refinedstorage:block/grid/front\",\n    \"particle\": \"refinedstorage:block/grid/right\",\n    \"south\": \"refinedstorage:block/grid/back\",\n    \"up\": \"refinedstorage:block/grid/top\",\n    \"west\": \"refinedstorage:block/grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_receiver/black.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_receiver/network_receiver\",\n    \"cutout\": \"refinedstorage:block/network_receiver/cutouts/black\",\n    \"particle\": \"refinedstorage:block/network_receiver/network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_receiver/blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_receiver/network_receiver\",\n    \"cutout\": \"refinedstorage:block/network_receiver/cutouts/blue\",\n    \"particle\": \"refinedstorage:block/network_receiver/network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_receiver/brown.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_receiver/network_receiver\",\n    \"cutout\": \"refinedstorage:block/network_receiver/cutouts/brown\",\n    \"particle\": \"refinedstorage:block/network_receiver/network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_receiver/cyan.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_receiver/network_receiver\",\n    \"cutout\": \"refinedstorage:block/network_receiver/cutouts/cyan\",\n    \"particle\": \"refinedstorage:block/network_receiver/network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_receiver/disconnected.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout_nonemissive\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_receiver/network_receiver\",\n    \"cutout\": \"refinedstorage:block/network_receiver/cutouts/disconnected\",\n    \"particle\": \"refinedstorage:block/network_receiver/network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_receiver/gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_receiver/network_receiver\",\n    \"cutout\": \"refinedstorage:block/network_receiver/cutouts/gray\",\n    \"particle\": \"refinedstorage:block/network_receiver/network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_receiver/green.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_receiver/network_receiver\",\n    \"cutout\": \"refinedstorage:block/network_receiver/cutouts/green\",\n    \"particle\": \"refinedstorage:block/network_receiver/network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_receiver/light_blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_receiver/network_receiver\",\n    \"cutout\": \"refinedstorage:block/network_receiver/cutouts/light_blue\",\n    \"particle\": \"refinedstorage:block/network_receiver/network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_receiver/light_gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_receiver/network_receiver\",\n    \"cutout\": \"refinedstorage:block/network_receiver/cutouts/light_gray\",\n    \"particle\": \"refinedstorage:block/network_receiver/network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_receiver/lime.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_receiver/network_receiver\",\n    \"cutout\": \"refinedstorage:block/network_receiver/cutouts/lime\",\n    \"particle\": \"refinedstorage:block/network_receiver/network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_receiver/magenta.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_receiver/network_receiver\",\n    \"cutout\": \"refinedstorage:block/network_receiver/cutouts/magenta\",\n    \"particle\": \"refinedstorage:block/network_receiver/network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_receiver/orange.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_receiver/network_receiver\",\n    \"cutout\": \"refinedstorage:block/network_receiver/cutouts/orange\",\n    \"particle\": \"refinedstorage:block/network_receiver/network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_receiver/pink.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_receiver/network_receiver\",\n    \"cutout\": \"refinedstorage:block/network_receiver/cutouts/pink\",\n    \"particle\": \"refinedstorage:block/network_receiver/network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_receiver/purple.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_receiver/network_receiver\",\n    \"cutout\": \"refinedstorage:block/network_receiver/cutouts/purple\",\n    \"particle\": \"refinedstorage:block/network_receiver/network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_receiver/red.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_receiver/network_receiver\",\n    \"cutout\": \"refinedstorage:block/network_receiver/cutouts/red\",\n    \"particle\": \"refinedstorage:block/network_receiver/network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_receiver/white.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_receiver/network_receiver\",\n    \"cutout\": \"refinedstorage:block/network_receiver/cutouts/white\",\n    \"particle\": \"refinedstorage:block/network_receiver/network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_receiver/yellow.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_receiver/network_receiver\",\n    \"cutout\": \"refinedstorage:block/network_receiver/cutouts/yellow\",\n    \"particle\": \"refinedstorage:block/network_receiver/network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_transmitter/black.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_transmitter/network_transmitter\",\n    \"cutout\": \"refinedstorage:block/network_transmitter/cutouts/black\",\n    \"particle\": \"refinedstorage:block/network_transmitter/network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_transmitter/blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_transmitter/network_transmitter\",\n    \"cutout\": \"refinedstorage:block/network_transmitter/cutouts/blue\",\n    \"particle\": \"refinedstorage:block/network_transmitter/network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_transmitter/brown.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_transmitter/network_transmitter\",\n    \"cutout\": \"refinedstorage:block/network_transmitter/cutouts/brown\",\n    \"particle\": \"refinedstorage:block/network_transmitter/network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_transmitter/cyan.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_transmitter/network_transmitter\",\n    \"cutout\": \"refinedstorage:block/network_transmitter/cutouts/cyan\",\n    \"particle\": \"refinedstorage:block/network_transmitter/network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_transmitter/disconnected.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout_nonemissive\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_transmitter/network_transmitter\",\n    \"cutout\": \"refinedstorage:block/network_transmitter/cutouts/disconnected\",\n    \"particle\": \"refinedstorage:block/network_transmitter/network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_transmitter/gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_transmitter/network_transmitter\",\n    \"cutout\": \"refinedstorage:block/network_transmitter/cutouts/gray\",\n    \"particle\": \"refinedstorage:block/network_transmitter/network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_transmitter/green.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_transmitter/network_transmitter\",\n    \"cutout\": \"refinedstorage:block/network_transmitter/cutouts/green\",\n    \"particle\": \"refinedstorage:block/network_transmitter/network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_transmitter/light_blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_transmitter/network_transmitter\",\n    \"cutout\": \"refinedstorage:block/network_transmitter/cutouts/light_blue\",\n    \"particle\": \"refinedstorage:block/network_transmitter/network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_transmitter/light_gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_transmitter/network_transmitter\",\n    \"cutout\": \"refinedstorage:block/network_transmitter/cutouts/light_gray\",\n    \"particle\": \"refinedstorage:block/network_transmitter/network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_transmitter/lime.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_transmitter/network_transmitter\",\n    \"cutout\": \"refinedstorage:block/network_transmitter/cutouts/lime\",\n    \"particle\": \"refinedstorage:block/network_transmitter/network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_transmitter/magenta.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_transmitter/network_transmitter\",\n    \"cutout\": \"refinedstorage:block/network_transmitter/cutouts/magenta\",\n    \"particle\": \"refinedstorage:block/network_transmitter/network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_transmitter/orange.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_transmitter/network_transmitter\",\n    \"cutout\": \"refinedstorage:block/network_transmitter/cutouts/orange\",\n    \"particle\": \"refinedstorage:block/network_transmitter/network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_transmitter/pink.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_transmitter/network_transmitter\",\n    \"cutout\": \"refinedstorage:block/network_transmitter/cutouts/pink\",\n    \"particle\": \"refinedstorage:block/network_transmitter/network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_transmitter/purple.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_transmitter/network_transmitter\",\n    \"cutout\": \"refinedstorage:block/network_transmitter/cutouts/purple\",\n    \"particle\": \"refinedstorage:block/network_transmitter/network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_transmitter/red.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_transmitter/network_transmitter\",\n    \"cutout\": \"refinedstorage:block/network_transmitter/cutouts/red\",\n    \"particle\": \"refinedstorage:block/network_transmitter/network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_transmitter/white.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_transmitter/network_transmitter\",\n    \"cutout\": \"refinedstorage:block/network_transmitter/cutouts/white\",\n    \"particle\": \"refinedstorage:block/network_transmitter/network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/network_transmitter/yellow.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/network_transmitter/network_transmitter\",\n    \"cutout\": \"refinedstorage:block/network_transmitter/cutouts/yellow\",\n    \"particle\": \"refinedstorage:block/network_transmitter/network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/pattern_grid/black.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/pattern_grid/cutouts/black\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/pattern_grid/right\",\n    \"north\": \"refinedstorage:block/pattern_grid/front\",\n    \"particle\": \"refinedstorage:block/pattern_grid/right\",\n    \"south\": \"refinedstorage:block/pattern_grid/back\",\n    \"up\": \"refinedstorage:block/pattern_grid/top\",\n    \"west\": \"refinedstorage:block/pattern_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/pattern_grid/blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/pattern_grid/cutouts/blue\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/pattern_grid/right\",\n    \"north\": \"refinedstorage:block/pattern_grid/front\",\n    \"particle\": \"refinedstorage:block/pattern_grid/right\",\n    \"south\": \"refinedstorage:block/pattern_grid/back\",\n    \"up\": \"refinedstorage:block/pattern_grid/top\",\n    \"west\": \"refinedstorage:block/pattern_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/pattern_grid/brown.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/pattern_grid/cutouts/brown\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/pattern_grid/right\",\n    \"north\": \"refinedstorage:block/pattern_grid/front\",\n    \"particle\": \"refinedstorage:block/pattern_grid/right\",\n    \"south\": \"refinedstorage:block/pattern_grid/back\",\n    \"up\": \"refinedstorage:block/pattern_grid/top\",\n    \"west\": \"refinedstorage:block/pattern_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/pattern_grid/cyan.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/pattern_grid/cutouts/cyan\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/pattern_grid/right\",\n    \"north\": \"refinedstorage:block/pattern_grid/front\",\n    \"particle\": \"refinedstorage:block/pattern_grid/right\",\n    \"south\": \"refinedstorage:block/pattern_grid/back\",\n    \"up\": \"refinedstorage:block/pattern_grid/top\",\n    \"west\": \"refinedstorage:block/pattern_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/pattern_grid/disconnected.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout_nonemissive\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/pattern_grid/cutouts/disconnected\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/pattern_grid/right\",\n    \"north\": \"refinedstorage:block/pattern_grid/front\",\n    \"particle\": \"refinedstorage:block/pattern_grid/right\",\n    \"south\": \"refinedstorage:block/pattern_grid/back\",\n    \"up\": \"refinedstorage:block/pattern_grid/top\",\n    \"west\": \"refinedstorage:block/pattern_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/pattern_grid/gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/pattern_grid/cutouts/gray\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/pattern_grid/right\",\n    \"north\": \"refinedstorage:block/pattern_grid/front\",\n    \"particle\": \"refinedstorage:block/pattern_grid/right\",\n    \"south\": \"refinedstorage:block/pattern_grid/back\",\n    \"up\": \"refinedstorage:block/pattern_grid/top\",\n    \"west\": \"refinedstorage:block/pattern_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/pattern_grid/green.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/pattern_grid/cutouts/green\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/pattern_grid/right\",\n    \"north\": \"refinedstorage:block/pattern_grid/front\",\n    \"particle\": \"refinedstorage:block/pattern_grid/right\",\n    \"south\": \"refinedstorage:block/pattern_grid/back\",\n    \"up\": \"refinedstorage:block/pattern_grid/top\",\n    \"west\": \"refinedstorage:block/pattern_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/pattern_grid/light_blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/pattern_grid/cutouts/light_blue\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/pattern_grid/right\",\n    \"north\": \"refinedstorage:block/pattern_grid/front\",\n    \"particle\": \"refinedstorage:block/pattern_grid/right\",\n    \"south\": \"refinedstorage:block/pattern_grid/back\",\n    \"up\": \"refinedstorage:block/pattern_grid/top\",\n    \"west\": \"refinedstorage:block/pattern_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/pattern_grid/light_gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/pattern_grid/cutouts/light_gray\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/pattern_grid/right\",\n    \"north\": \"refinedstorage:block/pattern_grid/front\",\n    \"particle\": \"refinedstorage:block/pattern_grid/right\",\n    \"south\": \"refinedstorage:block/pattern_grid/back\",\n    \"up\": \"refinedstorage:block/pattern_grid/top\",\n    \"west\": \"refinedstorage:block/pattern_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/pattern_grid/lime.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/pattern_grid/cutouts/lime\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/pattern_grid/right\",\n    \"north\": \"refinedstorage:block/pattern_grid/front\",\n    \"particle\": \"refinedstorage:block/pattern_grid/right\",\n    \"south\": \"refinedstorage:block/pattern_grid/back\",\n    \"up\": \"refinedstorage:block/pattern_grid/top\",\n    \"west\": \"refinedstorage:block/pattern_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/pattern_grid/magenta.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/pattern_grid/cutouts/magenta\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/pattern_grid/right\",\n    \"north\": \"refinedstorage:block/pattern_grid/front\",\n    \"particle\": \"refinedstorage:block/pattern_grid/right\",\n    \"south\": \"refinedstorage:block/pattern_grid/back\",\n    \"up\": \"refinedstorage:block/pattern_grid/top\",\n    \"west\": \"refinedstorage:block/pattern_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/pattern_grid/orange.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/pattern_grid/cutouts/orange\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/pattern_grid/right\",\n    \"north\": \"refinedstorage:block/pattern_grid/front\",\n    \"particle\": \"refinedstorage:block/pattern_grid/right\",\n    \"south\": \"refinedstorage:block/pattern_grid/back\",\n    \"up\": \"refinedstorage:block/pattern_grid/top\",\n    \"west\": \"refinedstorage:block/pattern_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/pattern_grid/pink.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/pattern_grid/cutouts/pink\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/pattern_grid/right\",\n    \"north\": \"refinedstorage:block/pattern_grid/front\",\n    \"particle\": \"refinedstorage:block/pattern_grid/right\",\n    \"south\": \"refinedstorage:block/pattern_grid/back\",\n    \"up\": \"refinedstorage:block/pattern_grid/top\",\n    \"west\": \"refinedstorage:block/pattern_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/pattern_grid/purple.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/pattern_grid/cutouts/purple\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/pattern_grid/right\",\n    \"north\": \"refinedstorage:block/pattern_grid/front\",\n    \"particle\": \"refinedstorage:block/pattern_grid/right\",\n    \"south\": \"refinedstorage:block/pattern_grid/back\",\n    \"up\": \"refinedstorage:block/pattern_grid/top\",\n    \"west\": \"refinedstorage:block/pattern_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/pattern_grid/red.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/pattern_grid/cutouts/red\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/pattern_grid/right\",\n    \"north\": \"refinedstorage:block/pattern_grid/front\",\n    \"particle\": \"refinedstorage:block/pattern_grid/right\",\n    \"south\": \"refinedstorage:block/pattern_grid/back\",\n    \"up\": \"refinedstorage:block/pattern_grid/top\",\n    \"west\": \"refinedstorage:block/pattern_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/pattern_grid/white.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/pattern_grid/cutouts/white\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/pattern_grid/right\",\n    \"north\": \"refinedstorage:block/pattern_grid/front\",\n    \"particle\": \"refinedstorage:block/pattern_grid/right\",\n    \"south\": \"refinedstorage:block/pattern_grid/back\",\n    \"up\": \"refinedstorage:block/pattern_grid/top\",\n    \"west\": \"refinedstorage:block/pattern_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/pattern_grid/yellow.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_north_cutout\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/pattern_grid/cutouts/yellow\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/pattern_grid/right\",\n    \"north\": \"refinedstorage:block/pattern_grid/front\",\n    \"particle\": \"refinedstorage:block/pattern_grid/right\",\n    \"south\": \"refinedstorage:block/pattern_grid/back\",\n    \"up\": \"refinedstorage:block/pattern_grid/top\",\n    \"west\": \"refinedstorage:block/pattern_grid/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/relay/black.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/relay/relay\",\n    \"cutout\": \"refinedstorage:block/relay/cutouts/black\",\n    \"particle\": \"refinedstorage:block/relay/relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/relay/blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/relay/relay\",\n    \"cutout\": \"refinedstorage:block/relay/cutouts/blue\",\n    \"particle\": \"refinedstorage:block/relay/relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/relay/brown.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/relay/relay\",\n    \"cutout\": \"refinedstorage:block/relay/cutouts/brown\",\n    \"particle\": \"refinedstorage:block/relay/relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/relay/cyan.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/relay/relay\",\n    \"cutout\": \"refinedstorage:block/relay/cutouts/cyan\",\n    \"particle\": \"refinedstorage:block/relay/relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/relay/disconnected.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout_nonemissive\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/relay/relay\",\n    \"cutout\": \"refinedstorage:block/relay/cutouts/disconnected\",\n    \"particle\": \"refinedstorage:block/relay/relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/relay/gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/relay/relay\",\n    \"cutout\": \"refinedstorage:block/relay/cutouts/gray\",\n    \"particle\": \"refinedstorage:block/relay/relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/relay/green.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/relay/relay\",\n    \"cutout\": \"refinedstorage:block/relay/cutouts/green\",\n    \"particle\": \"refinedstorage:block/relay/relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/relay/light_blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/relay/relay\",\n    \"cutout\": \"refinedstorage:block/relay/cutouts/light_blue\",\n    \"particle\": \"refinedstorage:block/relay/relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/relay/light_gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/relay/relay\",\n    \"cutout\": \"refinedstorage:block/relay/cutouts/light_gray\",\n    \"particle\": \"refinedstorage:block/relay/relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/relay/lime.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/relay/relay\",\n    \"cutout\": \"refinedstorage:block/relay/cutouts/lime\",\n    \"particle\": \"refinedstorage:block/relay/relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/relay/magenta.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/relay/relay\",\n    \"cutout\": \"refinedstorage:block/relay/cutouts/magenta\",\n    \"particle\": \"refinedstorage:block/relay/relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/relay/orange.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/relay/relay\",\n    \"cutout\": \"refinedstorage:block/relay/cutouts/orange\",\n    \"particle\": \"refinedstorage:block/relay/relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/relay/pink.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/relay/relay\",\n    \"cutout\": \"refinedstorage:block/relay/cutouts/pink\",\n    \"particle\": \"refinedstorage:block/relay/relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/relay/purple.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/relay/relay\",\n    \"cutout\": \"refinedstorage:block/relay/cutouts/purple\",\n    \"particle\": \"refinedstorage:block/relay/relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/relay/red.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/relay/relay\",\n    \"cutout\": \"refinedstorage:block/relay/cutouts/red\",\n    \"particle\": \"refinedstorage:block/relay/relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/relay/white.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/relay/relay\",\n    \"cutout\": \"refinedstorage:block/relay/cutouts/white\",\n    \"particle\": \"refinedstorage:block/relay/relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/relay/yellow.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_all_cutout\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/relay/relay\",\n    \"cutout\": \"refinedstorage:block/relay/cutouts/yellow\",\n    \"particle\": \"refinedstorage:block/relay/relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/security_manager/black.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/security_manager/cutouts/right_black\",\n    \"cutout_north\": \"refinedstorage:block/security_manager/cutouts/front_black\",\n    \"cutout_south\": \"refinedstorage:block/security_manager/cutouts/back_black\",\n    \"cutout_up\": \"refinedstorage:block/security_manager/cutouts/top_black\",\n    \"cutout_west\": \"refinedstorage:block/security_manager/cutouts/left_black\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/security_manager/right\",\n    \"north\": \"refinedstorage:block/security_manager/front\",\n    \"particle\": \"refinedstorage:block/security_manager/front\",\n    \"south\": \"refinedstorage:block/security_manager/back\",\n    \"up\": \"refinedstorage:block/security_manager/top\",\n    \"west\": \"refinedstorage:block/security_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/security_manager/blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/security_manager/cutouts/right_blue\",\n    \"cutout_north\": \"refinedstorage:block/security_manager/cutouts/front_blue\",\n    \"cutout_south\": \"refinedstorage:block/security_manager/cutouts/back_blue\",\n    \"cutout_up\": \"refinedstorage:block/security_manager/cutouts/top_blue\",\n    \"cutout_west\": \"refinedstorage:block/security_manager/cutouts/left_blue\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/security_manager/right\",\n    \"north\": \"refinedstorage:block/security_manager/front\",\n    \"particle\": \"refinedstorage:block/security_manager/front\",\n    \"south\": \"refinedstorage:block/security_manager/back\",\n    \"up\": \"refinedstorage:block/security_manager/top\",\n    \"west\": \"refinedstorage:block/security_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/security_manager/brown.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/security_manager/cutouts/right_brown\",\n    \"cutout_north\": \"refinedstorage:block/security_manager/cutouts/front_brown\",\n    \"cutout_south\": \"refinedstorage:block/security_manager/cutouts/back_brown\",\n    \"cutout_up\": \"refinedstorage:block/security_manager/cutouts/top_brown\",\n    \"cutout_west\": \"refinedstorage:block/security_manager/cutouts/left_brown\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/security_manager/right\",\n    \"north\": \"refinedstorage:block/security_manager/front\",\n    \"particle\": \"refinedstorage:block/security_manager/front\",\n    \"south\": \"refinedstorage:block/security_manager/back\",\n    \"up\": \"refinedstorage:block/security_manager/top\",\n    \"west\": \"refinedstorage:block/security_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/security_manager/cyan.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/security_manager/cutouts/right_cyan\",\n    \"cutout_north\": \"refinedstorage:block/security_manager/cutouts/front_cyan\",\n    \"cutout_south\": \"refinedstorage:block/security_manager/cutouts/back_cyan\",\n    \"cutout_up\": \"refinedstorage:block/security_manager/cutouts/top_cyan\",\n    \"cutout_west\": \"refinedstorage:block/security_manager/cutouts/left_cyan\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/security_manager/right\",\n    \"north\": \"refinedstorage:block/security_manager/front\",\n    \"particle\": \"refinedstorage:block/security_manager/front\",\n    \"south\": \"refinedstorage:block/security_manager/back\",\n    \"up\": \"refinedstorage:block/security_manager/top\",\n    \"west\": \"refinedstorage:block/security_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/security_manager/disconnected.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout_nonemissive\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/security_manager/cutouts/right_disconnected\",\n    \"cutout_north\": \"refinedstorage:block/security_manager/cutouts/front_disconnected\",\n    \"cutout_south\": \"refinedstorage:block/security_manager/cutouts/back_disconnected\",\n    \"cutout_up\": \"refinedstorage:block/security_manager/cutouts/top_disconnected\",\n    \"cutout_west\": \"refinedstorage:block/security_manager/cutouts/left_disconnected\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/security_manager/right\",\n    \"north\": \"refinedstorage:block/security_manager/front\",\n    \"particle\": \"refinedstorage:block/security_manager/front\",\n    \"south\": \"refinedstorage:block/security_manager/back\",\n    \"up\": \"refinedstorage:block/security_manager/top\",\n    \"west\": \"refinedstorage:block/security_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/security_manager/gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/security_manager/cutouts/right_gray\",\n    \"cutout_north\": \"refinedstorage:block/security_manager/cutouts/front_gray\",\n    \"cutout_south\": \"refinedstorage:block/security_manager/cutouts/back_gray\",\n    \"cutout_up\": \"refinedstorage:block/security_manager/cutouts/top_gray\",\n    \"cutout_west\": \"refinedstorage:block/security_manager/cutouts/left_gray\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/security_manager/right\",\n    \"north\": \"refinedstorage:block/security_manager/front\",\n    \"particle\": \"refinedstorage:block/security_manager/front\",\n    \"south\": \"refinedstorage:block/security_manager/back\",\n    \"up\": \"refinedstorage:block/security_manager/top\",\n    \"west\": \"refinedstorage:block/security_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/security_manager/green.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/security_manager/cutouts/right_green\",\n    \"cutout_north\": \"refinedstorage:block/security_manager/cutouts/front_green\",\n    \"cutout_south\": \"refinedstorage:block/security_manager/cutouts/back_green\",\n    \"cutout_up\": \"refinedstorage:block/security_manager/cutouts/top_green\",\n    \"cutout_west\": \"refinedstorage:block/security_manager/cutouts/left_green\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/security_manager/right\",\n    \"north\": \"refinedstorage:block/security_manager/front\",\n    \"particle\": \"refinedstorage:block/security_manager/front\",\n    \"south\": \"refinedstorage:block/security_manager/back\",\n    \"up\": \"refinedstorage:block/security_manager/top\",\n    \"west\": \"refinedstorage:block/security_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/security_manager/light_blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/security_manager/cutouts/right_light_blue\",\n    \"cutout_north\": \"refinedstorage:block/security_manager/cutouts/front_light_blue\",\n    \"cutout_south\": \"refinedstorage:block/security_manager/cutouts/back_light_blue\",\n    \"cutout_up\": \"refinedstorage:block/security_manager/cutouts/top_light_blue\",\n    \"cutout_west\": \"refinedstorage:block/security_manager/cutouts/left_light_blue\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/security_manager/right\",\n    \"north\": \"refinedstorage:block/security_manager/front\",\n    \"particle\": \"refinedstorage:block/security_manager/front\",\n    \"south\": \"refinedstorage:block/security_manager/back\",\n    \"up\": \"refinedstorage:block/security_manager/top\",\n    \"west\": \"refinedstorage:block/security_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/security_manager/light_gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/security_manager/cutouts/right_light_gray\",\n    \"cutout_north\": \"refinedstorage:block/security_manager/cutouts/front_light_gray\",\n    \"cutout_south\": \"refinedstorage:block/security_manager/cutouts/back_light_gray\",\n    \"cutout_up\": \"refinedstorage:block/security_manager/cutouts/top_light_gray\",\n    \"cutout_west\": \"refinedstorage:block/security_manager/cutouts/left_light_gray\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/security_manager/right\",\n    \"north\": \"refinedstorage:block/security_manager/front\",\n    \"particle\": \"refinedstorage:block/security_manager/front\",\n    \"south\": \"refinedstorage:block/security_manager/back\",\n    \"up\": \"refinedstorage:block/security_manager/top\",\n    \"west\": \"refinedstorage:block/security_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/security_manager/lime.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/security_manager/cutouts/right_lime\",\n    \"cutout_north\": \"refinedstorage:block/security_manager/cutouts/front_lime\",\n    \"cutout_south\": \"refinedstorage:block/security_manager/cutouts/back_lime\",\n    \"cutout_up\": \"refinedstorage:block/security_manager/cutouts/top_lime\",\n    \"cutout_west\": \"refinedstorage:block/security_manager/cutouts/left_lime\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/security_manager/right\",\n    \"north\": \"refinedstorage:block/security_manager/front\",\n    \"particle\": \"refinedstorage:block/security_manager/front\",\n    \"south\": \"refinedstorage:block/security_manager/back\",\n    \"up\": \"refinedstorage:block/security_manager/top\",\n    \"west\": \"refinedstorage:block/security_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/security_manager/magenta.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/security_manager/cutouts/right_magenta\",\n    \"cutout_north\": \"refinedstorage:block/security_manager/cutouts/front_magenta\",\n    \"cutout_south\": \"refinedstorage:block/security_manager/cutouts/back_magenta\",\n    \"cutout_up\": \"refinedstorage:block/security_manager/cutouts/top_magenta\",\n    \"cutout_west\": \"refinedstorage:block/security_manager/cutouts/left_magenta\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/security_manager/right\",\n    \"north\": \"refinedstorage:block/security_manager/front\",\n    \"particle\": \"refinedstorage:block/security_manager/front\",\n    \"south\": \"refinedstorage:block/security_manager/back\",\n    \"up\": \"refinedstorage:block/security_manager/top\",\n    \"west\": \"refinedstorage:block/security_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/security_manager/orange.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/security_manager/cutouts/right_orange\",\n    \"cutout_north\": \"refinedstorage:block/security_manager/cutouts/front_orange\",\n    \"cutout_south\": \"refinedstorage:block/security_manager/cutouts/back_orange\",\n    \"cutout_up\": \"refinedstorage:block/security_manager/cutouts/top_orange\",\n    \"cutout_west\": \"refinedstorage:block/security_manager/cutouts/left_orange\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/security_manager/right\",\n    \"north\": \"refinedstorage:block/security_manager/front\",\n    \"particle\": \"refinedstorage:block/security_manager/front\",\n    \"south\": \"refinedstorage:block/security_manager/back\",\n    \"up\": \"refinedstorage:block/security_manager/top\",\n    \"west\": \"refinedstorage:block/security_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/security_manager/pink.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/security_manager/cutouts/right_pink\",\n    \"cutout_north\": \"refinedstorage:block/security_manager/cutouts/front_pink\",\n    \"cutout_south\": \"refinedstorage:block/security_manager/cutouts/back_pink\",\n    \"cutout_up\": \"refinedstorage:block/security_manager/cutouts/top_pink\",\n    \"cutout_west\": \"refinedstorage:block/security_manager/cutouts/left_pink\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/security_manager/right\",\n    \"north\": \"refinedstorage:block/security_manager/front\",\n    \"particle\": \"refinedstorage:block/security_manager/front\",\n    \"south\": \"refinedstorage:block/security_manager/back\",\n    \"up\": \"refinedstorage:block/security_manager/top\",\n    \"west\": \"refinedstorage:block/security_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/security_manager/purple.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/security_manager/cutouts/right_purple\",\n    \"cutout_north\": \"refinedstorage:block/security_manager/cutouts/front_purple\",\n    \"cutout_south\": \"refinedstorage:block/security_manager/cutouts/back_purple\",\n    \"cutout_up\": \"refinedstorage:block/security_manager/cutouts/top_purple\",\n    \"cutout_west\": \"refinedstorage:block/security_manager/cutouts/left_purple\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/security_manager/right\",\n    \"north\": \"refinedstorage:block/security_manager/front\",\n    \"particle\": \"refinedstorage:block/security_manager/front\",\n    \"south\": \"refinedstorage:block/security_manager/back\",\n    \"up\": \"refinedstorage:block/security_manager/top\",\n    \"west\": \"refinedstorage:block/security_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/security_manager/red.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/security_manager/cutouts/right_red\",\n    \"cutout_north\": \"refinedstorage:block/security_manager/cutouts/front_red\",\n    \"cutout_south\": \"refinedstorage:block/security_manager/cutouts/back_red\",\n    \"cutout_up\": \"refinedstorage:block/security_manager/cutouts/top_red\",\n    \"cutout_west\": \"refinedstorage:block/security_manager/cutouts/left_red\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/security_manager/right\",\n    \"north\": \"refinedstorage:block/security_manager/front\",\n    \"particle\": \"refinedstorage:block/security_manager/front\",\n    \"south\": \"refinedstorage:block/security_manager/back\",\n    \"up\": \"refinedstorage:block/security_manager/top\",\n    \"west\": \"refinedstorage:block/security_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/security_manager/white.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/security_manager/cutouts/right_white\",\n    \"cutout_north\": \"refinedstorage:block/security_manager/cutouts/front_white\",\n    \"cutout_south\": \"refinedstorage:block/security_manager/cutouts/back_white\",\n    \"cutout_up\": \"refinedstorage:block/security_manager/cutouts/top_white\",\n    \"cutout_west\": \"refinedstorage:block/security_manager/cutouts/left_white\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/security_manager/right\",\n    \"north\": \"refinedstorage:block/security_manager/front\",\n    \"particle\": \"refinedstorage:block/security_manager/front\",\n    \"south\": \"refinedstorage:block/security_manager/back\",\n    \"up\": \"refinedstorage:block/security_manager/top\",\n    \"west\": \"refinedstorage:block/security_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/security_manager/yellow.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/cube_cutout\",\n  \"textures\": {\n    \"cutout_down\": \"refinedstorage:block/bottom\",\n    \"cutout_east\": \"refinedstorage:block/security_manager/cutouts/right_yellow\",\n    \"cutout_north\": \"refinedstorage:block/security_manager/cutouts/front_yellow\",\n    \"cutout_south\": \"refinedstorage:block/security_manager/cutouts/back_yellow\",\n    \"cutout_up\": \"refinedstorage:block/security_manager/cutouts/top_yellow\",\n    \"cutout_west\": \"refinedstorage:block/security_manager/cutouts/left_yellow\",\n    \"down\": \"refinedstorage:block/bottom\",\n    \"east\": \"refinedstorage:block/security_manager/right\",\n    \"north\": \"refinedstorage:block/security_manager/front\",\n    \"particle\": \"refinedstorage:block/security_manager/front\",\n    \"south\": \"refinedstorage:block/security_manager/back\",\n    \"up\": \"refinedstorage:block/security_manager/top\",\n    \"west\": \"refinedstorage:block/security_manager/left\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/black.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/wireless_transmitter/cutouts/black\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/wireless_transmitter/cutouts/blue\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/brown.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/wireless_transmitter/cutouts/brown\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/cyan.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/wireless_transmitter/cutouts/cyan\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/disconnected.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter_nonemissive\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/wireless_transmitter/cutouts/disconnected\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/wireless_transmitter/cutouts/gray\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/green.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/wireless_transmitter/cutouts/green\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/light_blue.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/wireless_transmitter/cutouts/light_blue\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/light_gray.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/wireless_transmitter/cutouts/light_gray\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/lime.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/wireless_transmitter/cutouts/lime\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/magenta.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/wireless_transmitter/cutouts/magenta\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/orange.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/wireless_transmitter/cutouts/orange\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/pink.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/wireless_transmitter/cutouts/pink\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/purple.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/wireless_transmitter/cutouts/purple\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/red.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/wireless_transmitter/cutouts/red\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/white.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/wireless_transmitter/cutouts/white\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/yellow.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter\",\n  \"textures\": {\n    \"cutout\": \"refinedstorage:block/wireless_transmitter/cutouts/yellow\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/black_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/black\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/black_crafter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter/black\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/black_crafter_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter_manager/black\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/black_crafting_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_grid/black\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/black_crafting_monitor.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_monitor/black\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/black_creative_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/black\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/black_detector.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector/black\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/black_disk_manipulator.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/disk_manipulator/black\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/black_fluid_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/fluid_grid/black\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/black_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/grid/black\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/black_network_receiver.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_receiver/black\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/black_network_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_transmitter/black\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/black_pattern_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/pattern_grid/black\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/black_relay.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/relay/black\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/black_security_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/security_manager/black\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/black_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter/black\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/blue_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/blue\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/blue_crafter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter/blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/blue_crafter_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter_manager/blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/blue_crafting_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_grid/blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/blue_crafting_monitor.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_monitor/blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/blue_creative_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/blue\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/blue_detector.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector/blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/blue_disk_manipulator.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/disk_manipulator/blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/blue_fluid_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/fluid_grid/blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/blue_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/grid/blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/blue_network_receiver.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_receiver/blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/blue_network_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_transmitter/blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/blue_pattern_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/pattern_grid/blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/blue_relay.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/relay/blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/blue_security_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/security_manager/blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/blue_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter/blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/brown_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/brown\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/brown_crafter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter/brown\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/brown_crafter_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter_manager/brown\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/brown_crafting_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_grid/brown\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/brown_crafting_monitor.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_monitor/brown\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/brown_creative_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/brown\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/brown_detector.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector/brown\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/brown_disk_manipulator.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/disk_manipulator/brown\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/brown_fluid_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/fluid_grid/brown\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/brown_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/grid/brown\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/brown_network_receiver.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_receiver/brown\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/brown_network_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_transmitter/brown\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/brown_pattern_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/pattern_grid/brown\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/brown_relay.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/relay/brown\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/brown_security_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/security_manager/brown\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/brown_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter/brown\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/light_blue\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/crafter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter/light_blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/crafter_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter_manager/light_blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/crafting_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_grid/light_blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/crafting_monitor.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_monitor/light_blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/creative_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/light_blue\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/cyan_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/cyan\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/cyan_crafter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter/cyan\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/cyan_crafter_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter_manager/cyan\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/cyan_crafting_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_grid/cyan\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/cyan_crafting_monitor.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_monitor/cyan\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/cyan_creative_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/cyan\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/cyan_detector.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector/cyan\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/cyan_disk_manipulator.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/disk_manipulator/cyan\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/cyan_fluid_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/fluid_grid/cyan\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/cyan_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/grid/cyan\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/cyan_network_receiver.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_receiver/cyan\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/cyan_network_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_transmitter/cyan\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/cyan_pattern_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/pattern_grid/cyan\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/cyan_relay.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/relay/cyan\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/cyan_security_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/security_manager/cyan\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/cyan_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter/cyan\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/detector.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector/light_blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/disk_manipulator.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/disk_manipulator/light_blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/fluid_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/fluid_grid/light_blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/gray_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/gray\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/gray_crafter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter/gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/gray_crafter_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter_manager/gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/gray_crafting_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_grid/gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/gray_crafting_monitor.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_monitor/gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/gray_creative_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/gray\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/gray_detector.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector/gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/gray_disk_manipulator.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/disk_manipulator/gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/gray_fluid_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/fluid_grid/gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/gray_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/grid/gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/gray_network_receiver.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_receiver/gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/gray_network_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_transmitter/gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/gray_pattern_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/pattern_grid/gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/gray_relay.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/relay/gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/gray_security_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/security_manager/gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/gray_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter/gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/green_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/green\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/green_crafter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter/green\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/green_crafter_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter_manager/green\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/green_crafting_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_grid/green\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/green_crafting_monitor.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_monitor/green\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/green_creative_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/green\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/green_detector.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector/green\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/green_disk_manipulator.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/disk_manipulator/green\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/green_fluid_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/fluid_grid/green\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/green_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/grid/green\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/green_network_receiver.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_receiver/green\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/green_network_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_transmitter/green\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/green_pattern_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/pattern_grid/green\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/green_relay.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/relay/green\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/green_security_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/security_manager/green\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/green_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter/green\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/grid/light_blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/light_gray_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/light_gray\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/light_gray_crafter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter/light_gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/light_gray_crafter_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter_manager/light_gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/light_gray_crafting_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_grid/light_gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/light_gray_crafting_monitor.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_monitor/light_gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/light_gray_creative_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/light_gray\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/light_gray_detector.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector/light_gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/light_gray_disk_manipulator.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/disk_manipulator/light_gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/light_gray_fluid_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/fluid_grid/light_gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/light_gray_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/grid/light_gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/light_gray_network_receiver.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_receiver/light_gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/light_gray_network_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_transmitter/light_gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/light_gray_pattern_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/pattern_grid/light_gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/light_gray_relay.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/relay/light_gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/light_gray_security_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/security_manager/light_gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/light_gray_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter/light_gray\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/lime_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/lime\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/lime_crafter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter/lime\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/lime_crafter_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter_manager/lime\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/lime_crafting_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_grid/lime\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/lime_crafting_monitor.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_monitor/lime\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/lime_creative_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/lime\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/lime_detector.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector/lime\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/lime_disk_manipulator.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/disk_manipulator/lime\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/lime_fluid_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/fluid_grid/lime\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/lime_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/grid/lime\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/lime_network_receiver.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_receiver/lime\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/lime_network_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_transmitter/lime\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/lime_pattern_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/pattern_grid/lime\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/lime_relay.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/relay/lime\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/lime_security_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/security_manager/lime\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/lime_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter/lime\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/magenta_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/magenta\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/magenta_crafter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter/magenta\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/magenta_crafter_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter_manager/magenta\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/magenta_crafting_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_grid/magenta\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/magenta_crafting_monitor.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_monitor/magenta\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/magenta_creative_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/magenta\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/magenta_detector.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector/magenta\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/magenta_disk_manipulator.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/disk_manipulator/magenta\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/magenta_fluid_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/fluid_grid/magenta\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/magenta_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/grid/magenta\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/magenta_network_receiver.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_receiver/magenta\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/magenta_network_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_transmitter/magenta\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/magenta_pattern_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/pattern_grid/magenta\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/magenta_relay.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/relay/magenta\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/magenta_security_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/security_manager/magenta\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/magenta_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter/magenta\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/network_receiver.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_receiver/light_blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/network_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_transmitter/light_blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/orange_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/orange\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/orange_crafter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter/orange\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/orange_crafter_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter_manager/orange\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/orange_crafting_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_grid/orange\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/orange_crafting_monitor.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_monitor/orange\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/orange_creative_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/orange\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/orange_detector.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector/orange\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/orange_disk_manipulator.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/disk_manipulator/orange\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/orange_fluid_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/fluid_grid/orange\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/orange_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/grid/orange\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/orange_network_receiver.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_receiver/orange\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/orange_network_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_transmitter/orange\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/orange_pattern_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/pattern_grid/orange\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/orange_relay.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/relay/orange\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/orange_security_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/security_manager/orange\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/orange_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter/orange\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/pattern_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/pattern_grid/light_blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/pink_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/pink\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/pink_crafter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter/pink\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/pink_crafter_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter_manager/pink\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/pink_crafting_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_grid/pink\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/pink_crafting_monitor.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_monitor/pink\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/pink_creative_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/pink\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/pink_detector.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector/pink\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/pink_disk_manipulator.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/disk_manipulator/pink\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/pink_fluid_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/fluid_grid/pink\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/pink_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/grid/pink\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/pink_network_receiver.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_receiver/pink\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/pink_network_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_transmitter/pink\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/pink_pattern_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/pattern_grid/pink\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/pink_relay.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/relay/pink\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/pink_security_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/security_manager/pink\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/pink_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter/pink\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/purple_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/purple\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/purple_crafter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter/purple\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/purple_crafter_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter_manager/purple\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/purple_crafting_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_grid/purple\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/purple_crafting_monitor.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_monitor/purple\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/purple_creative_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/purple\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/purple_detector.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector/purple\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/purple_disk_manipulator.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/disk_manipulator/purple\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/purple_fluid_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/fluid_grid/purple\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/purple_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/grid/purple\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/purple_network_receiver.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_receiver/purple\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/purple_network_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_transmitter/purple\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/purple_pattern_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/pattern_grid/purple\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/purple_relay.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/relay/purple\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/purple_security_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/security_manager/purple\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/purple_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter/purple\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/red_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/red\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/red_crafter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter/red\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/red_crafter_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter_manager/red\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/red_crafting_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_grid/red\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/red_crafting_monitor.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_monitor/red\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/red_creative_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/red\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/red_detector.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector/red\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/red_disk_manipulator.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/disk_manipulator/red\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/red_fluid_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/fluid_grid/red\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/red_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/grid/red\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/red_network_receiver.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_receiver/red\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/red_network_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_transmitter/red\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/red_pattern_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/pattern_grid/red\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/red_relay.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/relay/red\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/red_security_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/security_manager/red\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/red_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter/red\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/relay.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/relay/light_blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/security_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/security_manager/light_blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/white_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/white\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/white_crafter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter/white\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/white_crafter_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter_manager/white\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/white_crafting_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_grid/white\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/white_crafting_monitor.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_monitor/white\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/white_creative_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/white\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/white_detector.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector/white\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/white_disk_manipulator.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/disk_manipulator/white\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/white_fluid_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/fluid_grid/white\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/white_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/grid/white\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/white_network_receiver.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_receiver/white\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/white_network_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_transmitter/white\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/white_pattern_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/pattern_grid/white\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/white_relay.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/relay/white\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/white_security_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/security_manager/white\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/white_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter/white\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/wireless_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter/light_blue\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/yellow_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/yellow\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/yellow_crafter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter/yellow\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/yellow_crafter_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafter_manager/yellow\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/yellow_crafting_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_grid/yellow\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/yellow_crafting_monitor.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/crafting_monitor/yellow\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/yellow_creative_controller.json",
    "content": "{\n  \"overrides\": [\n    {\n      \"model\": \"refinedstorage:block/controller/off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 0.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_off\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 1.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/nearly_on\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 2.0\n      }\n    },\n    {\n      \"model\": \"refinedstorage:block/controller/yellow\",\n      \"predicate\": {\n        \"refinedstorage:energy_type\": 3.0\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/yellow_detector.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/detector/yellow\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/yellow_disk_manipulator.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/disk_manipulator/yellow\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/yellow_fluid_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/fluid_grid/yellow\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/yellow_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/grid/yellow\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/yellow_network_receiver.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_receiver/yellow\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/yellow_network_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/network_transmitter/yellow\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/yellow_pattern_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/pattern_grid/yellow\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/yellow_relay.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/relay/yellow\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/yellow_security_manager.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/security_manager/yellow\"\n}"
  },
  {
    "path": "src/generated/resources/assets/refinedstorage/models/item/yellow_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/wireless_transmitter/yellow\"\n}"
  },
  {
    "path": "src/generated/resources/data/forge/tags/blocks/relocation_not_supported.json",
    "content": "{\n  \"values\": [\n    \"#refinedstorage:detector\",\n    \"#refinedstorage:disk_manipulator\",\n    \"#refinedstorage:network_transmitter\",\n    \"#refinedstorage:fluid_grid\",\n    \"#refinedstorage:controller\",\n    \"#refinedstorage:crafting_monitor\",\n    \"#refinedstorage:pattern_grid\",\n    \"#refinedstorage:wireless_transmitter\",\n    \"#refinedstorage:relay\",\n    \"#refinedstorage:network_receiver\",\n    \"#refinedstorage:grid\",\n    \"#refinedstorage:crafter\",\n    \"#refinedstorage:crafter_manager\",\n    \"#refinedstorage:crafting_grid\",\n    \"#refinedstorage:security_manager\",\n    \"#refinedstorage:creative_controller\",\n    \"refinedstorage:1k_storage_block\",\n    \"refinedstorage:4k_storage_block\",\n    \"refinedstorage:16k_storage_block\",\n    \"refinedstorage:64k_storage_block\",\n    \"refinedstorage:creative_storage_block\",\n    \"refinedstorage:64k_fluid_storage_block\",\n    \"refinedstorage:256k_fluid_storage_block\",\n    \"refinedstorage:1024k_fluid_storage_block\",\n    \"refinedstorage:4096k_fluid_storage_block\",\n    \"refinedstorage:creative_fluid_storage_block\",\n    \"refinedstorage:importer\",\n    \"refinedstorage:exporter\",\n    \"refinedstorage:external_storage\",\n    \"refinedstorage:disk_drive\",\n    \"refinedstorage:interface\",\n    \"refinedstorage:fluid_interface\",\n    \"refinedstorage:storage_monitor\",\n    \"refinedstorage:constructor\",\n    \"refinedstorage:destructor\",\n    \"refinedstorage:portable_grid\",\n    \"refinedstorage:creative_portable_grid\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/packingtape/tags/block_entity_type/blacklist/problematic.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:controller\",\n    \"refinedstorage:creative_controller\",\n    \"refinedstorage:detector\",\n    \"refinedstorage:disk_drive\",\n    \"refinedstorage:exporter\",\n    \"refinedstorage:external_storage\",\n    \"refinedstorage:grid\",\n    \"refinedstorage:crafting_grid\",\n    \"refinedstorage:pattern_grid\",\n    \"refinedstorage:fluid_grid\",\n    \"refinedstorage:importer\",\n    \"refinedstorage:network_transmitter\",\n    \"refinedstorage:network_receiver\",\n    \"refinedstorage:relay\",\n    \"refinedstorage:cable\",\n    \"refinedstorage:1k_storage_block\",\n    \"refinedstorage:4k_storage_block\",\n    \"refinedstorage:16k_storage_block\",\n    \"refinedstorage:64k_storage_block\",\n    \"refinedstorage:creative_storage_block\",\n    \"refinedstorage:64k_fluid_storage_block\",\n    \"refinedstorage:256k_fluid_storage_block\",\n    \"refinedstorage:1024k_fluid_storage_block\",\n    \"refinedstorage:4096k_fluid_storage_block\",\n    \"refinedstorage:creative_fluid_storage_block\",\n    \"refinedstorage:security_manager\",\n    \"refinedstorage:interface\",\n    \"refinedstorage:fluid_interface\",\n    \"refinedstorage:wireless_transmitter\",\n    \"refinedstorage:storage_monitor\",\n    \"refinedstorage:constructor\",\n    \"refinedstorage:destructor\",\n    \"refinedstorage:disk_manipulator\",\n    \"refinedstorage:portable_grid\",\n    \"refinedstorage:creative_portable_grid\",\n    \"refinedstorage:crafter\",\n    \"refinedstorage:crafter_manager\",\n    \"refinedstorage:crafting_monitor\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_controller.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/black_controller\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/black_controller\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_crafter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/black_crafter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/black_crafter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_crafter_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/black_crafter_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/black_crafter_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/black_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/black_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_crafting_monitor.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/black_crafting_monitor\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/black_crafting_monitor\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_detector.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/black_detector\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/black_detector\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_disk_manipulator.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/black_disk_manipulator\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/black_disk_manipulator\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/black_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/black_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/black_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/black_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_network_receiver.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/black_network_receiver\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/black_network_receiver\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_network_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/black_network_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/black_network_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/black_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/black_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_relay.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/black_relay\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/black_relay\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_security_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/black_security_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/black_security_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/black_wireless_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/black_wireless_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_controller.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/blue_controller\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/blue_controller\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_crafter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/blue_crafter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/blue_crafter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_crafter_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/blue_crafter_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/blue_crafter_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/blue_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/blue_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_crafting_monitor.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/blue_crafting_monitor\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/blue_crafting_monitor\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_detector.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/blue_detector\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/blue_detector\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_disk_manipulator.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/blue_disk_manipulator\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/blue_disk_manipulator\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/blue_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/blue_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/blue_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/blue_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_network_receiver.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/blue_network_receiver\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/blue_network_receiver\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_network_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/blue_network_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/blue_network_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/blue_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/blue_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_relay.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/blue_relay\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/blue_relay\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_security_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/blue_security_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/blue_security_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/blue_wireless_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/blue_wireless_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_controller.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/brown_controller\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/brown_controller\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_crafter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/brown_crafter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/brown_crafter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_crafter_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/brown_crafter_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/brown_crafter_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/brown_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/brown_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_crafting_monitor.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/brown_crafting_monitor\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/brown_crafting_monitor\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_detector.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/brown_detector\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/brown_detector\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_disk_manipulator.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/brown_disk_manipulator\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/brown_disk_manipulator\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/brown_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/brown_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/brown_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/brown_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_network_receiver.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/brown_network_receiver\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/brown_network_receiver\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_network_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/brown_network_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/brown_network_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/brown_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/brown_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_relay.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/brown_relay\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/brown_relay\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_security_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/brown_security_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/brown_security_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/brown_wireless_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/brown_wireless_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/controller.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/controller\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/controller\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/crafter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/crafter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/crafter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/crafter_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/crafter_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/crafter_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/crafting_monitor.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/crafting_monitor\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/crafting_monitor\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_controller.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/cyan_controller\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/cyan_controller\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_crafter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/cyan_crafter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/cyan_crafter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_crafter_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/cyan_crafter_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/cyan_crafter_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/cyan_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/cyan_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_crafting_monitor.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/cyan_crafting_monitor\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/cyan_crafting_monitor\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_detector.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/cyan_detector\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/cyan_detector\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_disk_manipulator.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/cyan_disk_manipulator\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/cyan_disk_manipulator\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/cyan_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/cyan_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/cyan_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/cyan_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_network_receiver.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/cyan_network_receiver\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/cyan_network_receiver\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_network_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/cyan_network_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/cyan_network_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/cyan_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/cyan_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_relay.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/cyan_relay\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/cyan_relay\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_security_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/cyan_security_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/cyan_security_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/cyan_wireless_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/cyan_wireless_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/detector.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/detector\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/detector\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/disk_manipulator.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/disk_manipulator\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/disk_manipulator\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_controller.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/gray_controller\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/gray_controller\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_crafter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/gray_crafter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/gray_crafter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_crafter_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/gray_crafter_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/gray_crafter_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/gray_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/gray_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_crafting_monitor.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/gray_crafting_monitor\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/gray_crafting_monitor\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_detector.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/gray_detector\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/gray_detector\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_disk_manipulator.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/gray_disk_manipulator\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/gray_disk_manipulator\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/gray_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/gray_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/gray_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/gray_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_network_receiver.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/gray_network_receiver\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/gray_network_receiver\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_network_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/gray_network_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/gray_network_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/gray_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/gray_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_relay.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/gray_relay\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/gray_relay\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_security_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/gray_security_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/gray_security_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/gray_wireless_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/gray_wireless_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_controller.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/green_controller\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/green_controller\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_crafter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/green_crafter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/green_crafter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_crafter_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/green_crafter_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/green_crafter_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/green_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/green_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_crafting_monitor.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/green_crafting_monitor\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/green_crafting_monitor\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_detector.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/green_detector\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/green_detector\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_disk_manipulator.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/green_disk_manipulator\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/green_disk_manipulator\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/green_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/green_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/green_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/green_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_network_receiver.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/green_network_receiver\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/green_network_receiver\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_network_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/green_network_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/green_network_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/green_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/green_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_relay.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/green_relay\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/green_relay\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_security_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/green_security_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/green_security_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/green_wireless_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/green_wireless_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_controller.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/light_gray_controller\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/light_gray_controller\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_crafter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/light_gray_crafter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/light_gray_crafter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_crafter_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/light_gray_crafter_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/light_gray_crafter_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/light_gray_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/light_gray_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_crafting_monitor.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/light_gray_crafting_monitor\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/light_gray_crafting_monitor\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_detector.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/light_gray_detector\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/light_gray_detector\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_disk_manipulator.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/light_gray_disk_manipulator\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/light_gray_disk_manipulator\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/light_gray_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/light_gray_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/light_gray_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/light_gray_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_network_receiver.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/light_gray_network_receiver\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/light_gray_network_receiver\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_network_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/light_gray_network_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/light_gray_network_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/light_gray_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/light_gray_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_relay.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/light_gray_relay\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/light_gray_relay\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_security_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/light_gray_security_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/light_gray_security_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/light_gray_wireless_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/light_gray_wireless_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_controller.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/lime_controller\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/lime_controller\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_crafter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/lime_crafter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/lime_crafter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_crafter_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/lime_crafter_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/lime_crafter_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/lime_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/lime_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_crafting_monitor.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/lime_crafting_monitor\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/lime_crafting_monitor\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_detector.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/lime_detector\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/lime_detector\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_disk_manipulator.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/lime_disk_manipulator\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/lime_disk_manipulator\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/lime_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/lime_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/lime_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/lime_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_network_receiver.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/lime_network_receiver\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/lime_network_receiver\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_network_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/lime_network_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/lime_network_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/lime_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/lime_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_relay.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/lime_relay\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/lime_relay\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_security_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/lime_security_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/lime_security_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/lime_wireless_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/lime_wireless_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_controller.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/magenta_controller\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/magenta_controller\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_crafter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/magenta_crafter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/magenta_crafter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_crafter_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/magenta_crafter_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/magenta_crafter_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/magenta_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/magenta_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_crafting_monitor.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/magenta_crafting_monitor\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/magenta_crafting_monitor\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_detector.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/magenta_detector\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/magenta_detector\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_disk_manipulator.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/magenta_disk_manipulator\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/magenta_disk_manipulator\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/magenta_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/magenta_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/magenta_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/magenta_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_network_receiver.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/magenta_network_receiver\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/magenta_network_receiver\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_network_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/magenta_network_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/magenta_network_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/magenta_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/magenta_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_relay.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/magenta_relay\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/magenta_relay\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_security_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/magenta_security_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/magenta_security_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/magenta_wireless_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/magenta_wireless_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/network_receiver.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/network_receiver\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/network_receiver\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/network_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/network_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/network_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_controller.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/orange_controller\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/orange_controller\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_crafter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/orange_crafter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/orange_crafter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_crafter_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/orange_crafter_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/orange_crafter_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/orange_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/orange_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_crafting_monitor.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/orange_crafting_monitor\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/orange_crafting_monitor\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_detector.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/orange_detector\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/orange_detector\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_disk_manipulator.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/orange_disk_manipulator\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/orange_disk_manipulator\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/orange_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/orange_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/orange_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/orange_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_network_receiver.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/orange_network_receiver\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/orange_network_receiver\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_network_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/orange_network_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/orange_network_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/orange_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/orange_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_relay.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/orange_relay\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/orange_relay\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_security_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/orange_security_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/orange_security_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/orange_wireless_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/orange_wireless_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_controller.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/pink_controller\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/pink_controller\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_crafter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/pink_crafter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/pink_crafter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_crafter_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/pink_crafter_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/pink_crafter_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/pink_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/pink_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_crafting_monitor.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/pink_crafting_monitor\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/pink_crafting_monitor\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_detector.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/pink_detector\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/pink_detector\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_disk_manipulator.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/pink_disk_manipulator\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/pink_disk_manipulator\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/pink_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/pink_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/pink_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/pink_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_network_receiver.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/pink_network_receiver\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/pink_network_receiver\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_network_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/pink_network_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/pink_network_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/pink_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/pink_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_relay.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/pink_relay\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/pink_relay\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_security_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/pink_security_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/pink_security_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/pink_wireless_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/pink_wireless_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_controller.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/purple_controller\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/purple_controller\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_crafter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/purple_crafter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/purple_crafter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_crafter_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/purple_crafter_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/purple_crafter_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/purple_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/purple_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_crafting_monitor.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/purple_crafting_monitor\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/purple_crafting_monitor\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_detector.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/purple_detector\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/purple_detector\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_disk_manipulator.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/purple_disk_manipulator\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/purple_disk_manipulator\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/purple_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/purple_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/purple_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/purple_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_network_receiver.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/purple_network_receiver\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/purple_network_receiver\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_network_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/purple_network_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/purple_network_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/purple_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/purple_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_relay.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/purple_relay\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/purple_relay\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_security_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/purple_security_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/purple_security_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/purple_wireless_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/purple_wireless_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_controller.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/red_controller\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/red_controller\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_crafter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/red_crafter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/red_crafter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_crafter_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/red_crafter_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/red_crafter_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/red_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/red_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_crafting_monitor.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/red_crafting_monitor\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/red_crafting_monitor\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_detector.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/red_detector\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/red_detector\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_disk_manipulator.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/red_disk_manipulator\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/red_disk_manipulator\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/red_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/red_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/red_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/red_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_network_receiver.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/red_network_receiver\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/red_network_receiver\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_network_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/red_network_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/red_network_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/red_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/red_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_relay.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/red_relay\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/red_relay\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_security_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/red_security_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/red_security_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/red_wireless_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/red_wireless_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/relay.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/relay\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/relay\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/security_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/security_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/security_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_controller.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/white_controller\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/white_controller\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_crafter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/white_crafter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/white_crafter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_crafter_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/white_crafter_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/white_crafter_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/white_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/white_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_crafting_monitor.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/white_crafting_monitor\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/white_crafting_monitor\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_detector.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/white_detector\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/white_detector\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_disk_manipulator.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/white_disk_manipulator\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/white_disk_manipulator\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/white_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/white_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/white_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/white_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_network_receiver.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/white_network_receiver\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/white_network_receiver\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_network_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/white_network_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/white_network_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/white_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/white_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_relay.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/white_relay\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/white_relay\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_security_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/white_security_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/white_security_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/white_wireless_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/white_wireless_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/wireless_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/wireless_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/wireless_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_controller.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/yellow_controller\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/yellow_controller\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_crafter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/yellow_crafter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/yellow_crafter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_crafter_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/yellow_crafter_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/yellow_crafter_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/yellow_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/yellow_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_crafting_monitor.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/yellow_crafting_monitor\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/yellow_crafting_monitor\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_detector.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/yellow_detector\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/yellow_detector\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_disk_manipulator.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/yellow_disk_manipulator\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/yellow_disk_manipulator\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/yellow_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/yellow_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/yellow_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/yellow_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_network_receiver.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/yellow_network_receiver\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/yellow_network_receiver\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_network_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/yellow_network_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/yellow_network_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/yellow_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/yellow_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_relay.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/yellow_relay\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/yellow_relay\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_security_manager.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/yellow_security_manager\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/yellow_security_manager\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_wireless_transmitter.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:coloring_recipes/yellow_wireless_transmitter\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:controller\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:controller\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:coloring_recipes/yellow_wireless_transmitter\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/black_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:crafting_grid/black_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:crafting_grid/black_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/blue_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:crafting_grid/blue_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:crafting_grid/blue_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/brown_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:crafting_grid/brown_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:crafting_grid/brown_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:crafting_grid/crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:crafting_grid/crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/cyan_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:crafting_grid/cyan_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:crafting_grid/cyan_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/gray_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:crafting_grid/gray_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:crafting_grid/gray_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/green_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:crafting_grid/green_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:crafting_grid/green_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/light_gray_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:crafting_grid/light_gray_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:crafting_grid/light_gray_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/lime_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:crafting_grid/lime_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:crafting_grid/lime_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/magenta_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:crafting_grid/magenta_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:crafting_grid/magenta_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/orange_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:crafting_grid/orange_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:crafting_grid/orange_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/pink_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:crafting_grid/pink_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:crafting_grid/pink_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/purple_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:crafting_grid/purple_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:crafting_grid/purple_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/red_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:crafting_grid/red_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:crafting_grid/red_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/white_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:crafting_grid/white_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:crafting_grid/white_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/yellow_crafting_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:crafting_grid/yellow_crafting_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:crafting_grid/yellow_crafting_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/black_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:fluid_grid/black_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:fluid_grid/black_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/blue_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:fluid_grid/blue_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:fluid_grid/blue_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/brown_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:fluid_grid/brown_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:fluid_grid/brown_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/cyan_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:fluid_grid/cyan_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:fluid_grid/cyan_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:fluid_grid/fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:fluid_grid/fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/gray_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:fluid_grid/gray_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:fluid_grid/gray_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/green_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:fluid_grid/green_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:fluid_grid/green_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/light_gray_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:fluid_grid/light_gray_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:fluid_grid/light_gray_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/lime_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:fluid_grid/lime_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:fluid_grid/lime_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/magenta_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:fluid_grid/magenta_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:fluid_grid/magenta_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/orange_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:fluid_grid/orange_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:fluid_grid/orange_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/pink_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:fluid_grid/pink_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:fluid_grid/pink_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/purple_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:fluid_grid/purple_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:fluid_grid/purple_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/red_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:fluid_grid/red_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:fluid_grid/red_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/white_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:fluid_grid/white_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:fluid_grid/white_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/yellow_fluid_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:fluid_grid/yellow_fluid_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:fluid_grid/yellow_fluid_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/black_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:pattern_grid/black_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:pattern_grid/black_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/blue_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:pattern_grid/blue_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:pattern_grid/blue_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/brown_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:pattern_grid/brown_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:pattern_grid/brown_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/cyan_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:pattern_grid/cyan_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:pattern_grid/cyan_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/gray_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:pattern_grid/gray_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:pattern_grid/gray_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/green_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:pattern_grid/green_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:pattern_grid/green_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/light_gray_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:pattern_grid/light_gray_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:pattern_grid/light_gray_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/lime_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:pattern_grid/lime_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:pattern_grid/lime_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/magenta_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:pattern_grid/magenta_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:pattern_grid/magenta_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/orange_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:pattern_grid/orange_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:pattern_grid/orange_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:pattern_grid/pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:pattern_grid/pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/pink_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:pattern_grid/pink_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:pattern_grid/pink_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/purple_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:pattern_grid/purple_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:pattern_grid/purple_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/red_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:pattern_grid/red_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:pattern_grid/red_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/white_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:pattern_grid/white_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:pattern_grid/white_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/yellow_pattern_grid.json",
    "content": "{\n  \"parent\": \"minecraft:recipes/root\",\n  \"criteria\": {\n    \"has_the_recipe\": {\n      \"conditions\": {\n        \"recipe\": \"refinedstorage:pattern_grid/yellow_pattern_grid\"\n      },\n      \"trigger\": \"minecraft:recipe_unlocked\"\n    },\n    \"refinedstorage:grid\": {\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      },\n      \"trigger\": \"minecraft:inventory_changed\"\n    }\n  },\n  \"requirements\": [\n    [\n      \"has_the_recipe\",\n      \"refinedstorage:grid\"\n    ]\n  ],\n  \"rewards\": {\n    \"recipes\": [\n      \"refinedstorage:pattern_grid/yellow_pattern_grid\"\n    ]\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/black_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:controller\"\n            }\n          ],\n          \"name\": \"refinedstorage:black_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/black_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/black_crafter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:crafter\"\n            }\n          ],\n          \"name\": \"refinedstorage:black_crafter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/black_crafter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/black_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:black_crafter_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/black_crafter_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/black_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:black_crafting_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/black_crafting_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/black_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:black_crafting_monitor\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/black_crafting_monitor\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/black_creative_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:black_creative_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/black_creative_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/black_detector.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:black_detector\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/black_detector\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/black_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:black_disk_manipulator\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/black_disk_manipulator\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/black_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:black_fluid_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/black_fluid_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/black_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:black_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/black_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/black_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:black_network_receiver\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/black_network_receiver\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/black_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:black_network_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/black_network_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/black_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:black_pattern_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/black_pattern_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/black_relay.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:black_relay\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/black_relay\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/black_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:black_security_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/black_security_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/black_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:black_wireless_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/black_wireless_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:controller\"\n            }\n          ],\n          \"name\": \"refinedstorage:blue_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/blue_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_crafter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:crafter\"\n            }\n          ],\n          \"name\": \"refinedstorage:blue_crafter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/blue_crafter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:blue_crafter_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/blue_crafter_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:blue_crafting_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/blue_crafting_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:blue_crafting_monitor\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/blue_crafting_monitor\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_creative_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:blue_creative_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/blue_creative_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_detector.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:blue_detector\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/blue_detector\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:blue_disk_manipulator\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/blue_disk_manipulator\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:blue_fluid_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/blue_fluid_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:blue_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/blue_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:blue_network_receiver\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/blue_network_receiver\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:blue_network_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/blue_network_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:blue_pattern_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/blue_pattern_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_relay.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:blue_relay\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/blue_relay\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:blue_security_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/blue_security_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:blue_wireless_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/blue_wireless_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:controller\"\n            }\n          ],\n          \"name\": \"refinedstorage:brown_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/brown_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_crafter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:crafter\"\n            }\n          ],\n          \"name\": \"refinedstorage:brown_crafter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/brown_crafter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:brown_crafter_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/brown_crafter_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:brown_crafting_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/brown_crafting_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:brown_crafting_monitor\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/brown_crafting_monitor\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_creative_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:brown_creative_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/brown_creative_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_detector.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:brown_detector\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/brown_detector\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:brown_disk_manipulator\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/brown_disk_manipulator\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:brown_fluid_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/brown_fluid_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:brown_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/brown_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:brown_network_receiver\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/brown_network_receiver\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:brown_network_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/brown_network_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:brown_pattern_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/brown_pattern_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_relay.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:brown_relay\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/brown_relay\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:brown_security_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/brown_security_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:brown_wireless_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/brown_wireless_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:controller\"\n            }\n          ],\n          \"name\": \"refinedstorage:controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/crafter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:crafter\"\n            }\n          ],\n          \"name\": \"refinedstorage:crafter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/crafter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:crafter_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/crafter_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:crafting_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/crafting_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:crafting_monitor\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/crafting_monitor\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/creative_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:creative_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/creative_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:controller\"\n            }\n          ],\n          \"name\": \"refinedstorage:cyan_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/cyan_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_crafter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:crafter\"\n            }\n          ],\n          \"name\": \"refinedstorage:cyan_crafter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/cyan_crafter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:cyan_crafter_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/cyan_crafter_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:cyan_crafting_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/cyan_crafting_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:cyan_crafting_monitor\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/cyan_crafting_monitor\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_creative_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:cyan_creative_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/cyan_creative_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_detector.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:cyan_detector\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/cyan_detector\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:cyan_disk_manipulator\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/cyan_disk_manipulator\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:cyan_fluid_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/cyan_fluid_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:cyan_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/cyan_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:cyan_network_receiver\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/cyan_network_receiver\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:cyan_network_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/cyan_network_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:cyan_pattern_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/cyan_pattern_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_relay.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:cyan_relay\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/cyan_relay\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:cyan_security_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/cyan_security_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:cyan_wireless_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/cyan_wireless_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/detector.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:detector\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/detector\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:disk_manipulator\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/disk_manipulator\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:fluid_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/fluid_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:controller\"\n            }\n          ],\n          \"name\": \"refinedstorage:gray_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/gray_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_crafter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:crafter\"\n            }\n          ],\n          \"name\": \"refinedstorage:gray_crafter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/gray_crafter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:gray_crafter_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/gray_crafter_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:gray_crafting_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/gray_crafting_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:gray_crafting_monitor\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/gray_crafting_monitor\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_creative_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:gray_creative_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/gray_creative_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_detector.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:gray_detector\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/gray_detector\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:gray_disk_manipulator\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/gray_disk_manipulator\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:gray_fluid_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/gray_fluid_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:gray_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/gray_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:gray_network_receiver\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/gray_network_receiver\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:gray_network_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/gray_network_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:gray_pattern_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/gray_pattern_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_relay.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:gray_relay\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/gray_relay\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:gray_security_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/gray_security_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:gray_wireless_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/gray_wireless_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/green_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:controller\"\n            }\n          ],\n          \"name\": \"refinedstorage:green_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/green_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/green_crafter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:crafter\"\n            }\n          ],\n          \"name\": \"refinedstorage:green_crafter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/green_crafter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/green_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:green_crafter_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/green_crafter_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/green_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:green_crafting_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/green_crafting_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/green_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:green_crafting_monitor\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/green_crafting_monitor\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/green_creative_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:green_creative_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/green_creative_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/green_detector.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:green_detector\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/green_detector\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/green_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:green_disk_manipulator\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/green_disk_manipulator\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/green_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:green_fluid_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/green_fluid_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/green_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:green_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/green_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/green_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:green_network_receiver\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/green_network_receiver\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/green_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:green_network_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/green_network_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/green_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:green_pattern_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/green_pattern_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/green_relay.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:green_relay\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/green_relay\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/green_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:green_security_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/green_security_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/green_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:green_wireless_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/green_wireless_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:controller\"\n            }\n          ],\n          \"name\": \"refinedstorage:light_gray_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/light_gray_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_crafter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:crafter\"\n            }\n          ],\n          \"name\": \"refinedstorage:light_gray_crafter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/light_gray_crafter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:light_gray_crafter_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/light_gray_crafter_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:light_gray_crafting_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/light_gray_crafting_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:light_gray_crafting_monitor\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/light_gray_crafting_monitor\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_creative_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:light_gray_creative_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/light_gray_creative_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_detector.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:light_gray_detector\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/light_gray_detector\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:light_gray_disk_manipulator\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/light_gray_disk_manipulator\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:light_gray_fluid_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/light_gray_fluid_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:light_gray_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/light_gray_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:light_gray_network_receiver\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/light_gray_network_receiver\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:light_gray_network_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/light_gray_network_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:light_gray_pattern_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/light_gray_pattern_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_relay.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:light_gray_relay\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/light_gray_relay\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:light_gray_security_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/light_gray_security_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:light_gray_wireless_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/light_gray_wireless_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:controller\"\n            }\n          ],\n          \"name\": \"refinedstorage:lime_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/lime_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_crafter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:crafter\"\n            }\n          ],\n          \"name\": \"refinedstorage:lime_crafter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/lime_crafter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:lime_crafter_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/lime_crafter_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:lime_crafting_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/lime_crafting_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:lime_crafting_monitor\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/lime_crafting_monitor\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_creative_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:lime_creative_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/lime_creative_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_detector.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:lime_detector\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/lime_detector\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:lime_disk_manipulator\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/lime_disk_manipulator\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:lime_fluid_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/lime_fluid_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:lime_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/lime_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:lime_network_receiver\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/lime_network_receiver\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:lime_network_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/lime_network_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:lime_pattern_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/lime_pattern_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_relay.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:lime_relay\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/lime_relay\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:lime_security_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/lime_security_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:lime_wireless_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/lime_wireless_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:controller\"\n            }\n          ],\n          \"name\": \"refinedstorage:magenta_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/magenta_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_crafter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:crafter\"\n            }\n          ],\n          \"name\": \"refinedstorage:magenta_crafter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/magenta_crafter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:magenta_crafter_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/magenta_crafter_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:magenta_crafting_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/magenta_crafting_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:magenta_crafting_monitor\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/magenta_crafting_monitor\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_creative_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:magenta_creative_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/magenta_creative_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_detector.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:magenta_detector\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/magenta_detector\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:magenta_disk_manipulator\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/magenta_disk_manipulator\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:magenta_fluid_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/magenta_fluid_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:magenta_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/magenta_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:magenta_network_receiver\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/magenta_network_receiver\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:magenta_network_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/magenta_network_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:magenta_pattern_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/magenta_pattern_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_relay.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:magenta_relay\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/magenta_relay\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:magenta_security_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/magenta_security_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:magenta_wireless_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/magenta_wireless_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:network_receiver\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/network_receiver\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:network_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/network_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:controller\"\n            }\n          ],\n          \"name\": \"refinedstorage:orange_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/orange_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_crafter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:crafter\"\n            }\n          ],\n          \"name\": \"refinedstorage:orange_crafter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/orange_crafter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:orange_crafter_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/orange_crafter_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:orange_crafting_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/orange_crafting_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:orange_crafting_monitor\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/orange_crafting_monitor\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_creative_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:orange_creative_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/orange_creative_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_detector.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:orange_detector\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/orange_detector\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:orange_disk_manipulator\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/orange_disk_manipulator\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:orange_fluid_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/orange_fluid_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:orange_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/orange_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:orange_network_receiver\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/orange_network_receiver\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:orange_network_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/orange_network_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:orange_pattern_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/orange_pattern_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_relay.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:orange_relay\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/orange_relay\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:orange_security_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/orange_security_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:orange_wireless_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/orange_wireless_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:pattern_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/pattern_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:controller\"\n            }\n          ],\n          \"name\": \"refinedstorage:pink_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/pink_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_crafter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:crafter\"\n            }\n          ],\n          \"name\": \"refinedstorage:pink_crafter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/pink_crafter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:pink_crafter_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/pink_crafter_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:pink_crafting_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/pink_crafting_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:pink_crafting_monitor\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/pink_crafting_monitor\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_creative_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:pink_creative_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/pink_creative_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_detector.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:pink_detector\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/pink_detector\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:pink_disk_manipulator\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/pink_disk_manipulator\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:pink_fluid_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/pink_fluid_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:pink_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/pink_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:pink_network_receiver\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/pink_network_receiver\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:pink_network_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/pink_network_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:pink_pattern_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/pink_pattern_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_relay.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:pink_relay\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/pink_relay\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:pink_security_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/pink_security_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:pink_wireless_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/pink_wireless_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:controller\"\n            }\n          ],\n          \"name\": \"refinedstorage:purple_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/purple_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_crafter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:crafter\"\n            }\n          ],\n          \"name\": \"refinedstorage:purple_crafter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/purple_crafter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:purple_crafter_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/purple_crafter_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:purple_crafting_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/purple_crafting_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:purple_crafting_monitor\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/purple_crafting_monitor\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_creative_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:purple_creative_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/purple_creative_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_detector.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:purple_detector\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/purple_detector\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:purple_disk_manipulator\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/purple_disk_manipulator\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:purple_fluid_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/purple_fluid_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:purple_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/purple_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:purple_network_receiver\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/purple_network_receiver\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:purple_network_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/purple_network_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:purple_pattern_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/purple_pattern_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_relay.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:purple_relay\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/purple_relay\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:purple_security_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/purple_security_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:purple_wireless_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/purple_wireless_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/red_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:controller\"\n            }\n          ],\n          \"name\": \"refinedstorage:red_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/red_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/red_crafter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:crafter\"\n            }\n          ],\n          \"name\": \"refinedstorage:red_crafter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/red_crafter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/red_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:red_crafter_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/red_crafter_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/red_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:red_crafting_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/red_crafting_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/red_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:red_crafting_monitor\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/red_crafting_monitor\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/red_creative_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:red_creative_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/red_creative_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/red_detector.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:red_detector\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/red_detector\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/red_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:red_disk_manipulator\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/red_disk_manipulator\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/red_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:red_fluid_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/red_fluid_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/red_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:red_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/red_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/red_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:red_network_receiver\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/red_network_receiver\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/red_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:red_network_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/red_network_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/red_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:red_pattern_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/red_pattern_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/red_relay.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:red_relay\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/red_relay\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/red_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:red_security_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/red_security_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/red_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:red_wireless_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/red_wireless_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/relay.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:relay\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/relay\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/security_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:security_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/security_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/white_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:controller\"\n            }\n          ],\n          \"name\": \"refinedstorage:white_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/white_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/white_crafter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:crafter\"\n            }\n          ],\n          \"name\": \"refinedstorage:white_crafter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/white_crafter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/white_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:white_crafter_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/white_crafter_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/white_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:white_crafting_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/white_crafting_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/white_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:white_crafting_monitor\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/white_crafting_monitor\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/white_creative_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:white_creative_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/white_creative_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/white_detector.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:white_detector\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/white_detector\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/white_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:white_disk_manipulator\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/white_disk_manipulator\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/white_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:white_fluid_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/white_fluid_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/white_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:white_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/white_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/white_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:white_network_receiver\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/white_network_receiver\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/white_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:white_network_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/white_network_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/white_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:white_pattern_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/white_pattern_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/white_relay.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:white_relay\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/white_relay\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/white_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:white_security_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/white_security_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/white_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:white_wireless_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/white_wireless_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:wireless_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/wireless_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:controller\"\n            }\n          ],\n          \"name\": \"refinedstorage:yellow_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/yellow_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_crafter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:crafter\"\n            }\n          ],\n          \"name\": \"refinedstorage:yellow_crafter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/yellow_crafter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:yellow_crafter_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/yellow_crafter_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:yellow_crafting_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/yellow_crafting_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:yellow_crafting_monitor\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/yellow_crafting_monitor\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_creative_controller.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:yellow_creative_controller\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/yellow_creative_controller\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_detector.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:yellow_detector\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/yellow_detector\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:yellow_disk_manipulator\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/yellow_disk_manipulator\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:yellow_fluid_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/yellow_fluid_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:yellow_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/yellow_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:yellow_network_receiver\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/yellow_network_receiver\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:yellow_network_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/yellow_network_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:yellow_pattern_grid\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/yellow_pattern_grid\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_relay.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:yellow_relay\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/yellow_relay\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:yellow_security_manager\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/yellow_security_manager\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"bonus_rolls\": 0.0,\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ],\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:yellow_wireless_transmitter\"\n        }\n      ],\n      \"rolls\": 1.0\n    }\n  ],\n  \"random_sequence\": \"refinedstorage:blocks/yellow_wireless_transmitter\"\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_controller.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:controller\"\n    },\n    {\n      \"tag\": \"forge:dyes/black\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:black_controller\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_crafter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter\"\n    },\n    {\n      \"tag\": \"forge:dyes/black\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:black_crafter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/black\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:black_crafter_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/black\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:black_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_monitor\"\n    },\n    {\n      \"tag\": \"forge:dyes/black\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:black_crafting_monitor\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_detector.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:detector\"\n    },\n    {\n      \"tag\": \"forge:dyes/black\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:black_detector\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:disk_manipulator\"\n    },\n    {\n      \"tag\": \"forge:dyes/black\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:black_disk_manipulator\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:fluid_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/black\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:black_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/black\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:black_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_receiver\"\n    },\n    {\n      \"tag\": \"forge:dyes/black\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:black_network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/black\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:black_network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:pattern_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/black\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:black_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_relay.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:relay\"\n    },\n    {\n      \"tag\": \"forge:dyes/black\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:black_relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:security_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/black\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:black_security_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:wireless_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/black\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:black_wireless_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_controller.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:controller\"\n    },\n    {\n      \"tag\": \"forge:dyes/blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:blue_controller\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_crafter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter\"\n    },\n    {\n      \"tag\": \"forge:dyes/blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:blue_crafter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:blue_crafter_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:blue_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_monitor\"\n    },\n    {\n      \"tag\": \"forge:dyes/blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:blue_crafting_monitor\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_detector.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:detector\"\n    },\n    {\n      \"tag\": \"forge:dyes/blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:blue_detector\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:disk_manipulator\"\n    },\n    {\n      \"tag\": \"forge:dyes/blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:blue_disk_manipulator\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:fluid_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:blue_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:blue_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_receiver\"\n    },\n    {\n      \"tag\": \"forge:dyes/blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:blue_network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:blue_network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:pattern_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:blue_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_relay.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:relay\"\n    },\n    {\n      \"tag\": \"forge:dyes/blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:blue_relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:security_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:blue_security_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:wireless_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:blue_wireless_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_controller.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:controller\"\n    },\n    {\n      \"tag\": \"forge:dyes/brown\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:brown_controller\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_crafter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter\"\n    },\n    {\n      \"tag\": \"forge:dyes/brown\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:brown_crafter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/brown\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:brown_crafter_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/brown\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:brown_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_monitor\"\n    },\n    {\n      \"tag\": \"forge:dyes/brown\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:brown_crafting_monitor\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_detector.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:detector\"\n    },\n    {\n      \"tag\": \"forge:dyes/brown\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:brown_detector\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:disk_manipulator\"\n    },\n    {\n      \"tag\": \"forge:dyes/brown\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:brown_disk_manipulator\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:fluid_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/brown\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:brown_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/brown\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:brown_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_receiver\"\n    },\n    {\n      \"tag\": \"forge:dyes/brown\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:brown_network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/brown\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:brown_network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:pattern_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/brown\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:brown_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_relay.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:relay\"\n    },\n    {\n      \"tag\": \"forge:dyes/brown\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:brown_relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:security_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/brown\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:brown_security_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:wireless_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/brown\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:brown_wireless_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/controller.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:controller\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:controller\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/crafter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:crafter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:crafter_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_monitor\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:crafting_monitor\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_controller.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:controller\"\n    },\n    {\n      \"tag\": \"forge:dyes/cyan\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:cyan_controller\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_crafter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter\"\n    },\n    {\n      \"tag\": \"forge:dyes/cyan\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:cyan_crafter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/cyan\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:cyan_crafter_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/cyan\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:cyan_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_monitor\"\n    },\n    {\n      \"tag\": \"forge:dyes/cyan\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:cyan_crafting_monitor\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_detector.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:detector\"\n    },\n    {\n      \"tag\": \"forge:dyes/cyan\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:cyan_detector\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:disk_manipulator\"\n    },\n    {\n      \"tag\": \"forge:dyes/cyan\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:cyan_disk_manipulator\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:fluid_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/cyan\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:cyan_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/cyan\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:cyan_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_receiver\"\n    },\n    {\n      \"tag\": \"forge:dyes/cyan\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:cyan_network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/cyan\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:cyan_network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:pattern_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/cyan\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:cyan_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_relay.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:relay\"\n    },\n    {\n      \"tag\": \"forge:dyes/cyan\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:cyan_relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:security_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/cyan\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:cyan_security_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:wireless_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/cyan\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:cyan_wireless_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/detector.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:detector\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:detector\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:disk_manipulator\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:disk_manipulator\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:fluid_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_controller.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:controller\"\n    },\n    {\n      \"tag\": \"forge:dyes/gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:gray_controller\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_crafter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter\"\n    },\n    {\n      \"tag\": \"forge:dyes/gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:gray_crafter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:gray_crafter_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:gray_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_monitor\"\n    },\n    {\n      \"tag\": \"forge:dyes/gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:gray_crafting_monitor\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_detector.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:detector\"\n    },\n    {\n      \"tag\": \"forge:dyes/gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:gray_detector\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:disk_manipulator\"\n    },\n    {\n      \"tag\": \"forge:dyes/gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:gray_disk_manipulator\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:fluid_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:gray_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:gray_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_receiver\"\n    },\n    {\n      \"tag\": \"forge:dyes/gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:gray_network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:gray_network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:pattern_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:gray_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_relay.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:relay\"\n    },\n    {\n      \"tag\": \"forge:dyes/gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:gray_relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:security_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:gray_security_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:wireless_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:gray_wireless_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_controller.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:controller\"\n    },\n    {\n      \"tag\": \"forge:dyes/green\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:green_controller\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_crafter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter\"\n    },\n    {\n      \"tag\": \"forge:dyes/green\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:green_crafter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/green\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:green_crafter_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/green\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:green_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_monitor\"\n    },\n    {\n      \"tag\": \"forge:dyes/green\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:green_crafting_monitor\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_detector.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:detector\"\n    },\n    {\n      \"tag\": \"forge:dyes/green\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:green_detector\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:disk_manipulator\"\n    },\n    {\n      \"tag\": \"forge:dyes/green\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:green_disk_manipulator\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:fluid_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/green\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:green_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/green\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:green_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_receiver\"\n    },\n    {\n      \"tag\": \"forge:dyes/green\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:green_network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/green\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:green_network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:pattern_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/green\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:green_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_relay.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:relay\"\n    },\n    {\n      \"tag\": \"forge:dyes/green\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:green_relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:security_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/green\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:green_security_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:wireless_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/green\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:green_wireless_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_controller.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:controller\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:light_gray_controller\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_crafter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:light_gray_crafter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:light_gray_crafter_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:light_gray_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_monitor\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:light_gray_crafting_monitor\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_detector.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:detector\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:light_gray_detector\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:disk_manipulator\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:light_gray_disk_manipulator\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:fluid_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:light_gray_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:light_gray_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_receiver\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:light_gray_network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:light_gray_network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:pattern_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:light_gray_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_relay.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:relay\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:light_gray_relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:security_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:light_gray_security_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:wireless_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_gray\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:light_gray_wireless_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_controller.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:controller\"\n    },\n    {\n      \"tag\": \"forge:dyes/lime\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:lime_controller\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_crafter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter\"\n    },\n    {\n      \"tag\": \"forge:dyes/lime\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:lime_crafter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/lime\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:lime_crafter_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/lime\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:lime_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_monitor\"\n    },\n    {\n      \"tag\": \"forge:dyes/lime\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:lime_crafting_monitor\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_detector.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:detector\"\n    },\n    {\n      \"tag\": \"forge:dyes/lime\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:lime_detector\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:disk_manipulator\"\n    },\n    {\n      \"tag\": \"forge:dyes/lime\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:lime_disk_manipulator\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:fluid_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/lime\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:lime_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/lime\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:lime_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_receiver\"\n    },\n    {\n      \"tag\": \"forge:dyes/lime\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:lime_network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/lime\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:lime_network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:pattern_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/lime\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:lime_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_relay.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:relay\"\n    },\n    {\n      \"tag\": \"forge:dyes/lime\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:lime_relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:security_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/lime\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:lime_security_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:wireless_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/lime\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:lime_wireless_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_controller.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:controller\"\n    },\n    {\n      \"tag\": \"forge:dyes/magenta\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:magenta_controller\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_crafter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter\"\n    },\n    {\n      \"tag\": \"forge:dyes/magenta\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:magenta_crafter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/magenta\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:magenta_crafter_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/magenta\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:magenta_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_monitor\"\n    },\n    {\n      \"tag\": \"forge:dyes/magenta\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:magenta_crafting_monitor\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_detector.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:detector\"\n    },\n    {\n      \"tag\": \"forge:dyes/magenta\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:magenta_detector\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:disk_manipulator\"\n    },\n    {\n      \"tag\": \"forge:dyes/magenta\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:magenta_disk_manipulator\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:fluid_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/magenta\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:magenta_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/magenta\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:magenta_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_receiver\"\n    },\n    {\n      \"tag\": \"forge:dyes/magenta\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:magenta_network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/magenta\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:magenta_network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:pattern_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/magenta\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:magenta_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_relay.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:relay\"\n    },\n    {\n      \"tag\": \"forge:dyes/magenta\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:magenta_relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:security_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/magenta\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:magenta_security_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:wireless_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/magenta\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:magenta_wireless_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_receiver\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_controller.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:controller\"\n    },\n    {\n      \"tag\": \"forge:dyes/orange\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:orange_controller\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_crafter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter\"\n    },\n    {\n      \"tag\": \"forge:dyes/orange\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:orange_crafter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/orange\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:orange_crafter_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/orange\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:orange_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_monitor\"\n    },\n    {\n      \"tag\": \"forge:dyes/orange\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:orange_crafting_monitor\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_detector.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:detector\"\n    },\n    {\n      \"tag\": \"forge:dyes/orange\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:orange_detector\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:disk_manipulator\"\n    },\n    {\n      \"tag\": \"forge:dyes/orange\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:orange_disk_manipulator\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:fluid_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/orange\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:orange_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/orange\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:orange_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_receiver\"\n    },\n    {\n      \"tag\": \"forge:dyes/orange\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:orange_network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/orange\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:orange_network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:pattern_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/orange\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:orange_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_relay.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:relay\"\n    },\n    {\n      \"tag\": \"forge:dyes/orange\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:orange_relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:security_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/orange\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:orange_security_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:wireless_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/orange\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:orange_wireless_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:pattern_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_controller.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:controller\"\n    },\n    {\n      \"tag\": \"forge:dyes/pink\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:pink_controller\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_crafter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter\"\n    },\n    {\n      \"tag\": \"forge:dyes/pink\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:pink_crafter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/pink\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:pink_crafter_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/pink\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:pink_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_monitor\"\n    },\n    {\n      \"tag\": \"forge:dyes/pink\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:pink_crafting_monitor\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_detector.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:detector\"\n    },\n    {\n      \"tag\": \"forge:dyes/pink\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:pink_detector\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:disk_manipulator\"\n    },\n    {\n      \"tag\": \"forge:dyes/pink\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:pink_disk_manipulator\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:fluid_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/pink\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:pink_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/pink\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:pink_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_receiver\"\n    },\n    {\n      \"tag\": \"forge:dyes/pink\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:pink_network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/pink\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:pink_network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:pattern_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/pink\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:pink_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_relay.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:relay\"\n    },\n    {\n      \"tag\": \"forge:dyes/pink\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:pink_relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:security_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/pink\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:pink_security_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:wireless_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/pink\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:pink_wireless_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_controller.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:controller\"\n    },\n    {\n      \"tag\": \"forge:dyes/purple\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:purple_controller\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_crafter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter\"\n    },\n    {\n      \"tag\": \"forge:dyes/purple\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:purple_crafter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/purple\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:purple_crafter_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/purple\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:purple_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_monitor\"\n    },\n    {\n      \"tag\": \"forge:dyes/purple\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:purple_crafting_monitor\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_detector.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:detector\"\n    },\n    {\n      \"tag\": \"forge:dyes/purple\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:purple_detector\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:disk_manipulator\"\n    },\n    {\n      \"tag\": \"forge:dyes/purple\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:purple_disk_manipulator\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:fluid_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/purple\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:purple_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/purple\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:purple_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_receiver\"\n    },\n    {\n      \"tag\": \"forge:dyes/purple\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:purple_network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/purple\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:purple_network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:pattern_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/purple\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:purple_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_relay.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:relay\"\n    },\n    {\n      \"tag\": \"forge:dyes/purple\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:purple_relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:security_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/purple\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:purple_security_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:wireless_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/purple\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:purple_wireless_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_controller.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:controller\"\n    },\n    {\n      \"tag\": \"forge:dyes/red\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:red_controller\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_crafter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter\"\n    },\n    {\n      \"tag\": \"forge:dyes/red\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:red_crafter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/red\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:red_crafter_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/red\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:red_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_monitor\"\n    },\n    {\n      \"tag\": \"forge:dyes/red\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:red_crafting_monitor\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_detector.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:detector\"\n    },\n    {\n      \"tag\": \"forge:dyes/red\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:red_detector\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:disk_manipulator\"\n    },\n    {\n      \"tag\": \"forge:dyes/red\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:red_disk_manipulator\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:fluid_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/red\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:red_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/red\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:red_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_receiver\"\n    },\n    {\n      \"tag\": \"forge:dyes/red\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:red_network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/red\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:red_network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:pattern_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/red\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:red_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_relay.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:relay\"\n    },\n    {\n      \"tag\": \"forge:dyes/red\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:red_relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:security_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/red\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:red_security_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:wireless_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/red\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:red_wireless_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/relay.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:relay\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/security_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:security_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:security_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_controller.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:controller\"\n    },\n    {\n      \"tag\": \"forge:dyes/white\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:white_controller\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_crafter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter\"\n    },\n    {\n      \"tag\": \"forge:dyes/white\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:white_crafter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/white\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:white_crafter_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/white\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:white_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_monitor\"\n    },\n    {\n      \"tag\": \"forge:dyes/white\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:white_crafting_monitor\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_detector.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:detector\"\n    },\n    {\n      \"tag\": \"forge:dyes/white\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:white_detector\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:disk_manipulator\"\n    },\n    {\n      \"tag\": \"forge:dyes/white\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:white_disk_manipulator\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:fluid_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/white\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:white_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/white\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:white_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_receiver\"\n    },\n    {\n      \"tag\": \"forge:dyes/white\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:white_network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/white\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:white_network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:pattern_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/white\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:white_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_relay.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:relay\"\n    },\n    {\n      \"tag\": \"forge:dyes/white\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:white_relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:security_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/white\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:white_security_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:wireless_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/white\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:white_wireless_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:wireless_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/light_blue\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:wireless_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_controller.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:controller\"\n    },\n    {\n      \"tag\": \"forge:dyes/yellow\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:yellow_controller\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_crafter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter\"\n    },\n    {\n      \"tag\": \"forge:dyes/yellow\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:yellow_crafter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafter_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/yellow\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:yellow_crafter_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/yellow\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:yellow_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:crafting_monitor\"\n    },\n    {\n      \"tag\": \"forge:dyes/yellow\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:yellow_crafting_monitor\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_detector.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:detector\"\n    },\n    {\n      \"tag\": \"forge:dyes/yellow\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:yellow_detector\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:disk_manipulator\"\n    },\n    {\n      \"tag\": \"forge:dyes/yellow\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:yellow_disk_manipulator\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:fluid_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/yellow\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:yellow_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/yellow\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:yellow_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_receiver\"\n    },\n    {\n      \"tag\": \"forge:dyes/yellow\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:yellow_network_receiver\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:network_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/yellow\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:yellow_network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:pattern_grid\"\n    },\n    {\n      \"tag\": \"forge:dyes/yellow\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:yellow_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_relay.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:relay\"\n    },\n    {\n      \"tag\": \"forge:dyes/yellow\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:yellow_relay\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_security_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:security_manager\"\n    },\n    {\n      \"tag\": \"forge:dyes/yellow\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:yellow_security_manager\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"group\": \"refinedstorage\",\n  \"ingredients\": [\n    {\n      \"tag\": \"refinedstorage:wireless_transmitter\"\n    },\n    {\n      \"tag\": \"forge:dyes/yellow\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:yellow_wireless_transmitter\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/crafting_grid/black_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:black_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"tag\": \"refinedstorage:crafting_tables\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:black_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/crafting_grid/blue_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:blue_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"tag\": \"refinedstorage:crafting_tables\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:blue_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/crafting_grid/brown_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:brown_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"tag\": \"refinedstorage:crafting_tables\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:brown_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/crafting_grid/crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"tag\": \"refinedstorage:crafting_tables\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/crafting_grid/cyan_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:cyan_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"tag\": \"refinedstorage:crafting_tables\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:cyan_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/crafting_grid/gray_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:gray_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"tag\": \"refinedstorage:crafting_tables\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:gray_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/crafting_grid/green_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:green_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"tag\": \"refinedstorage:crafting_tables\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:green_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/crafting_grid/light_gray_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:light_gray_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"tag\": \"refinedstorage:crafting_tables\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:light_gray_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/crafting_grid/lime_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:lime_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"tag\": \"refinedstorage:crafting_tables\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:lime_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/crafting_grid/magenta_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:magenta_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"tag\": \"refinedstorage:crafting_tables\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:magenta_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/crafting_grid/orange_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:orange_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"tag\": \"refinedstorage:crafting_tables\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:orange_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/crafting_grid/pink_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:pink_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"tag\": \"refinedstorage:crafting_tables\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:pink_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/crafting_grid/purple_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:purple_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"tag\": \"refinedstorage:crafting_tables\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:purple_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/crafting_grid/red_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:red_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"tag\": \"refinedstorage:crafting_tables\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:red_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/crafting_grid/white_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:white_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"tag\": \"refinedstorage:crafting_tables\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:white_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/crafting_grid/yellow_crafting_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:yellow_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"tag\": \"refinedstorage:crafting_tables\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:yellow_crafting_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/fluid_grid/black_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:black_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"minecraft:bucket\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:black_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/fluid_grid/blue_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:blue_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"minecraft:bucket\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:blue_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/fluid_grid/brown_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:brown_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"minecraft:bucket\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:brown_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/fluid_grid/cyan_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:cyan_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"minecraft:bucket\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:cyan_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/fluid_grid/fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"minecraft:bucket\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/fluid_grid/gray_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:gray_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"minecraft:bucket\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:gray_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/fluid_grid/green_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:green_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"minecraft:bucket\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:green_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/fluid_grid/light_gray_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:light_gray_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"minecraft:bucket\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:light_gray_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/fluid_grid/lime_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:lime_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"minecraft:bucket\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:lime_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/fluid_grid/magenta_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:magenta_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"minecraft:bucket\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:magenta_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/fluid_grid/orange_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:orange_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"minecraft:bucket\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:orange_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/fluid_grid/pink_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:pink_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"minecraft:bucket\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:pink_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/fluid_grid/purple_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:purple_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"minecraft:bucket\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:purple_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/fluid_grid/red_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:red_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"minecraft:bucket\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:red_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/fluid_grid/white_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:white_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"minecraft:bucket\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:white_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/fluid_grid/yellow_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:yellow_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"minecraft:bucket\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:yellow_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/pattern_grid/black_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:black_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"refinedstorage:pattern\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:black_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/pattern_grid/blue_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:blue_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"refinedstorage:pattern\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:blue_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/pattern_grid/brown_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:brown_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"refinedstorage:pattern\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:brown_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/pattern_grid/cyan_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:cyan_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"refinedstorage:pattern\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:cyan_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/pattern_grid/gray_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:gray_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"refinedstorage:pattern\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:gray_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/pattern_grid/green_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:green_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"refinedstorage:pattern\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:green_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/pattern_grid/light_gray_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:light_gray_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"refinedstorage:pattern\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:light_gray_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/pattern_grid/lime_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:lime_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"refinedstorage:pattern\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:lime_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/pattern_grid/magenta_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:magenta_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"refinedstorage:pattern\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:magenta_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/pattern_grid/orange_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:orange_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"refinedstorage:pattern\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:orange_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/pattern_grid/pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"refinedstorage:pattern\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/pattern_grid/pink_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:pink_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"refinedstorage:pattern\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:pink_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/pattern_grid/purple_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:purple_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"refinedstorage:pattern\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:purple_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/pattern_grid/red_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:red_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"refinedstorage:pattern\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:red_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/pattern_grid/white_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:white_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"refinedstorage:pattern\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:white_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/recipes/pattern_grid/yellow_pattern_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"category\": \"misc\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:yellow_grid\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"refinedstorage:pattern\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:yellow_pattern_grid\"\n  }\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/blocks/controller.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_controller\",\n    \"refinedstorage:orange_controller\",\n    \"refinedstorage:magenta_controller\",\n    \"refinedstorage:controller\",\n    \"refinedstorage:yellow_controller\",\n    \"refinedstorage:lime_controller\",\n    \"refinedstorage:pink_controller\",\n    \"refinedstorage:gray_controller\",\n    \"refinedstorage:light_gray_controller\",\n    \"refinedstorage:cyan_controller\",\n    \"refinedstorage:purple_controller\",\n    \"refinedstorage:blue_controller\",\n    \"refinedstorage:brown_controller\",\n    \"refinedstorage:green_controller\",\n    \"refinedstorage:red_controller\",\n    \"refinedstorage:black_controller\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/blocks/crafter.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_crafter\",\n    \"refinedstorage:orange_crafter\",\n    \"refinedstorage:magenta_crafter\",\n    \"refinedstorage:crafter\",\n    \"refinedstorage:yellow_crafter\",\n    \"refinedstorage:lime_crafter\",\n    \"refinedstorage:pink_crafter\",\n    \"refinedstorage:gray_crafter\",\n    \"refinedstorage:light_gray_crafter\",\n    \"refinedstorage:cyan_crafter\",\n    \"refinedstorage:purple_crafter\",\n    \"refinedstorage:blue_crafter\",\n    \"refinedstorage:brown_crafter\",\n    \"refinedstorage:green_crafter\",\n    \"refinedstorage:red_crafter\",\n    \"refinedstorage:black_crafter\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/blocks/crafter_manager.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_crafter_manager\",\n    \"refinedstorage:orange_crafter_manager\",\n    \"refinedstorage:magenta_crafter_manager\",\n    \"refinedstorage:crafter_manager\",\n    \"refinedstorage:yellow_crafter_manager\",\n    \"refinedstorage:lime_crafter_manager\",\n    \"refinedstorage:pink_crafter_manager\",\n    \"refinedstorage:gray_crafter_manager\",\n    \"refinedstorage:light_gray_crafter_manager\",\n    \"refinedstorage:cyan_crafter_manager\",\n    \"refinedstorage:purple_crafter_manager\",\n    \"refinedstorage:blue_crafter_manager\",\n    \"refinedstorage:brown_crafter_manager\",\n    \"refinedstorage:green_crafter_manager\",\n    \"refinedstorage:red_crafter_manager\",\n    \"refinedstorage:black_crafter_manager\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/blocks/crafting_grid.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_crafting_grid\",\n    \"refinedstorage:orange_crafting_grid\",\n    \"refinedstorage:magenta_crafting_grid\",\n    \"refinedstorage:crafting_grid\",\n    \"refinedstorage:yellow_crafting_grid\",\n    \"refinedstorage:lime_crafting_grid\",\n    \"refinedstorage:pink_crafting_grid\",\n    \"refinedstorage:gray_crafting_grid\",\n    \"refinedstorage:light_gray_crafting_grid\",\n    \"refinedstorage:cyan_crafting_grid\",\n    \"refinedstorage:purple_crafting_grid\",\n    \"refinedstorage:blue_crafting_grid\",\n    \"refinedstorage:brown_crafting_grid\",\n    \"refinedstorage:green_crafting_grid\",\n    \"refinedstorage:red_crafting_grid\",\n    \"refinedstorage:black_crafting_grid\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/blocks/crafting_monitor.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_crafting_monitor\",\n    \"refinedstorage:orange_crafting_monitor\",\n    \"refinedstorage:magenta_crafting_monitor\",\n    \"refinedstorage:crafting_monitor\",\n    \"refinedstorage:yellow_crafting_monitor\",\n    \"refinedstorage:lime_crafting_monitor\",\n    \"refinedstorage:pink_crafting_monitor\",\n    \"refinedstorage:gray_crafting_monitor\",\n    \"refinedstorage:light_gray_crafting_monitor\",\n    \"refinedstorage:cyan_crafting_monitor\",\n    \"refinedstorage:purple_crafting_monitor\",\n    \"refinedstorage:blue_crafting_monitor\",\n    \"refinedstorage:brown_crafting_monitor\",\n    \"refinedstorage:green_crafting_monitor\",\n    \"refinedstorage:red_crafting_monitor\",\n    \"refinedstorage:black_crafting_monitor\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/blocks/creative_controller.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_creative_controller\",\n    \"refinedstorage:orange_creative_controller\",\n    \"refinedstorage:magenta_creative_controller\",\n    \"refinedstorage:creative_controller\",\n    \"refinedstorage:yellow_creative_controller\",\n    \"refinedstorage:lime_creative_controller\",\n    \"refinedstorage:pink_creative_controller\",\n    \"refinedstorage:gray_creative_controller\",\n    \"refinedstorage:light_gray_creative_controller\",\n    \"refinedstorage:cyan_creative_controller\",\n    \"refinedstorage:purple_creative_controller\",\n    \"refinedstorage:blue_creative_controller\",\n    \"refinedstorage:brown_creative_controller\",\n    \"refinedstorage:green_creative_controller\",\n    \"refinedstorage:red_creative_controller\",\n    \"refinedstorage:black_creative_controller\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/blocks/detector.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_detector\",\n    \"refinedstorage:orange_detector\",\n    \"refinedstorage:magenta_detector\",\n    \"refinedstorage:detector\",\n    \"refinedstorage:yellow_detector\",\n    \"refinedstorage:lime_detector\",\n    \"refinedstorage:pink_detector\",\n    \"refinedstorage:gray_detector\",\n    \"refinedstorage:light_gray_detector\",\n    \"refinedstorage:cyan_detector\",\n    \"refinedstorage:purple_detector\",\n    \"refinedstorage:blue_detector\",\n    \"refinedstorage:brown_detector\",\n    \"refinedstorage:green_detector\",\n    \"refinedstorage:red_detector\",\n    \"refinedstorage:black_detector\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/blocks/disk_manipulator.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_disk_manipulator\",\n    \"refinedstorage:orange_disk_manipulator\",\n    \"refinedstorage:magenta_disk_manipulator\",\n    \"refinedstorage:disk_manipulator\",\n    \"refinedstorage:yellow_disk_manipulator\",\n    \"refinedstorage:lime_disk_manipulator\",\n    \"refinedstorage:pink_disk_manipulator\",\n    \"refinedstorage:gray_disk_manipulator\",\n    \"refinedstorage:light_gray_disk_manipulator\",\n    \"refinedstorage:cyan_disk_manipulator\",\n    \"refinedstorage:purple_disk_manipulator\",\n    \"refinedstorage:blue_disk_manipulator\",\n    \"refinedstorage:brown_disk_manipulator\",\n    \"refinedstorage:green_disk_manipulator\",\n    \"refinedstorage:red_disk_manipulator\",\n    \"refinedstorage:black_disk_manipulator\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/blocks/fluid_grid.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_fluid_grid\",\n    \"refinedstorage:orange_fluid_grid\",\n    \"refinedstorage:magenta_fluid_grid\",\n    \"refinedstorage:fluid_grid\",\n    \"refinedstorage:yellow_fluid_grid\",\n    \"refinedstorage:lime_fluid_grid\",\n    \"refinedstorage:pink_fluid_grid\",\n    \"refinedstorage:gray_fluid_grid\",\n    \"refinedstorage:light_gray_fluid_grid\",\n    \"refinedstorage:cyan_fluid_grid\",\n    \"refinedstorage:purple_fluid_grid\",\n    \"refinedstorage:blue_fluid_grid\",\n    \"refinedstorage:brown_fluid_grid\",\n    \"refinedstorage:green_fluid_grid\",\n    \"refinedstorage:red_fluid_grid\",\n    \"refinedstorage:black_fluid_grid\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/blocks/grid.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_grid\",\n    \"refinedstorage:orange_grid\",\n    \"refinedstorage:magenta_grid\",\n    \"refinedstorage:grid\",\n    \"refinedstorage:yellow_grid\",\n    \"refinedstorage:lime_grid\",\n    \"refinedstorage:pink_grid\",\n    \"refinedstorage:gray_grid\",\n    \"refinedstorage:light_gray_grid\",\n    \"refinedstorage:cyan_grid\",\n    \"refinedstorage:purple_grid\",\n    \"refinedstorage:blue_grid\",\n    \"refinedstorage:brown_grid\",\n    \"refinedstorage:green_grid\",\n    \"refinedstorage:red_grid\",\n    \"refinedstorage:black_grid\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/blocks/network_receiver.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_network_receiver\",\n    \"refinedstorage:orange_network_receiver\",\n    \"refinedstorage:magenta_network_receiver\",\n    \"refinedstorage:network_receiver\",\n    \"refinedstorage:yellow_network_receiver\",\n    \"refinedstorage:lime_network_receiver\",\n    \"refinedstorage:pink_network_receiver\",\n    \"refinedstorage:gray_network_receiver\",\n    \"refinedstorage:light_gray_network_receiver\",\n    \"refinedstorage:cyan_network_receiver\",\n    \"refinedstorage:purple_network_receiver\",\n    \"refinedstorage:blue_network_receiver\",\n    \"refinedstorage:brown_network_receiver\",\n    \"refinedstorage:green_network_receiver\",\n    \"refinedstorage:red_network_receiver\",\n    \"refinedstorage:black_network_receiver\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/blocks/network_transmitter.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_network_transmitter\",\n    \"refinedstorage:orange_network_transmitter\",\n    \"refinedstorage:magenta_network_transmitter\",\n    \"refinedstorage:network_transmitter\",\n    \"refinedstorage:yellow_network_transmitter\",\n    \"refinedstorage:lime_network_transmitter\",\n    \"refinedstorage:pink_network_transmitter\",\n    \"refinedstorage:gray_network_transmitter\",\n    \"refinedstorage:light_gray_network_transmitter\",\n    \"refinedstorage:cyan_network_transmitter\",\n    \"refinedstorage:purple_network_transmitter\",\n    \"refinedstorage:blue_network_transmitter\",\n    \"refinedstorage:brown_network_transmitter\",\n    \"refinedstorage:green_network_transmitter\",\n    \"refinedstorage:red_network_transmitter\",\n    \"refinedstorage:black_network_transmitter\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/blocks/pattern_grid.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_pattern_grid\",\n    \"refinedstorage:orange_pattern_grid\",\n    \"refinedstorage:magenta_pattern_grid\",\n    \"refinedstorage:pattern_grid\",\n    \"refinedstorage:yellow_pattern_grid\",\n    \"refinedstorage:lime_pattern_grid\",\n    \"refinedstorage:pink_pattern_grid\",\n    \"refinedstorage:gray_pattern_grid\",\n    \"refinedstorage:light_gray_pattern_grid\",\n    \"refinedstorage:cyan_pattern_grid\",\n    \"refinedstorage:purple_pattern_grid\",\n    \"refinedstorage:blue_pattern_grid\",\n    \"refinedstorage:brown_pattern_grid\",\n    \"refinedstorage:green_pattern_grid\",\n    \"refinedstorage:red_pattern_grid\",\n    \"refinedstorage:black_pattern_grid\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/blocks/relay.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_relay\",\n    \"refinedstorage:orange_relay\",\n    \"refinedstorage:magenta_relay\",\n    \"refinedstorage:relay\",\n    \"refinedstorage:yellow_relay\",\n    \"refinedstorage:lime_relay\",\n    \"refinedstorage:pink_relay\",\n    \"refinedstorage:gray_relay\",\n    \"refinedstorage:light_gray_relay\",\n    \"refinedstorage:cyan_relay\",\n    \"refinedstorage:purple_relay\",\n    \"refinedstorage:blue_relay\",\n    \"refinedstorage:brown_relay\",\n    \"refinedstorage:green_relay\",\n    \"refinedstorage:red_relay\",\n    \"refinedstorage:black_relay\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/blocks/security_manager.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_security_manager\",\n    \"refinedstorage:orange_security_manager\",\n    \"refinedstorage:magenta_security_manager\",\n    \"refinedstorage:security_manager\",\n    \"refinedstorage:yellow_security_manager\",\n    \"refinedstorage:lime_security_manager\",\n    \"refinedstorage:pink_security_manager\",\n    \"refinedstorage:gray_security_manager\",\n    \"refinedstorage:light_gray_security_manager\",\n    \"refinedstorage:cyan_security_manager\",\n    \"refinedstorage:purple_security_manager\",\n    \"refinedstorage:blue_security_manager\",\n    \"refinedstorage:brown_security_manager\",\n    \"refinedstorage:green_security_manager\",\n    \"refinedstorage:red_security_manager\",\n    \"refinedstorage:black_security_manager\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/blocks/wireless_transmitter.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_wireless_transmitter\",\n    \"refinedstorage:orange_wireless_transmitter\",\n    \"refinedstorage:magenta_wireless_transmitter\",\n    \"refinedstorage:wireless_transmitter\",\n    \"refinedstorage:yellow_wireless_transmitter\",\n    \"refinedstorage:lime_wireless_transmitter\",\n    \"refinedstorage:pink_wireless_transmitter\",\n    \"refinedstorage:gray_wireless_transmitter\",\n    \"refinedstorage:light_gray_wireless_transmitter\",\n    \"refinedstorage:cyan_wireless_transmitter\",\n    \"refinedstorage:purple_wireless_transmitter\",\n    \"refinedstorage:blue_wireless_transmitter\",\n    \"refinedstorage:brown_wireless_transmitter\",\n    \"refinedstorage:green_wireless_transmitter\",\n    \"refinedstorage:red_wireless_transmitter\",\n    \"refinedstorage:black_wireless_transmitter\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/items/controller.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_controller\",\n    \"refinedstorage:orange_controller\",\n    \"refinedstorage:magenta_controller\",\n    \"refinedstorage:controller\",\n    \"refinedstorage:yellow_controller\",\n    \"refinedstorage:lime_controller\",\n    \"refinedstorage:pink_controller\",\n    \"refinedstorage:gray_controller\",\n    \"refinedstorage:light_gray_controller\",\n    \"refinedstorage:cyan_controller\",\n    \"refinedstorage:purple_controller\",\n    \"refinedstorage:blue_controller\",\n    \"refinedstorage:brown_controller\",\n    \"refinedstorage:green_controller\",\n    \"refinedstorage:red_controller\",\n    \"refinedstorage:black_controller\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/items/crafter.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_crafter\",\n    \"refinedstorage:orange_crafter\",\n    \"refinedstorage:magenta_crafter\",\n    \"refinedstorage:crafter\",\n    \"refinedstorage:yellow_crafter\",\n    \"refinedstorage:lime_crafter\",\n    \"refinedstorage:pink_crafter\",\n    \"refinedstorage:gray_crafter\",\n    \"refinedstorage:light_gray_crafter\",\n    \"refinedstorage:cyan_crafter\",\n    \"refinedstorage:purple_crafter\",\n    \"refinedstorage:blue_crafter\",\n    \"refinedstorage:brown_crafter\",\n    \"refinedstorage:green_crafter\",\n    \"refinedstorage:red_crafter\",\n    \"refinedstorage:black_crafter\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/items/crafter_manager.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_crafter_manager\",\n    \"refinedstorage:orange_crafter_manager\",\n    \"refinedstorage:magenta_crafter_manager\",\n    \"refinedstorage:crafter_manager\",\n    \"refinedstorage:yellow_crafter_manager\",\n    \"refinedstorage:lime_crafter_manager\",\n    \"refinedstorage:pink_crafter_manager\",\n    \"refinedstorage:gray_crafter_manager\",\n    \"refinedstorage:light_gray_crafter_manager\",\n    \"refinedstorage:cyan_crafter_manager\",\n    \"refinedstorage:purple_crafter_manager\",\n    \"refinedstorage:blue_crafter_manager\",\n    \"refinedstorage:brown_crafter_manager\",\n    \"refinedstorage:green_crafter_manager\",\n    \"refinedstorage:red_crafter_manager\",\n    \"refinedstorage:black_crafter_manager\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/items/crafting_grid.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_crafting_grid\",\n    \"refinedstorage:orange_crafting_grid\",\n    \"refinedstorage:magenta_crafting_grid\",\n    \"refinedstorage:crafting_grid\",\n    \"refinedstorage:yellow_crafting_grid\",\n    \"refinedstorage:lime_crafting_grid\",\n    \"refinedstorage:pink_crafting_grid\",\n    \"refinedstorage:gray_crafting_grid\",\n    \"refinedstorage:light_gray_crafting_grid\",\n    \"refinedstorage:cyan_crafting_grid\",\n    \"refinedstorage:purple_crafting_grid\",\n    \"refinedstorage:blue_crafting_grid\",\n    \"refinedstorage:brown_crafting_grid\",\n    \"refinedstorage:green_crafting_grid\",\n    \"refinedstorage:red_crafting_grid\",\n    \"refinedstorage:black_crafting_grid\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/items/crafting_monitor.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_crafting_monitor\",\n    \"refinedstorage:orange_crafting_monitor\",\n    \"refinedstorage:magenta_crafting_monitor\",\n    \"refinedstorage:crafting_monitor\",\n    \"refinedstorage:yellow_crafting_monitor\",\n    \"refinedstorage:lime_crafting_monitor\",\n    \"refinedstorage:pink_crafting_monitor\",\n    \"refinedstorage:gray_crafting_monitor\",\n    \"refinedstorage:light_gray_crafting_monitor\",\n    \"refinedstorage:cyan_crafting_monitor\",\n    \"refinedstorage:purple_crafting_monitor\",\n    \"refinedstorage:blue_crafting_monitor\",\n    \"refinedstorage:brown_crafting_monitor\",\n    \"refinedstorage:green_crafting_monitor\",\n    \"refinedstorage:red_crafting_monitor\",\n    \"refinedstorage:black_crafting_monitor\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/items/detector.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_detector\",\n    \"refinedstorage:orange_detector\",\n    \"refinedstorage:magenta_detector\",\n    \"refinedstorage:detector\",\n    \"refinedstorage:yellow_detector\",\n    \"refinedstorage:lime_detector\",\n    \"refinedstorage:pink_detector\",\n    \"refinedstorage:gray_detector\",\n    \"refinedstorage:light_gray_detector\",\n    \"refinedstorage:cyan_detector\",\n    \"refinedstorage:purple_detector\",\n    \"refinedstorage:blue_detector\",\n    \"refinedstorage:brown_detector\",\n    \"refinedstorage:green_detector\",\n    \"refinedstorage:red_detector\",\n    \"refinedstorage:black_detector\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/items/disk_manipulator.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_disk_manipulator\",\n    \"refinedstorage:orange_disk_manipulator\",\n    \"refinedstorage:magenta_disk_manipulator\",\n    \"refinedstorage:disk_manipulator\",\n    \"refinedstorage:yellow_disk_manipulator\",\n    \"refinedstorage:lime_disk_manipulator\",\n    \"refinedstorage:pink_disk_manipulator\",\n    \"refinedstorage:gray_disk_manipulator\",\n    \"refinedstorage:light_gray_disk_manipulator\",\n    \"refinedstorage:cyan_disk_manipulator\",\n    \"refinedstorage:purple_disk_manipulator\",\n    \"refinedstorage:blue_disk_manipulator\",\n    \"refinedstorage:brown_disk_manipulator\",\n    \"refinedstorage:green_disk_manipulator\",\n    \"refinedstorage:red_disk_manipulator\",\n    \"refinedstorage:black_disk_manipulator\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/items/fluid_grid.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_fluid_grid\",\n    \"refinedstorage:orange_fluid_grid\",\n    \"refinedstorage:magenta_fluid_grid\",\n    \"refinedstorage:fluid_grid\",\n    \"refinedstorage:yellow_fluid_grid\",\n    \"refinedstorage:lime_fluid_grid\",\n    \"refinedstorage:pink_fluid_grid\",\n    \"refinedstorage:gray_fluid_grid\",\n    \"refinedstorage:light_gray_fluid_grid\",\n    \"refinedstorage:cyan_fluid_grid\",\n    \"refinedstorage:purple_fluid_grid\",\n    \"refinedstorage:blue_fluid_grid\",\n    \"refinedstorage:brown_fluid_grid\",\n    \"refinedstorage:green_fluid_grid\",\n    \"refinedstorage:red_fluid_grid\",\n    \"refinedstorage:black_fluid_grid\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/items/grid.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_grid\",\n    \"refinedstorage:orange_grid\",\n    \"refinedstorage:magenta_grid\",\n    \"refinedstorage:grid\",\n    \"refinedstorage:yellow_grid\",\n    \"refinedstorage:lime_grid\",\n    \"refinedstorage:pink_grid\",\n    \"refinedstorage:gray_grid\",\n    \"refinedstorage:light_gray_grid\",\n    \"refinedstorage:cyan_grid\",\n    \"refinedstorage:purple_grid\",\n    \"refinedstorage:blue_grid\",\n    \"refinedstorage:brown_grid\",\n    \"refinedstorage:green_grid\",\n    \"refinedstorage:red_grid\",\n    \"refinedstorage:black_grid\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/items/network_receiver.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_network_receiver\",\n    \"refinedstorage:orange_network_receiver\",\n    \"refinedstorage:magenta_network_receiver\",\n    \"refinedstorage:network_receiver\",\n    \"refinedstorage:yellow_network_receiver\",\n    \"refinedstorage:lime_network_receiver\",\n    \"refinedstorage:pink_network_receiver\",\n    \"refinedstorage:gray_network_receiver\",\n    \"refinedstorage:light_gray_network_receiver\",\n    \"refinedstorage:cyan_network_receiver\",\n    \"refinedstorage:purple_network_receiver\",\n    \"refinedstorage:blue_network_receiver\",\n    \"refinedstorage:brown_network_receiver\",\n    \"refinedstorage:green_network_receiver\",\n    \"refinedstorage:red_network_receiver\",\n    \"refinedstorage:black_network_receiver\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/items/network_transmitter.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_network_transmitter\",\n    \"refinedstorage:orange_network_transmitter\",\n    \"refinedstorage:magenta_network_transmitter\",\n    \"refinedstorage:network_transmitter\",\n    \"refinedstorage:yellow_network_transmitter\",\n    \"refinedstorage:lime_network_transmitter\",\n    \"refinedstorage:pink_network_transmitter\",\n    \"refinedstorage:gray_network_transmitter\",\n    \"refinedstorage:light_gray_network_transmitter\",\n    \"refinedstorage:cyan_network_transmitter\",\n    \"refinedstorage:purple_network_transmitter\",\n    \"refinedstorage:blue_network_transmitter\",\n    \"refinedstorage:brown_network_transmitter\",\n    \"refinedstorage:green_network_transmitter\",\n    \"refinedstorage:red_network_transmitter\",\n    \"refinedstorage:black_network_transmitter\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/items/pattern_grid.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_pattern_grid\",\n    \"refinedstorage:orange_pattern_grid\",\n    \"refinedstorage:magenta_pattern_grid\",\n    \"refinedstorage:pattern_grid\",\n    \"refinedstorage:yellow_pattern_grid\",\n    \"refinedstorage:lime_pattern_grid\",\n    \"refinedstorage:pink_pattern_grid\",\n    \"refinedstorage:gray_pattern_grid\",\n    \"refinedstorage:light_gray_pattern_grid\",\n    \"refinedstorage:cyan_pattern_grid\",\n    \"refinedstorage:purple_pattern_grid\",\n    \"refinedstorage:blue_pattern_grid\",\n    \"refinedstorage:brown_pattern_grid\",\n    \"refinedstorage:green_pattern_grid\",\n    \"refinedstorage:red_pattern_grid\",\n    \"refinedstorage:black_pattern_grid\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/items/relay.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_relay\",\n    \"refinedstorage:orange_relay\",\n    \"refinedstorage:magenta_relay\",\n    \"refinedstorage:relay\",\n    \"refinedstorage:yellow_relay\",\n    \"refinedstorage:lime_relay\",\n    \"refinedstorage:pink_relay\",\n    \"refinedstorage:gray_relay\",\n    \"refinedstorage:light_gray_relay\",\n    \"refinedstorage:cyan_relay\",\n    \"refinedstorage:purple_relay\",\n    \"refinedstorage:blue_relay\",\n    \"refinedstorage:brown_relay\",\n    \"refinedstorage:green_relay\",\n    \"refinedstorage:red_relay\",\n    \"refinedstorage:black_relay\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/items/security_manager.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_security_manager\",\n    \"refinedstorage:orange_security_manager\",\n    \"refinedstorage:magenta_security_manager\",\n    \"refinedstorage:security_manager\",\n    \"refinedstorage:yellow_security_manager\",\n    \"refinedstorage:lime_security_manager\",\n    \"refinedstorage:pink_security_manager\",\n    \"refinedstorage:gray_security_manager\",\n    \"refinedstorage:light_gray_security_manager\",\n    \"refinedstorage:cyan_security_manager\",\n    \"refinedstorage:purple_security_manager\",\n    \"refinedstorage:blue_security_manager\",\n    \"refinedstorage:brown_security_manager\",\n    \"refinedstorage:green_security_manager\",\n    \"refinedstorage:red_security_manager\",\n    \"refinedstorage:black_security_manager\"\n  ]\n}"
  },
  {
    "path": "src/generated/resources/data/refinedstorage/tags/items/wireless_transmitter.json",
    "content": "{\n  \"values\": [\n    \"refinedstorage:white_wireless_transmitter\",\n    \"refinedstorage:orange_wireless_transmitter\",\n    \"refinedstorage:magenta_wireless_transmitter\",\n    \"refinedstorage:wireless_transmitter\",\n    \"refinedstorage:yellow_wireless_transmitter\",\n    \"refinedstorage:lime_wireless_transmitter\",\n    \"refinedstorage:pink_wireless_transmitter\",\n    \"refinedstorage:gray_wireless_transmitter\",\n    \"refinedstorage:light_gray_wireless_transmitter\",\n    \"refinedstorage:cyan_wireless_transmitter\",\n    \"refinedstorage:purple_wireless_transmitter\",\n    \"refinedstorage:blue_wireless_transmitter\",\n    \"refinedstorage:brown_wireless_transmitter\",\n    \"refinedstorage:green_wireless_transmitter\",\n    \"refinedstorage:red_wireless_transmitter\",\n    \"refinedstorage:black_wireless_transmitter\"\n  ]\n}"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/RS.java",
    "content": "package com.refinedmods.refinedstorage;\n\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.config.ClientConfig;\nimport com.refinedmods.refinedstorage.config.ServerConfig;\nimport com.refinedmods.refinedstorage.datageneration.DataGenerators;\nimport com.refinedmods.refinedstorage.integration.curios.CuriosIntegration;\nimport com.refinedmods.refinedstorage.network.NetworkHandler;\nimport com.refinedmods.refinedstorage.setup.ClientSetup;\nimport com.refinedmods.refinedstorage.setup.CommonSetup;\nimport com.refinedmods.refinedstorage.setup.ServerSetup;\n\nimport net.neoforged.api.distmarker.Dist;\nimport net.neoforged.bus.api.IEventBus;\nimport net.neoforged.fml.ModLoadingContext;\nimport net.neoforged.fml.common.Mod;\nimport net.neoforged.fml.config.ModConfig;\nimport net.neoforged.fml.loading.FMLEnvironment;\nimport net.neoforged.neoforge.common.NeoForge;\n\n@Mod(RS.ID)\npublic final class RS {\n    public static final String ID = \"refinedstorage\";\n    public static final String NAME = \"Refined Storage\";\n\n    public static final NetworkHandler NETWORK_HANDLER = new NetworkHandler();\n    public static final ServerConfig SERVER_CONFIG = new ServerConfig();\n    public static final ClientConfig CLIENT_CONFIG = new ClientConfig();\n\n    public RS(IEventBus eventBus) {\n        if (FMLEnvironment.dist == Dist.CLIENT) {\n            eventBus.addListener(ClientSetup::onClientSetup);\n            eventBus.addListener(ClientSetup::registerMenuScreens);\n            eventBus.addListener(ClientSetup::onModelBake);\n            eventBus.addListener(ClientSetup::onRegisterAdditionalModels);\n            eventBus.addListener(ClientSetup::onRegisterModelGeometry);\n            eventBus.addListener(ClientSetup::onRegisterKeymappings);\n            eventBus.addListener(ClientSetup::onRegisterColorBindings);\n            NeoForge.EVENT_BUS.addListener(ClientSetup::addReloadListener);\n        }\n\n        NeoForge.EVENT_BUS.register(new ServerSetup());\n\n        ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, SERVER_CONFIG.getSpec());\n        ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, CLIENT_CONFIG.getSpec());\n\n        RSBlocks.register(eventBus);\n        RSItems.register(eventBus);\n\n        eventBus.addListener(CommonSetup::onCommonSetup);\n        eventBus.addListener(CommonSetup::onRegister);\n        eventBus.addListener(CommonSetup::onRegisterCapabilities);\n        eventBus.addListener(CommonSetup::onRegisterNetworkPackets);\n        eventBus.register(new DataGenerators());\n        eventBus.register(new CuriosIntegration());\n\n        RSContainerMenus.REGISTRY.register(eventBus);\n        RSBlockEntities.REGISTRY.register(eventBus);\n        RSRecipeSerializers.REGISTRY.register(eventBus);\n\n        API.deliver();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/RSBlockEntities.java",
    "content": "package com.refinedmods.refinedstorage;\n\nimport com.refinedmods.refinedstorage.api.network.NetworkType;\nimport com.refinedmods.refinedstorage.api.network.grid.GridType;\nimport com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType;\nimport com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType;\nimport com.refinedmods.refinedstorage.blockentity.*;\nimport com.refinedmods.refinedstorage.blockentity.craftingmonitor.CraftingMonitorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport com.refinedmods.refinedstorage.blockentity.grid.GridBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.grid.portable.PortableGridBlockEntity;\nimport com.refinedmods.refinedstorage.item.blockitem.PortableGridBlockItem;\n\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.entity.BlockEntityType;\nimport net.neoforged.neoforge.registries.DeferredRegister;\nimport net.neoforged.neoforge.registries.DeferredHolder;\n\npublic final class RSBlockEntities {\n    public static final DeferredRegister<BlockEntityType<?>> REGISTRY = DeferredRegister.create(BuiltInRegistries.BLOCK_ENTITY_TYPE, RS.ID);\n\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<ControllerBlockEntity>> CONTROLLER =\n        REGISTRY.register(\"controller\", () -> registerSynchronizationParameters(ControllerBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new ControllerBlockEntity(NetworkType.NORMAL, pos, state), RSBlocks.CONTROLLER.getBlocks()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<ControllerBlockEntity>> CREATIVE_CONTROLLER =\n        REGISTRY.register(\"creative_controller\", () -> registerSynchronizationParameters(ControllerBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new ControllerBlockEntity(NetworkType.CREATIVE, pos, state), RSBlocks.CREATIVE_CONTROLLER.getBlocks()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<DetectorBlockEntity>> DETECTOR =\n        REGISTRY.register(\"detector\", () -> registerSynchronizationParameters(DetectorBlockEntity.SPEC, BlockEntityType.Builder.of(DetectorBlockEntity::new, RSBlocks.DETECTOR.getBlocks()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<DiskDriveBlockEntity>> DISK_DRIVE =\n        REGISTRY.register(\"disk_drive\", () -> registerSynchronizationParameters(DiskDriveBlockEntity.SPEC, BlockEntityType.Builder.of(DiskDriveBlockEntity::new, RSBlocks.DISK_DRIVE.get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<ExporterBlockEntity>> EXPORTER =\n        REGISTRY.register(\"exporter\", () -> registerSynchronizationParameters(ExporterBlockEntity.SPEC, BlockEntityType.Builder.of(ExporterBlockEntity::new, RSBlocks.EXPORTER.get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<ExternalStorageBlockEntity>> EXTERNAL_STORAGE =\n        REGISTRY.register(\"external_storage\", () -> registerSynchronizationParameters(ExternalStorageBlockEntity.SPEC, BlockEntityType.Builder.of(ExternalStorageBlockEntity::new, RSBlocks.EXTERNAL_STORAGE.get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<GridBlockEntity>> GRID =\n        REGISTRY.register(\"grid\", () -> registerSynchronizationParameters(GridBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new GridBlockEntity(GridType.NORMAL, pos, state), RSBlocks.GRID.getBlocks()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<GridBlockEntity>> CRAFTING_GRID =\n        REGISTRY.register(\"crafting_grid\", () -> registerSynchronizationParameters(GridBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new GridBlockEntity(GridType.CRAFTING, pos, state), RSBlocks.CRAFTING_GRID.getBlocks()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<GridBlockEntity>> PATTERN_GRID =\n        REGISTRY.register(\"pattern_grid\", () -> registerSynchronizationParameters(GridBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new GridBlockEntity(GridType.PATTERN, pos, state), RSBlocks.PATTERN_GRID.getBlocks()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<GridBlockEntity>> FLUID_GRID =\n        REGISTRY.register(\"fluid_grid\", () -> registerSynchronizationParameters(GridBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new GridBlockEntity(GridType.FLUID, pos, state), RSBlocks.FLUID_GRID.getBlocks()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<ImporterBlockEntity>> IMPORTER =\n        REGISTRY.register(\"importer\", () -> registerSynchronizationParameters(ImporterBlockEntity.SPEC, BlockEntityType.Builder.of(ImporterBlockEntity::new, RSBlocks.IMPORTER.get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<NetworkTransmitterBlockEntity>> NETWORK_TRANSMITTER =\n        REGISTRY.register(\"network_transmitter\", () -> registerSynchronizationParameters(NetworkTransmitterBlockEntity.SPEC, BlockEntityType.Builder.of(NetworkTransmitterBlockEntity::new, RSBlocks.NETWORK_TRANSMITTER.getBlocks()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<NetworkReceiverBlockEntity>> NETWORK_RECEIVER =\n        REGISTRY.register(\"network_receiver\", () -> registerSynchronizationParameters(NetworkReceiverBlockEntity.SPEC, BlockEntityType.Builder.of(NetworkReceiverBlockEntity::new, RSBlocks.NETWORK_RECEIVER.getBlocks()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<RelayBlockEntity>> RELAY =\n        REGISTRY.register(\"relay\", () -> registerSynchronizationParameters(RelayBlockEntity.SPEC, BlockEntityType.Builder.of(RelayBlockEntity::new, RSBlocks.RELAY.getBlocks()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<CableBlockEntity>> CABLE =\n        REGISTRY.register(\"cable\", () -> registerSynchronizationParameters(CableBlockEntity.SPEC, BlockEntityType.Builder.of(CableBlockEntity::new, RSBlocks.CABLE.get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<StorageBlockEntity>> ONE_K_STORAGE_BLOCK =\n        REGISTRY.register(\"1k_storage_block\", () -> registerSynchronizationParameters(StorageBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new StorageBlockEntity(ItemStorageType.ONE_K, pos, state), RSBlocks.STORAGE_BLOCKS.get(ItemStorageType.ONE_K).get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<StorageBlockEntity>> FOUR_K_STORAGE_BLOCK =\n        REGISTRY.register(\"4k_storage_block\", () -> registerSynchronizationParameters(StorageBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new StorageBlockEntity(ItemStorageType.FOUR_K, pos, state), RSBlocks.STORAGE_BLOCKS.get(ItemStorageType.FOUR_K).get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<StorageBlockEntity>> SIXTEEN_K_STORAGE_BLOCK =\n        REGISTRY.register(\"16k_storage_block\", () -> registerSynchronizationParameters(StorageBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new StorageBlockEntity(ItemStorageType.SIXTEEN_K, pos, state), RSBlocks.STORAGE_BLOCKS.get(ItemStorageType.SIXTEEN_K).get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<StorageBlockEntity>> SIXTY_FOUR_K_STORAGE_BLOCK =\n        REGISTRY.register(\"64k_storage_block\", () -> registerSynchronizationParameters(StorageBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new StorageBlockEntity(ItemStorageType.SIXTY_FOUR_K, pos, state), RSBlocks.STORAGE_BLOCKS.get(ItemStorageType.SIXTY_FOUR_K).get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<StorageBlockEntity>> CREATIVE_STORAGE_BLOCK =\n        REGISTRY.register(\"creative_storage_block\", () -> registerSynchronizationParameters(StorageBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new StorageBlockEntity(ItemStorageType.CREATIVE, pos, state), RSBlocks.STORAGE_BLOCKS.get(ItemStorageType.CREATIVE).get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<FluidStorageBlockEntity>> SIXTY_FOUR_K_FLUID_STORAGE_BLOCK =\n        REGISTRY.register(\"64k_fluid_storage_block\", () -> registerSynchronizationParameters(FluidStorageBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new FluidStorageBlockEntity(FluidStorageType.SIXTY_FOUR_K, pos, state), RSBlocks.FLUID_STORAGE_BLOCKS.get(FluidStorageType.SIXTY_FOUR_K).get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<FluidStorageBlockEntity>> TWO_HUNDRED_FIFTY_SIX_K_FLUID_STORAGE_BLOCK =\n        REGISTRY.register(\"256k_fluid_storage_block\", () -> registerSynchronizationParameters(FluidStorageBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new FluidStorageBlockEntity(FluidStorageType.TWO_HUNDRED_FIFTY_SIX_K, pos, state), RSBlocks.FLUID_STORAGE_BLOCKS.get(FluidStorageType.TWO_HUNDRED_FIFTY_SIX_K).get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<FluidStorageBlockEntity>> THOUSAND_TWENTY_FOUR_K_FLUID_STORAGE_BLOCK =\n        REGISTRY.register(\"1024k_fluid_storage_block\", () -> registerSynchronizationParameters(FluidStorageBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new FluidStorageBlockEntity(FluidStorageType.THOUSAND_TWENTY_FOUR_K, pos, state), RSBlocks.FLUID_STORAGE_BLOCKS.get(FluidStorageType.THOUSAND_TWENTY_FOUR_K).get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<FluidStorageBlockEntity>> FOUR_THOUSAND_NINETY_SIX_K_FLUID_STORAGE_BLOCK =\n        REGISTRY.register(\"4096k_fluid_storage_block\", () -> registerSynchronizationParameters(FluidStorageBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new FluidStorageBlockEntity(FluidStorageType.FOUR_THOUSAND_NINETY_SIX_K, pos, state), RSBlocks.FLUID_STORAGE_BLOCKS.get(FluidStorageType.FOUR_THOUSAND_NINETY_SIX_K).get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<FluidStorageBlockEntity>> CREATIVE_FLUID_STORAGE_BLOCK =\n        REGISTRY.register(\"creative_fluid_storage_block\", () -> registerSynchronizationParameters(FluidStorageBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new FluidStorageBlockEntity(FluidStorageType.CREATIVE, pos, state), RSBlocks.FLUID_STORAGE_BLOCKS.get(FluidStorageType.CREATIVE).get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<SecurityManagerBlockEntity>> SECURITY_MANAGER =\n        REGISTRY.register(\"security_manager\", () -> registerSynchronizationParameters(SecurityManagerBlockEntity.SPEC, BlockEntityType.Builder.of(SecurityManagerBlockEntity::new, RSBlocks.SECURITY_MANAGER.getBlocks()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<InterfaceBlockEntity>> INTERFACE =\n        REGISTRY.register(\"interface\", () -> registerSynchronizationParameters(InterfaceBlockEntity.SPEC, BlockEntityType.Builder.of(InterfaceBlockEntity::new, RSBlocks.INTERFACE.get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<FluidInterfaceBlockEntity>> FLUID_INTERFACE =\n        REGISTRY.register(\"fluid_interface\", () -> registerSynchronizationParameters(FluidInterfaceBlockEntity.SPEC, BlockEntityType.Builder.of(FluidInterfaceBlockEntity::new, RSBlocks.FLUID_INTERFACE.get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<WirelessTransmitterBlockEntity>> WIRELESS_TRANSMITTER =\n        REGISTRY.register(\"wireless_transmitter\", () -> registerSynchronizationParameters(WirelessTransmitterBlockEntity.SPEC, BlockEntityType.Builder.of(WirelessTransmitterBlockEntity::new, RSBlocks.WIRELESS_TRANSMITTER.getBlocks()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<StorageMonitorBlockEntity>> STORAGE_MONITOR =\n        REGISTRY.register(\"storage_monitor\", () -> registerSynchronizationParameters(StorageMonitorBlockEntity.SPEC, BlockEntityType.Builder.of(StorageMonitorBlockEntity::new, RSBlocks.STORAGE_MONITOR.get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<ConstructorBlockEntity>> CONSTRUCTOR =\n        REGISTRY.register(\"constructor\", () -> registerSynchronizationParameters(ConstructorBlockEntity.SPEC, BlockEntityType.Builder.of(ConstructorBlockEntity::new, RSBlocks.CONSTRUCTOR.get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<DestructorBlockEntity>> DESTRUCTOR =\n        REGISTRY.register(\"destructor\", () -> registerSynchronizationParameters(DestructorBlockEntity.SPEC, BlockEntityType.Builder.of(DestructorBlockEntity::new, RSBlocks.DESTRUCTOR.get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<DiskManipulatorBlockEntity>> DISK_MANIPULATOR =\n        REGISTRY.register(\"disk_manipulator\", () -> registerSynchronizationParameters(DiskManipulatorBlockEntity.SPEC, BlockEntityType.Builder.of(DiskManipulatorBlockEntity::new, RSBlocks.DISK_MANIPULATOR.getBlocks()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<PortableGridBlockEntity>> PORTABLE_GRID =\n        REGISTRY.register(\"portable_grid\", () -> registerSynchronizationParameters(PortableGridBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new PortableGridBlockEntity(PortableGridBlockItem.Type.NORMAL, pos, state), RSBlocks.PORTABLE_GRID.get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<PortableGridBlockEntity>> CREATIVE_PORTABLE_GRID =\n        REGISTRY.register(\"creative_portable_grid\", () -> registerSynchronizationParameters(PortableGridBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new PortableGridBlockEntity(PortableGridBlockItem.Type.CREATIVE, pos, state), RSBlocks.CREATIVE_PORTABLE_GRID.get()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<CrafterBlockEntity>> CRAFTER =\n        REGISTRY.register(\"crafter\", () -> registerSynchronizationParameters(CrafterBlockEntity.SPEC, BlockEntityType.Builder.of(CrafterBlockEntity::new, RSBlocks.CRAFTER.getBlocks()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<CrafterManagerBlockEntity>> CRAFTER_MANAGER =\n        REGISTRY.register(\"crafter_manager\", () -> registerSynchronizationParameters(CrafterManagerBlockEntity.SPEC, BlockEntityType.Builder.of(CrafterManagerBlockEntity::new, RSBlocks.CRAFTER_MANAGER.getBlocks()).build(null)));\n    public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<CraftingMonitorBlockEntity>> CRAFTING_MONITOR =\n        REGISTRY.register(\"crafting_monitor\", () -> registerSynchronizationParameters(CraftingMonitorBlockEntity.SPEC, BlockEntityType.Builder.of(CraftingMonitorBlockEntity::new, RSBlocks.CRAFTING_MONITOR.getBlocks()).build(null)));\n\n    private static <T extends BlockEntity> BlockEntityType<T> registerSynchronizationParameters(BlockEntitySynchronizationSpec spec, BlockEntityType<T> t) {\n        spec.getParameters().forEach(BlockEntitySynchronizationManager::registerParameter);\n        return t;\n    }\n\n    private RSBlockEntities() {\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/RSBlocks.java",
    "content": "package com.refinedmods.refinedstorage;\n\nimport com.refinedmods.refinedstorage.api.network.NetworkType;\nimport com.refinedmods.refinedstorage.api.network.grid.GridType;\nimport com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType;\nimport com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType;\nimport com.refinedmods.refinedstorage.block.*;\nimport com.refinedmods.refinedstorage.item.blockitem.PortableGridBlockItem;\nimport com.refinedmods.refinedstorage.util.BlockColorMap;\n\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.tags.TagKey;\nimport net.minecraft.world.level.block.Block;\nimport net.neoforged.bus.api.IEventBus;\nimport net.neoforged.neoforge.registries.DeferredHolder;\nimport net.neoforged.neoforge.registries.DeferredRegister;\nimport java.util.ArrayList;\nimport java.util.EnumMap;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic final class RSBlocks {\n    public static final DeferredHolder<Block, ImporterBlock> IMPORTER;\n    public static final DeferredHolder<Block, ExporterBlock> EXPORTER;\n    public static final DeferredHolder<Block, QuartzEnrichedIronBlock> QUARTZ_ENRICHED_IRON;\n    public static final DeferredHolder<Block, MachineCasingBlock> MACHINE_CASING;\n    public static final DeferredHolder<Block, CableBlock> CABLE;\n    public static final DeferredHolder<Block, DiskDriveBlock> DISK_DRIVE;\n    public static final DeferredHolder<Block, ExternalStorageBlock> EXTERNAL_STORAGE;\n    public static final Map<ItemStorageType, DeferredHolder<Block, StorageBlock>> STORAGE_BLOCKS = new EnumMap<>(ItemStorageType.class);\n    public static final Map<FluidStorageType, DeferredHolder<Block, FluidStorageBlock>> FLUID_STORAGE_BLOCKS = new EnumMap<>(FluidStorageType.class);\n    public static final Map<TagKey<Block>, BlockColorMap<?>> COLORED_BLOCK_TAGS = new HashMap<>();\n    public static final DeferredHolder<Block, InterfaceBlock> INTERFACE;\n    public static final DeferredHolder<Block, FluidInterfaceBlock> FLUID_INTERFACE;\n    public static final DeferredHolder<Block, StorageMonitorBlock> STORAGE_MONITOR;\n    public static final DeferredHolder<Block, ConstructorBlock> CONSTRUCTOR;\n    public static final DeferredHolder<Block, DestructorBlock> DESTRUCTOR;\n    public static final DeferredHolder<Block, PortableGridBlock> PORTABLE_GRID;\n    public static final DeferredHolder<Block, PortableGridBlock> CREATIVE_PORTABLE_GRID;\n    public static final List<DeferredHolder<Block, ? extends Block>> COLORED_BLOCKS = new ArrayList<>();\n    private static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(BuiltInRegistries.BLOCK, RS.ID);\n    public static final BlockColorMap<CrafterBlock> CRAFTER = new BlockColorMap<>(BLOCKS);\n    public static final BlockColorMap<RelayBlock> RELAY = new BlockColorMap<>(BLOCKS);\n    public static final BlockColorMap<NetworkTransmitterBlock> NETWORK_TRANSMITTER = new BlockColorMap<>(BLOCKS);\n    public static final BlockColorMap<NetworkReceiverBlock> NETWORK_RECEIVER = new BlockColorMap<>(BLOCKS);\n    public static final BlockColorMap<ControllerBlock> CONTROLLER = new BlockColorMap<>(BLOCKS);\n    public static final BlockColorMap<ControllerBlock> CREATIVE_CONTROLLER = new BlockColorMap<>(BLOCKS);\n    public static final BlockColorMap<GridBlock> GRID = new BlockColorMap<>(BLOCKS);\n    public static final BlockColorMap<GridBlock> CRAFTING_GRID = new BlockColorMap<>(BLOCKS);\n    public static final BlockColorMap<GridBlock> PATTERN_GRID = new BlockColorMap<>(BLOCKS);\n    public static final BlockColorMap<GridBlock> FLUID_GRID = new BlockColorMap<>(BLOCKS);\n    public static final BlockColorMap<SecurityManagerBlock> SECURITY_MANAGER = new BlockColorMap<>(BLOCKS);\n    public static final BlockColorMap<WirelessTransmitterBlock> WIRELESS_TRANSMITTER = new BlockColorMap<>(BLOCKS);\n    public static final BlockColorMap<DiskManipulatorBlock> DISK_MANIPULATOR = new BlockColorMap<>(BLOCKS);\n    public static final BlockColorMap<CrafterManagerBlock> CRAFTER_MANAGER = new BlockColorMap<>(BLOCKS);\n    public static final BlockColorMap<CraftingMonitorBlock> CRAFTING_MONITOR = new BlockColorMap<>(BLOCKS);\n    public static final BlockColorMap<DetectorBlock> DETECTOR = new BlockColorMap<>(BLOCKS);\n    private static final String GRID_SUFFIX = \"_grid\";\n\n    static {\n        QUARTZ_ENRICHED_IRON = BLOCKS.register(\"quartz_enriched_iron_block\", QuartzEnrichedIronBlock::new);\n        MACHINE_CASING = BLOCKS.register(\"machine_casing\", MachineCasingBlock::new);\n        CABLE = BLOCKS.register(\"cable\", CableBlock::new);\n        DISK_DRIVE = BLOCKS.register(\"disk_drive\", DiskDriveBlock::new);\n        EXTERNAL_STORAGE = BLOCKS.register(\"external_storage\", ExternalStorageBlock::new);\n        IMPORTER = BLOCKS.register(\"importer\", ImporterBlock::new);\n        EXPORTER = BLOCKS.register(\"exporter\", ExporterBlock::new);\n        INTERFACE = BLOCKS.register(\"interface\", InterfaceBlock::new);\n        FLUID_INTERFACE = BLOCKS.register(\"fluid_interface\", FluidInterfaceBlock::new);\n        STORAGE_MONITOR = BLOCKS.register(\"storage_monitor\", StorageMonitorBlock::new);\n        CONSTRUCTOR = BLOCKS.register(\"constructor\", ConstructorBlock::new);\n        DESTRUCTOR = BLOCKS.register(\"destructor\", DestructorBlock::new);\n        CREATIVE_PORTABLE_GRID = BLOCKS.register(\"creative_portable_grid\", () -> new PortableGridBlock(PortableGridBlockItem.Type.CREATIVE));\n        PORTABLE_GRID = BLOCKS.register(\"portable_grid\", () -> new PortableGridBlock(PortableGridBlockItem.Type.NORMAL));\n\n        for (ItemStorageType type : ItemStorageType.values()) {\n            STORAGE_BLOCKS.put(type, BLOCKS.register(type.getName() + \"_storage_block\", () -> new StorageBlock(type)));\n        }\n\n        for (FluidStorageType type : FluidStorageType.values()) {\n            FLUID_STORAGE_BLOCKS.put(type, BLOCKS.register(type.getName() + \"_fluid_storage_block\", () -> new FluidStorageBlock(type)));\n        }\n\n        GRID.registerBlocks(\"grid\", () -> new GridBlock(GridType.NORMAL));\n        CRAFTING_GRID.registerBlocks(GridType.CRAFTING.getSerializedName() + GRID_SUFFIX, () -> new GridBlock(GridType.CRAFTING));\n        PATTERN_GRID.registerBlocks(GridType.PATTERN.getSerializedName() + GRID_SUFFIX, () -> new GridBlock(GridType.PATTERN));\n        FLUID_GRID.registerBlocks(GridType.FLUID.getSerializedName() + GRID_SUFFIX, () -> new GridBlock(GridType.FLUID));\n        CONTROLLER.registerBlocks(\"controller\", () -> new ControllerBlock(NetworkType.NORMAL));\n        CREATIVE_CONTROLLER.registerBlocks(\"creative_controller\", () -> new ControllerBlock(NetworkType.CREATIVE));\n        NETWORK_RECEIVER.registerBlocks(\"network_receiver\", NetworkReceiverBlock::new);\n        NETWORK_TRANSMITTER.registerBlocks(\"network_transmitter\", NetworkTransmitterBlock::new);\n        RELAY.registerBlocks(\"relay\", RelayBlock::new);\n        SECURITY_MANAGER.registerBlocks(\"security_manager\", SecurityManagerBlock::new);\n        WIRELESS_TRANSMITTER.registerBlocks(\"wireless_transmitter\", WirelessTransmitterBlock::new);\n        DISK_MANIPULATOR.registerBlocks(\"disk_manipulator\", DiskManipulatorBlock::new);\n        CRAFTER.registerBlocks(\"crafter\", CrafterBlock::new);\n        CRAFTER_MANAGER.registerBlocks(\"crafter_manager\", CrafterManagerBlock::new);\n        CRAFTING_MONITOR.registerBlocks(\"crafting_monitor\", CraftingMonitorBlock::new);\n        DETECTOR.registerBlocks(\"detector\", DetectorBlock::new);\n    }\n\n    private RSBlocks() {\n    }\n\n    public static void register(IEventBus bus) {\n        BLOCKS.register(bus);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/RSContainerMenus.java",
    "content": "package com.refinedmods.refinedstorage;\n\nimport com.refinedmods.refinedstorage.blockentity.*;\nimport com.refinedmods.refinedstorage.container.*;\nimport com.refinedmods.refinedstorage.container.factory.*;\n\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.world.inventory.MenuType;\nimport net.neoforged.neoforge.common.extensions.IMenuTypeExtension;\nimport net.neoforged.neoforge.registries.DeferredHolder;\nimport net.neoforged.neoforge.registries.DeferredRegister;\n\npublic final class RSContainerMenus {\n    public static final DeferredRegister<MenuType<?>> REGISTRY = DeferredRegister.create(BuiltInRegistries.MENU, RS.ID);\n\n    public static final DeferredHolder<MenuType<?>, MenuType<ControllerContainerMenu>>\n        CONTROLLER = REGISTRY.register(\"controller\", () -> IMenuTypeExtension.create(((windowId, inv, data) -> new ControllerContainerMenu(null, inv.player, windowId))));\n    public static final DeferredHolder<MenuType<?>, MenuType<GridContainerMenu>> GRID = REGISTRY.register(\"grid\", () -> IMenuTypeExtension.create(new GridContainerFactory()));\n    public static final DeferredHolder<MenuType<?>, MenuType<DetectorContainerMenu>> DETECTOR = REGISTRY.register(\"detector\", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory<DetectorContainerMenu, DetectorBlockEntity>((windowId, inv, blockEntity) -> new DetectorContainerMenu(blockEntity, inv.player, windowId))));\n    public static final DeferredHolder<MenuType<?>, MenuType<ExporterContainerMenu>> EXPORTER = REGISTRY.register(\"exporter\", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory<ExporterContainerMenu, ExporterBlockEntity>((windowId, inv, blockEntity) -> new ExporterContainerMenu(blockEntity, inv.player, windowId))));\n    public static final DeferredHolder<MenuType<?>, MenuType<ExternalStorageContainerMenu>> EXTERNAL_STORAGE = REGISTRY.register(\"external_storage\", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory<ExternalStorageContainerMenu, ExternalStorageBlockEntity>((windowId, inv, blockEntity) -> new ExternalStorageContainerMenu(blockEntity, inv.player, windowId))));\n    public static final DeferredHolder<MenuType<?>, MenuType<FilterContainerMenu>> FILTER = REGISTRY.register(\"filter\", () -> IMenuTypeExtension.create((windowId, inv, data) -> new FilterContainerMenu(inv.player, inv.getSelected(), windowId)));\n    public static final DeferredHolder<MenuType<?>, MenuType<ImporterContainerMenu>> IMPORTER = REGISTRY.register(\"importer\", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory<ImporterContainerMenu, ImporterBlockEntity>((windowId, inv, blockEntity) -> new ImporterContainerMenu(blockEntity, inv.player, windowId))));\n    public static final DeferredHolder<MenuType<?>, MenuType<NetworkTransmitterContainerMenu>> NETWORK_TRANSMITTER = REGISTRY.register(\"network_transmitter\", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory<NetworkTransmitterContainerMenu, NetworkTransmitterBlockEntity>((windowId, inv, blockEntity) -> new NetworkTransmitterContainerMenu(blockEntity, inv.player, windowId))));\n    public static final DeferredHolder<MenuType<?>, MenuType<RelayContainerMenu>> RELAY = REGISTRY.register(\"relay\", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory<RelayContainerMenu, RelayBlockEntity>((windowId, inv, blockEntity) -> new RelayContainerMenu(blockEntity, inv.player, windowId))));\n    public static final DeferredHolder<MenuType<?>, MenuType<DiskDriveContainerMenu>> DISK_DRIVE = REGISTRY.register(\"disk_drive\", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory<DiskDriveContainerMenu, DiskDriveBlockEntity>((windowId, inv, blockEntity) -> new DiskDriveContainerMenu(blockEntity, inv.player, windowId))));\n    public static final DeferredHolder<MenuType<?>, MenuType<StorageContainerMenu>> STORAGE_BLOCK = REGISTRY.register(\"storage_block\", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory<StorageContainerMenu, StorageBlockEntity>((windowId, inv, blockEntity) -> new StorageContainerMenu(blockEntity, inv.player, windowId))));\n    public static final DeferredHolder<MenuType<?>, MenuType<FluidStorageContainerMenu>> FLUID_STORAGE_BLOCK = REGISTRY.register(\"fluid_storage_block\", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory<FluidStorageContainerMenu, FluidStorageBlockEntity>((windowId, inv, blockEntity) -> new FluidStorageContainerMenu(blockEntity, inv.player, windowId))));\n    public static final DeferredHolder<MenuType<?>, MenuType<SecurityManagerContainerMenu>> SECURITY_MANAGER = REGISTRY.register(\"security_manager\", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory<SecurityManagerContainerMenu, SecurityManagerBlockEntity>((windowId, inv, blockEntity) -> new SecurityManagerContainerMenu(blockEntity, inv.player, windowId))));\n    public static final DeferredHolder<MenuType<?>, MenuType<InterfaceContainerMenu>> INTERFACE = REGISTRY.register(\"interface\", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory<InterfaceContainerMenu, InterfaceBlockEntity>((windowId, inv, blockEntity) -> new InterfaceContainerMenu(blockEntity, inv.player, windowId))));\n    public static final DeferredHolder<MenuType<?>, MenuType<FluidInterfaceContainerMenu>> FLUID_INTERFACE = REGISTRY.register(\"fluid_interface\", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory<FluidInterfaceContainerMenu, FluidInterfaceBlockEntity>((windowId, inv, blockEntity) -> new FluidInterfaceContainerMenu(blockEntity, inv.player, windowId))));\n    public static final DeferredHolder<MenuType<?>, MenuType<WirelessTransmitterContainerMenu>> WIRELESS_TRANSMITTER = REGISTRY.register(\"wireless_transmitter\", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory<WirelessTransmitterContainerMenu, WirelessTransmitterBlockEntity>((windowId, inv, blockEntity) -> new WirelessTransmitterContainerMenu(blockEntity, inv.player, windowId))));\n    public static final DeferredHolder<MenuType<?>, MenuType<StorageMonitorContainerMenu>> STORAGE_MONITOR = REGISTRY.register(\"storage_monitor\", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory<StorageMonitorContainerMenu, StorageMonitorBlockEntity>((windowId, inv, blockEntity) -> new StorageMonitorContainerMenu(blockEntity, inv.player, windowId))));\n    public static final DeferredHolder<MenuType<?>, MenuType<ConstructorContainerMenu>> CONSTRUCTOR = REGISTRY.register(\"constructor\", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory<ConstructorContainerMenu, ConstructorBlockEntity>((windowId, inv, blockEntity) -> new ConstructorContainerMenu(blockEntity, inv.player, windowId))));\n    public static final DeferredHolder<MenuType<?>, MenuType<DestructorContainerMenu>> DESTRUCTOR = REGISTRY.register(\"destructor\", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory<DestructorContainerMenu, DestructorBlockEntity>((windowId, inv, blockEntity) -> new DestructorContainerMenu(blockEntity, inv.player, windowId))));\n    public static final DeferredHolder<MenuType<?>, MenuType<DiskManipulatorContainerMenu>> DISK_MANIPULATOR = REGISTRY.register(\"disk_manipulator\", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory<DiskManipulatorContainerMenu, DiskManipulatorBlockEntity>((windowId, inv, blockEntity) -> new DiskManipulatorContainerMenu(blockEntity, inv.player, windowId))));\n    public static final DeferredHolder<MenuType<?>, MenuType<CrafterContainerMenu>> CRAFTER = REGISTRY.register(\"crafter\", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory<CrafterContainerMenu, CrafterBlockEntity>((windowId, inv, blockEntity) -> new CrafterContainerMenu(blockEntity, inv.player, windowId))));\n    public static final DeferredHolder<MenuType<?>, MenuType<CrafterManagerContainerMenu>> CRAFTER_MANAGER = REGISTRY.register(\"crafter_manager\", () -> IMenuTypeExtension.create(new CrafterManagerContainerFactory()));\n    public static final DeferredHolder<MenuType<?>, MenuType<CraftingMonitorContainerMenu>> CRAFTING_MONITOR = REGISTRY.register(\"crafting_monitor\", () -> IMenuTypeExtension.create(new CraftingMonitorContainerFactory()));\n    public static final DeferredHolder<MenuType<?>, MenuType<CraftingMonitorContainerMenu>> WIRELESS_CRAFTING_MONITOR = REGISTRY.register(\"wireless_crafting_monitor\", () -> IMenuTypeExtension.create(new WirelessCraftingMonitorContainerFactory()));\n\n    private RSContainerMenus() {\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/RSCreativeModeTabItems.java",
    "content": "package com.refinedmods.refinedstorage;\n\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;\nimport com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType;\nimport com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType;\nimport com.refinedmods.refinedstorage.item.*;\nimport com.refinedmods.refinedstorage.util.ColorMap;\n\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.*;\nimport net.minecraft.world.level.block.Block;\nimport net.minecraft.world.level.block.Blocks;\nimport net.neoforged.neoforge.registries.DeferredHolder;\nimport net.neoforged.neoforge.registries.RegisterEvent;\n\npublic class RSCreativeModeTabItems {\n    private RSCreativeModeTabItems() {\n    }\n\n    public static void register(RegisterEvent.RegisterHelper<CreativeModeTab> helper) {\n        helper.register(new ResourceLocation(RS.ID, \"general\"), CreativeModeTab.builder()\n            .title(Component.translatable(\"itemGroup.refinedstorage\"))\n            .icon(() -> new ItemStack(RSBlocks.CREATIVE_CONTROLLER.get(ColorMap.DEFAULT_COLOR).get()))\n            .displayItems((params, output) -> RSCreativeModeTabItems.append(output))\n            .build());\n    }\n\n    public static void append(CreativeModeTab.Output output) {\n        add(output, RSItems.CONSTRUCTION_CORE);\n        add(output, RSItems.DESTRUCTION_CORE);\n        add(output, RSItems.QUARTZ_ENRICHED_IRON);\n        add(output, RSItems.PROCESSOR_BINDING);\n        add(output, RSItems.PROCESSORS.get(ProcessorItem.Type.RAW_BASIC));\n        add(output, RSItems.PROCESSORS.get(ProcessorItem.Type.RAW_IMPROVED));\n        add(output, RSItems.PROCESSORS.get(ProcessorItem.Type.RAW_ADVANCED));\n        add(output, RSItems.PROCESSORS.get(ProcessorItem.Type.BASIC));\n        add(output, RSItems.PROCESSORS.get(ProcessorItem.Type.IMPROVED));\n        add(output, RSItems.PROCESSORS.get(ProcessorItem.Type.ADVANCED));\n        add(output, RSItems.SILICON);\n        add(output, RSItems.SECURITY_CARD);\n        add(output, RSItems.NETWORK_CARD);\n\n        add(output, ItemStorageType.ONE_K);\n        add(output, ItemStorageType.FOUR_K);\n        add(output, ItemStorageType.SIXTEEN_K);\n        add(output, ItemStorageType.SIXTY_FOUR_K);\n        add(output, ItemStorageType.CREATIVE);\n\n        add(output, FluidStorageType.SIXTY_FOUR_K);\n        add(output, FluidStorageType.TWO_HUNDRED_FIFTY_SIX_K);\n        add(output, FluidStorageType.THOUSAND_TWENTY_FOUR_K);\n        add(output, FluidStorageType.FOUR_THOUSAND_NINETY_SIX_K);\n        add(output, FluidStorageType.CREATIVE);\n\n        add(output, RSItems.STORAGE_HOUSING);\n\n        add(output, UpgradeItem.Type.NORMAL);\n        add(output, UpgradeItem.Type.SPEED);\n        add(output, UpgradeItem.Type.RANGE);\n        add(output, UpgradeItem.Type.CRAFTING);\n        add(output, UpgradeItem.Type.STACK);\n        add(output, UpgradeItem.Type.SILK_TOUCH);\n        add(output, UpgradeItem.Type.FORTUNE_1);\n        add(output, UpgradeItem.Type.FORTUNE_2);\n        add(output, UpgradeItem.Type.FORTUNE_3);\n        add(output, UpgradeItem.Type.REGULATOR);\n\n        add(output, RSItems.WRENCH);\n        add(output, RSItems.PATTERN);\n        add(output, RSItems.FILTER);\n\n        add(output, RSItems.WIRELESS_GRID);\n        add(output, RSItems.CREATIVE_WIRELESS_GRID);\n        add(output, RSItems.WIRELESS_FLUID_GRID);\n        add(output, RSItems.CREATIVE_WIRELESS_FLUID_GRID);\n        add(output, RSItems.WIRELESS_CRAFTING_MONITOR);\n        add(output, RSItems.CREATIVE_WIRELESS_CRAFTING_MONITOR);\n\n        add(output, RSItems.PORTABLE_GRID);\n        add(output, RSItems.CREATIVE_PORTABLE_GRID);\n        add(output, RSItems.QUARTZ_ENRICHED_IRON_BLOCK);\n        add(output, RSItems.MACHINE_CASING);\n        add(output, RSItems.CABLE);\n        add(output, RSItems.DISK_DRIVE);\n\n        addStorageBlock(output, ItemStorageType.ONE_K);\n        addStorageBlock(output, ItemStorageType.FOUR_K);\n        addStorageBlock(output, ItemStorageType.SIXTEEN_K);\n        addStorageBlock(output, ItemStorageType.SIXTY_FOUR_K);\n        addStorageBlock(output, ItemStorageType.CREATIVE);\n\n        addStorageBlock(output, FluidStorageType.SIXTY_FOUR_K);\n        addStorageBlock(output, FluidStorageType.TWO_HUNDRED_FIFTY_SIX_K);\n        addStorageBlock(output, FluidStorageType.THOUSAND_TWENTY_FOUR_K);\n        addStorageBlock(output, FluidStorageType.FOUR_THOUSAND_NINETY_SIX_K);\n        addStorageBlock(output, FluidStorageType.CREATIVE);\n\n        add(output, RSItems.EXTERNAL_STORAGE);\n        add(output, RSItems.IMPORTER);\n        add(output, RSItems.EXPORTER);\n        add(output, RSItems.INTERFACE);\n        add(output, RSItems.FLUID_INTERFACE);\n        add(output, RSItems.STORAGE_MONITOR);\n        add(output, RSItems.CONSTRUCTOR);\n        add(output, RSItems.DESTRUCTOR);\n        add(output, RSItems.CONTROLLER);\n        add(output, RSItems.CREATIVE_CONTROLLER);\n        add(output, RSItems.GRID);\n        add(output, RSItems.CRAFTING_GRID);\n        add(output, RSItems.PATTERN_GRID);\n        add(output, RSItems.FLUID_GRID);\n        add(output, RSItems.NETWORK_RECEIVER);\n        add(output, RSItems.NETWORK_TRANSMITTER);\n        add(output, RSItems.RELAY);\n        add(output, RSItems.DETECTOR);\n        add(output, RSItems.SECURITY_MANAGER);\n        add(output, RSItems.WIRELESS_TRANSMITTER);\n        add(output, RSItems.DISK_MANIPULATOR);\n        add(output, RSItems.CRAFTER);\n        add(output, RSItems.CRAFTER_MANAGER);\n        add(output, RSItems.CRAFTING_MONITOR);\n\n        addCovers(output);\n    }\n\n    private static void addCovers(CreativeModeTab.Output output) {\n        if (!RS.CLIENT_CONFIG.getCover().showAllRecipesInJEI()) {\n            ItemStack coverExampleStack = new ItemStack(Blocks.STONE_BRICKS);\n            addCovers(output, coverExampleStack);\n            return;\n        }\n        for (Block block : BuiltInRegistries.BLOCK) {\n            Item item = Item.byBlock(block);\n            if (item == Items.AIR) {\n                continue;\n            }\n            ItemStack itemStack = new ItemStack(item);\n            if (CoverManager.isValidCover(itemStack)) {\n                addCovers(output, itemStack);\n            }\n        }\n    }\n\n    private static void addCovers(CreativeModeTab.Output output, ItemStack coverExampleStack) {\n        ItemStack coverStack = new ItemStack(RSItems.COVER.get());\n        ItemStack hollowCoverStack = new ItemStack(RSItems.HOLLOW_COVER.get());\n        CoverItem.setItem(coverStack, coverExampleStack);\n        CoverItem.setItem(hollowCoverStack, coverExampleStack);\n        output.accept(coverStack);\n        output.accept(hollowCoverStack);\n    }\n\n    private static void add(CreativeModeTab.Output output, ColorMap<Item, ? extends Item> cm) {\n        cm.values().forEach(c -> add(output, c));\n    }\n\n    private static void add(CreativeModeTab.Output output, ItemStorageType type) {\n        DeferredHolder<Item, StoragePartItem> part = RSItems.ITEM_STORAGE_PARTS.get(type);\n        if (part != null) {\n            add(output, part);\n        }\n        add(output, RSItems.ITEM_STORAGE_DISKS.get(type));\n    }\n\n    private static void addStorageBlock(CreativeModeTab.Output output, ItemStorageType type) {\n        add(output, RSItems.STORAGE_BLOCKS.get(type));\n    }\n\n    private static void addStorageBlock(CreativeModeTab.Output output, FluidStorageType type) {\n        add(output, RSItems.FLUID_STORAGE_BLOCKS.get(type));\n    }\n\n    private static void add(CreativeModeTab.Output output, FluidStorageType type) {\n        DeferredHolder<Item, FluidStoragePartItem> part = RSItems.FLUID_STORAGE_PARTS.get(type);\n        if (part != null) {\n            add(output, part);\n        }\n        add(output, RSItems.FLUID_STORAGE_DISKS.get(type));\n    }\n\n    private static void add(CreativeModeTab.Output output, UpgradeItem.Type type) {\n        add(output, RSItems.UPGRADE_ITEMS.get(type));\n    }\n\n    private static void add(CreativeModeTab.Output output, DeferredHolder<Item, ? extends Item> ro) {\n        output.accept(ro.get());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/RSItems.java",
    "content": "package com.refinedmods.refinedstorage;\n\nimport com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType;\nimport com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType;\nimport com.refinedmods.refinedstorage.block.BaseBlock;\nimport com.refinedmods.refinedstorage.item.CoreItem;\nimport com.refinedmods.refinedstorage.item.CoverItem;\nimport com.refinedmods.refinedstorage.item.FilterItem;\nimport com.refinedmods.refinedstorage.item.FluidStorageDiskItem;\nimport com.refinedmods.refinedstorage.item.FluidStoragePartItem;\nimport com.refinedmods.refinedstorage.item.HollowCoverItem;\nimport com.refinedmods.refinedstorage.item.NetworkCardItem;\nimport com.refinedmods.refinedstorage.item.PatternItem;\nimport com.refinedmods.refinedstorage.item.ProcessorBindingItem;\nimport com.refinedmods.refinedstorage.item.ProcessorItem;\nimport com.refinedmods.refinedstorage.item.QuartzEnrichedIronItem;\nimport com.refinedmods.refinedstorage.item.SecurityCardItem;\nimport com.refinedmods.refinedstorage.item.SiliconItem;\nimport com.refinedmods.refinedstorage.item.StorageDiskItem;\nimport com.refinedmods.refinedstorage.item.StorageHousingItem;\nimport com.refinedmods.refinedstorage.item.StoragePartItem;\nimport com.refinedmods.refinedstorage.item.UpgradeItem;\nimport com.refinedmods.refinedstorage.item.WirelessCraftingMonitorItem;\nimport com.refinedmods.refinedstorage.item.WirelessFluidGridItem;\nimport com.refinedmods.refinedstorage.item.WirelessGridItem;\nimport com.refinedmods.refinedstorage.item.WrenchItem;\nimport com.refinedmods.refinedstorage.item.blockitem.BaseBlockItem;\nimport com.refinedmods.refinedstorage.item.blockitem.ControllerBlockItem;\nimport com.refinedmods.refinedstorage.item.blockitem.FluidStorageBlockItem;\nimport com.refinedmods.refinedstorage.item.blockitem.PortableGridBlockItem;\nimport com.refinedmods.refinedstorage.item.blockitem.StorageBlockItem;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.ColorMap;\nimport com.refinedmods.refinedstorage.util.ItemColorMap;\n\nimport java.util.ArrayList;\nimport java.util.EnumMap;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.tags.ItemTags;\nimport net.minecraft.tags.TagKey;\nimport net.minecraft.world.item.BlockItem;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.level.block.Block;\nimport net.neoforged.bus.api.IEventBus;\nimport net.neoforged.neoforge.registries.DeferredHolder;\nimport net.neoforged.neoforge.registries.DeferredRegister;\n\npublic final class RSItems {\n    public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(BuiltInRegistries.ITEM, RS.ID);\n\n    public static final DeferredHolder<Item, QuartzEnrichedIronItem> QUARTZ_ENRICHED_IRON;\n    public static final DeferredHolder<Item, SiliconItem> SILICON;\n    public static final DeferredHolder<Item, ProcessorBindingItem> PROCESSOR_BINDING;\n    public static final DeferredHolder<Item, WrenchItem> WRENCH;\n    public static final DeferredHolder<Item, PatternItem> PATTERN;\n    public static final DeferredHolder<Item, FilterItem> FILTER;\n    public static final DeferredHolder<Item, StorageHousingItem> STORAGE_HOUSING;\n    public static final DeferredHolder<Item, NetworkCardItem> NETWORK_CARD;\n    public static final DeferredHolder<Item, SecurityCardItem> SECURITY_CARD;\n    public static final DeferredHolder<Item, CoreItem> CONSTRUCTION_CORE;\n    public static final DeferredHolder<Item, CoreItem> DESTRUCTION_CORE;\n    public static final DeferredHolder<Item, WirelessGridItem> WIRELESS_GRID;\n    public static final DeferredHolder<Item, WirelessGridItem> CREATIVE_WIRELESS_GRID;\n    public static final DeferredHolder<Item, WirelessFluidGridItem> WIRELESS_FLUID_GRID;\n    public static final DeferredHolder<Item, WirelessFluidGridItem> CREATIVE_WIRELESS_FLUID_GRID;\n    public static final DeferredHolder<Item, PortableGridBlockItem> PORTABLE_GRID;\n    public static final DeferredHolder<Item, PortableGridBlockItem> CREATIVE_PORTABLE_GRID;\n    public static final DeferredHolder<Item, WirelessCraftingMonitorItem> WIRELESS_CRAFTING_MONITOR;\n    public static final DeferredHolder<Item, WirelessCraftingMonitorItem> CREATIVE_WIRELESS_CRAFTING_MONITOR;\n    public static final DeferredHolder<Item, BlockItem> MACHINE_CASING;\n    public static final DeferredHolder<Item, CoverItem> COVER;\n    public static final DeferredHolder<Item, CoverItem> HOLLOW_COVER;\n    public static final DeferredHolder<Item, BlockItem> QUARTZ_ENRICHED_IRON_BLOCK;\n    public static final DeferredHolder<Item, BlockItem> CABLE;\n    public static final DeferredHolder<Item, BlockItem> DISK_DRIVE;\n    public static final DeferredHolder<Item, BlockItem> EXTERNAL_STORAGE;\n    public static final DeferredHolder<Item, BlockItem> IMPORTER;\n    public static final DeferredHolder<Item, BlockItem> EXPORTER;\n    public static final DeferredHolder<Item, BlockItem> INTERFACE;\n    public static final DeferredHolder<Item, BlockItem> FLUID_INTERFACE;\n    public static final DeferredHolder<Item, BlockItem> STORAGE_MONITOR;\n    public static final DeferredHolder<Item, BlockItem> CONSTRUCTOR;\n    public static final DeferredHolder<Item, BlockItem> DESTRUCTOR;\n\n    public static final Map<ProcessorItem.Type, DeferredHolder<Item, ProcessorItem>> PROCESSORS =\n        new EnumMap<>(ProcessorItem.Type.class);\n\n    public static final Map<ItemStorageType, DeferredHolder<Item, StoragePartItem>> ITEM_STORAGE_PARTS =\n        new EnumMap<>(ItemStorageType.class);\n    public static final Map<ItemStorageType, DeferredHolder<Item, StorageDiskItem>> ITEM_STORAGE_DISKS =\n        new EnumMap<>(ItemStorageType.class);\n    public static final Map<ItemStorageType, DeferredHolder<Item, StorageBlockItem>> STORAGE_BLOCKS =\n        new EnumMap<>(ItemStorageType.class);\n\n    public static final Map<FluidStorageType, DeferredHolder<Item, FluidStoragePartItem>> FLUID_STORAGE_PARTS =\n        new EnumMap<>(FluidStorageType.class);\n    public static final Map<FluidStorageType, DeferredHolder<Item, FluidStorageDiskItem>> FLUID_STORAGE_DISKS =\n        new EnumMap<>(FluidStorageType.class);\n    public static final Map<FluidStorageType, DeferredHolder<Item, FluidStorageBlockItem>> FLUID_STORAGE_BLOCKS =\n        new EnumMap<>(FluidStorageType.class);\n\n    public static final Map<UpgradeItem.Type, DeferredHolder<Item, UpgradeItem>> UPGRADE_ITEMS =\n        new EnumMap<>(UpgradeItem.Type.class);\n\n    public static final Map<TagKey<Item>, ColorMap<Item, ?>> COLORED_ITEM_TAGS = new HashMap<>();\n\n    private static final List<Runnable> LATE_REGISTRATION = new ArrayList<>();\n\n    public static final ItemColorMap CRAFTER = new ItemColorMap(ITEMS, LATE_REGISTRATION);\n    public static final ItemColorMap RELAY = new ItemColorMap(ITEMS, LATE_REGISTRATION);\n    public static final ItemColorMap NETWORK_TRANSMITTER = new ItemColorMap(ITEMS, LATE_REGISTRATION);\n    public static final ItemColorMap NETWORK_RECEIVER = new ItemColorMap(ITEMS, LATE_REGISTRATION);\n    public static final ColorMap<Item, ControllerBlockItem> CONTROLLER = new ColorMap<>(ITEMS, LATE_REGISTRATION);\n    public static final ColorMap<Item, ControllerBlockItem> CREATIVE_CONTROLLER = new ColorMap<>(ITEMS, LATE_REGISTRATION);\n    public static final ItemColorMap GRID = new ItemColorMap(ITEMS, LATE_REGISTRATION);\n    public static final ItemColorMap CRAFTING_GRID = new ItemColorMap(ITEMS, LATE_REGISTRATION);\n    public static final ItemColorMap PATTERN_GRID = new ItemColorMap(ITEMS, LATE_REGISTRATION);\n    public static final ItemColorMap FLUID_GRID = new ItemColorMap(ITEMS, LATE_REGISTRATION);\n    public static final ItemColorMap SECURITY_MANAGER = new ItemColorMap(ITEMS, LATE_REGISTRATION);\n    public static final ItemColorMap WIRELESS_TRANSMITTER = new ItemColorMap(ITEMS, LATE_REGISTRATION);\n    public static final ItemColorMap DISK_MANIPULATOR = new ItemColorMap(ITEMS, LATE_REGISTRATION);\n    public static final ItemColorMap CRAFTER_MANAGER = new ItemColorMap(ITEMS, LATE_REGISTRATION);\n    public static final ItemColorMap CRAFTING_MONITOR = new ItemColorMap(ITEMS, LATE_REGISTRATION);\n    public static final ItemColorMap DETECTOR = new ItemColorMap(ITEMS, LATE_REGISTRATION);\n\n    static {\n        CONSTRUCTION_CORE = ITEMS.register(\"construction_core\", CoreItem::new);\n        DESTRUCTION_CORE = ITEMS.register(\"destruction_core\", CoreItem::new);\n        QUARTZ_ENRICHED_IRON = ITEMS.register(\"quartz_enriched_iron\", QuartzEnrichedIronItem::new);\n        PROCESSOR_BINDING = ITEMS.register(\"processor_binding\", ProcessorBindingItem::new);\n\n        for (ProcessorItem.Type type : ProcessorItem.Type.values()) {\n            PROCESSORS.put(type, ITEMS.register(type.getName() + \"_processor\", ProcessorItem::new));\n        }\n\n        SILICON = ITEMS.register(\"silicon\", SiliconItem::new);\n        SECURITY_CARD = ITEMS.register(\"security_card\", SecurityCardItem::new);\n        NETWORK_CARD = ITEMS.register(\"network_card\", NetworkCardItem::new);\n\n        for (ItemStorageType type : ItemStorageType.values()) {\n            if (type != ItemStorageType.CREATIVE) {\n                ITEM_STORAGE_PARTS.put(type, ITEMS.register(type.getName() + \"_storage_part\", StoragePartItem::new));\n            }\n\n            ITEM_STORAGE_DISKS.put(type,\n                ITEMS.register(type.getName() + \"_storage_disk\", () -> new StorageDiskItem(type)));\n        }\n\n        for (FluidStorageType type : FluidStorageType.values()) {\n            if (type != FluidStorageType.CREATIVE) {\n                FLUID_STORAGE_PARTS.put(type,\n                    ITEMS.register(type.getName() + \"_fluid_storage_part\", FluidStoragePartItem::new));\n            }\n\n            FLUID_STORAGE_DISKS.put(type,\n                ITEMS.register(type.getName() + \"_fluid_storage_disk\", () -> new FluidStorageDiskItem(type)));\n        }\n\n        STORAGE_HOUSING = ITEMS.register(\"storage_housing\", StorageHousingItem::new);\n\n        for (UpgradeItem.Type type : UpgradeItem.Type.values()) {\n            UPGRADE_ITEMS.put(type,\n                ITEMS.register(type == UpgradeItem.Type.NORMAL ? \"upgrade\" : type.getName() + \"_upgrade\",\n                    () -> new UpgradeItem(type)));\n        }\n\n        WRENCH = ITEMS.register(\"wrench\", WrenchItem::new);\n        PATTERN = ITEMS.register(\"pattern\", PatternItem::new);\n        FILTER = ITEMS.register(\"filter\", FilterItem::new);\n        PORTABLE_GRID =\n            ITEMS.register(\"portable_grid\", () -> new PortableGridBlockItem(PortableGridBlockItem.Type.NORMAL));\n        CREATIVE_PORTABLE_GRID = ITEMS.register(\"creative_portable_grid\",\n            () -> new PortableGridBlockItem(PortableGridBlockItem.Type.CREATIVE));\n\n        QUARTZ_ENRICHED_IRON_BLOCK = registerBlockItemFor(RSBlocks.QUARTZ_ENRICHED_IRON);\n        MACHINE_CASING = registerBlockItemFor(RSBlocks.MACHINE_CASING);\n        COVER = ITEMS.register(\"cover\", CoverItem::new);\n        HOLLOW_COVER = ITEMS.register(\"hollow_cover\", HollowCoverItem::new);\n        CABLE = registerBlockItemFor(RSBlocks.CABLE);\n        DISK_DRIVE = registerBlockItemFor(RSBlocks.DISK_DRIVE);\n\n        for (ItemStorageType type : ItemStorageType.values()) {\n            STORAGE_BLOCKS.put(type, ITEMS.register(RSBlocks.STORAGE_BLOCKS.get(type).getId().getPath(),\n                () -> new StorageBlockItem(RSBlocks.STORAGE_BLOCKS.get(type).get())));\n        }\n\n        for (FluidStorageType type : FluidStorageType.values()) {\n            FLUID_STORAGE_BLOCKS.put(type, ITEMS.register(RSBlocks.FLUID_STORAGE_BLOCKS.get(type).getId().getPath(),\n                () -> new FluidStorageBlockItem(RSBlocks.FLUID_STORAGE_BLOCKS.get(type).get())));\n        }\n\n        EXTERNAL_STORAGE = registerBlockItemFor(RSBlocks.EXTERNAL_STORAGE);\n        IMPORTER = registerBlockItemFor(RSBlocks.IMPORTER);\n        EXPORTER = registerBlockItemFor(RSBlocks.EXPORTER);\n        INTERFACE = registerBlockItemFor(RSBlocks.INTERFACE);\n        FLUID_INTERFACE = registerBlockItemFor(RSBlocks.FLUID_INTERFACE);\n        STORAGE_MONITOR = registerBlockItemFor(RSBlocks.STORAGE_MONITOR);\n        CONSTRUCTOR = registerBlockItemFor(RSBlocks.CONSTRUCTOR);\n        DESTRUCTOR = registerBlockItemFor(RSBlocks.DESTRUCTOR);\n\n        CONTROLLER.put(ColorMap.DEFAULT_COLOR, ITEMS.register(\n            RSBlocks.CONTROLLER.get(ColorMap.DEFAULT_COLOR).getId().getPath(),\n            () -> new ControllerBlockItem(\n                RSBlocks.CONTROLLER.get(ColorMap.DEFAULT_COLOR).get(),\n                ColorMap.DEFAULT_COLOR,\n                BlockUtils.getBlockTranslation(RSBlocks.CONTROLLER.get(ColorMap.DEFAULT_COLOR).get())\n            )\n        ));\n        CREATIVE_CONTROLLER.put(ColorMap.DEFAULT_COLOR, ITEMS.register(\n            RSBlocks.CREATIVE_CONTROLLER.get(ColorMap.DEFAULT_COLOR).getId().getPath(),\n            () -> new ControllerBlockItem(\n                RSBlocks.CREATIVE_CONTROLLER.get(ColorMap.DEFAULT_COLOR).get(),\n                ColorMap.DEFAULT_COLOR,\n                BlockUtils.getBlockTranslation(RSBlocks.CREATIVE_CONTROLLER.get(ColorMap.DEFAULT_COLOR).get())\n            )\n        ));\n\n        COLORED_ITEM_TAGS.put(\n            ItemTags.create(new ResourceLocation(RS.ID, CONTROLLER.get(ColorMap.DEFAULT_COLOR).getId().getPath())),\n            CONTROLLER\n        );\n\n        LATE_REGISTRATION.add(() -> {\n            RSBlocks.CONTROLLER.forEach((color, block) -> {\n                if (color != ColorMap.DEFAULT_COLOR) {\n                    CONTROLLER.put(color, ITEMS.register(RSBlocks.CONTROLLER.get(color).getId().getPath(),\n                        () -> new ControllerBlockItem(RSBlocks.CONTROLLER.get(color).get(), color,\n                            Component.translatable(\n                                RSBlocks.CONTROLLER.get(ColorMap.DEFAULT_COLOR).get().getDescriptionId()))));\n                }\n            });\n\n            RSBlocks.CREATIVE_CONTROLLER.forEach((color, block) -> {\n                if (color != ColorMap.DEFAULT_COLOR) {\n                    CREATIVE_CONTROLLER.put(color,\n                        ITEMS.register(RSBlocks.CREATIVE_CONTROLLER.get(color).getId().getPath(),\n                            () -> new ControllerBlockItem(RSBlocks.CREATIVE_CONTROLLER.get(color).get(), color,\n                                Component.translatable(RSBlocks.CREATIVE_CONTROLLER.get(ColorMap.DEFAULT_COLOR).get()\n                                    .getDescriptionId()))));\n                }\n            });\n        });\n\n        GRID.registerItemsFromBlocks(RSBlocks.GRID);\n        CRAFTING_GRID.registerItemsFromBlocks(RSBlocks.CRAFTING_GRID);\n        PATTERN_GRID.registerItemsFromBlocks(RSBlocks.PATTERN_GRID);\n        FLUID_GRID.registerItemsFromBlocks(RSBlocks.FLUID_GRID);\n        NETWORK_RECEIVER.registerItemsFromBlocks(RSBlocks.NETWORK_RECEIVER);\n        NETWORK_TRANSMITTER.registerItemsFromBlocks(RSBlocks.NETWORK_TRANSMITTER);\n        RELAY.registerItemsFromBlocks(RSBlocks.RELAY);\n        DETECTOR.registerItemsFromBlocks(RSBlocks.DETECTOR);\n        SECURITY_MANAGER.registerItemsFromBlocks(RSBlocks.SECURITY_MANAGER);\n        WIRELESS_TRANSMITTER.registerItemsFromBlocks(RSBlocks.WIRELESS_TRANSMITTER);\n        DISK_MANIPULATOR.registerItemsFromBlocks(RSBlocks.DISK_MANIPULATOR);\n        CRAFTER.registerItemsFromBlocks(RSBlocks.CRAFTER);\n        CRAFTER_MANAGER.registerItemsFromBlocks(RSBlocks.CRAFTER_MANAGER);\n        CRAFTING_MONITOR.registerItemsFromBlocks(RSBlocks.CRAFTING_MONITOR);\n\n        WIRELESS_GRID = ITEMS.register(\"wireless_grid\", () -> new WirelessGridItem(WirelessGridItem.Type.NORMAL));\n        CREATIVE_WIRELESS_GRID =\n            ITEMS.register(\"creative_wireless_grid\", () -> new WirelessGridItem(WirelessGridItem.Type.CREATIVE));\n        WIRELESS_FLUID_GRID =\n            ITEMS.register(\"wireless_fluid_grid\", () -> new WirelessFluidGridItem(WirelessFluidGridItem.Type.NORMAL));\n        CREATIVE_WIRELESS_FLUID_GRID = ITEMS.register(\"creative_wireless_fluid_grid\",\n            () -> new WirelessFluidGridItem(WirelessFluidGridItem.Type.CREATIVE));\n        WIRELESS_CRAFTING_MONITOR = ITEMS.register(\"wireless_crafting_monitor\",\n            () -> new WirelessCraftingMonitorItem(WirelessCraftingMonitorItem.Type.NORMAL));\n        CREATIVE_WIRELESS_CRAFTING_MONITOR = ITEMS.register(\"creative_wireless_crafting_monitor\",\n            () -> new WirelessCraftingMonitorItem(WirelessCraftingMonitorItem.Type.CREATIVE));\n\n        LATE_REGISTRATION.forEach(Runnable::run);\n    }\n\n    private RSItems() {\n    }\n\n    private static <T extends BaseBlock> DeferredHolder<Item, BlockItem> registerBlockItemFor(\n        DeferredHolder<Block, T> block) {\n        return ITEMS.register(block.getId().getPath(), () -> new BaseBlockItem(block.get(), new Item.Properties()));\n    }\n\n    public static void register(IEventBus bus) {\n        ITEMS.register(bus);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/RSKeyBindings.java",
    "content": "package com.refinedmods.refinedstorage;\n\nimport com.mojang.blaze3d.platform.InputConstants;\nimport net.minecraft.client.KeyMapping;\nimport net.neoforged.neoforge.client.settings.KeyConflictContext;\nimport net.neoforged.neoforge.client.settings.KeyModifier;\nimport org.lwjgl.glfw.GLFW;\n\npublic final class RSKeyBindings {\n    public static final KeyMapping FOCUS_SEARCH_BAR = new KeyMapping(\n        \"key.refinedstorage.focusSearchBar\",\n        KeyConflictContext.GUI,\n        InputConstants.Type.KEYSYM,\n        GLFW.GLFW_KEY_TAB,\n        RS.NAME\n    );\n\n    public static final KeyMapping CLEAR_GRID_CRAFTING_MATRIX = new KeyMapping(\n        \"key.refinedstorage.clearGridCraftingMatrix\",\n        KeyConflictContext.GUI,\n        KeyModifier.CONTROL,\n        InputConstants.Type.KEYSYM,\n        GLFW.GLFW_KEY_X,\n        RS.NAME\n    );\n\n    public static final KeyMapping OPEN_WIRELESS_GRID = new KeyMapping(\n        \"key.refinedstorage.openWirelessGrid\",\n        KeyConflictContext.IN_GAME,\n        InputConstants.UNKNOWN,\n        RS.NAME\n    );\n\n    public static final KeyMapping OPEN_WIRELESS_FLUID_GRID = new KeyMapping(\n        \"key.refinedstorage.openWirelessFluidGrid\",\n        KeyConflictContext.IN_GAME,\n        InputConstants.UNKNOWN,\n        RS.NAME\n    );\n\n    public static final KeyMapping OPEN_WIRELESS_CRAFTING_MONITOR = new KeyMapping(\n        \"key.refinedstorage.openWirelessCraftingMonitor\",\n        KeyConflictContext.IN_GAME,\n        InputConstants.UNKNOWN,\n        RS.NAME\n    );\n\n    public static final KeyMapping OPEN_PORTABLE_GRID = new KeyMapping(\n        \"key.refinedstorage.openPortableGrid\",\n        KeyConflictContext.IN_GAME,\n        InputConstants.UNKNOWN,\n        RS.NAME\n    );\n\n    private RSKeyBindings() {\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/RSLootFunctions.java",
    "content": "package com.refinedmods.refinedstorage;\n\nimport com.refinedmods.refinedstorage.loottable.ControllerLootFunction;\nimport com.refinedmods.refinedstorage.loottable.CrafterLootFunction;\nimport com.refinedmods.refinedstorage.loottable.PortableGridBlockLootFunction;\nimport com.refinedmods.refinedstorage.loottable.StorageBlockLootFunction;\n\nimport com.mojang.serialization.Codec;\nimport net.minecraft.core.Registry;\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.storage.loot.functions.LootItemFunctionType;\n\npublic final class RSLootFunctions {\n    public static LootItemFunctionType STORAGE_BLOCK;\n    public static LootItemFunctionType PORTABLE_GRID;\n    public static LootItemFunctionType CRAFTER;\n    public static LootItemFunctionType CONTROLLER;\n\n    private RSLootFunctions() {\n    }\n\n    public static void register() {\n        STORAGE_BLOCK =\n            Registry.register(BuiltInRegistries.LOOT_FUNCTION_TYPE, new ResourceLocation(RS.ID, \"storage_block\"),\n                new LootItemFunctionType(Codec.unit(new StorageBlockLootFunction())));\n        PORTABLE_GRID =\n            Registry.register(BuiltInRegistries.LOOT_FUNCTION_TYPE, new ResourceLocation(RS.ID, \"portable_grid\"),\n                new LootItemFunctionType(\n                    Codec.unit(new PortableGridBlockLootFunction())));\n        CRAFTER = Registry.register(BuiltInRegistries.LOOT_FUNCTION_TYPE, new ResourceLocation(RS.ID, \"crafter\"),\n            new LootItemFunctionType(Codec.unit(new CrafterLootFunction())));\n        CONTROLLER = Registry.register(BuiltInRegistries.LOOT_FUNCTION_TYPE, new ResourceLocation(RS.ID, \"controller\"),\n            new LootItemFunctionType(Codec.unit(new ControllerLootFunction())));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/RSRecipeSerializers.java",
    "content": "package com.refinedmods.refinedstorage;\n\nimport com.refinedmods.refinedstorage.recipe.CoverRecipe;\nimport com.refinedmods.refinedstorage.recipe.HollowCoverRecipe;\nimport com.refinedmods.refinedstorage.recipe.UpgradeWithEnchantedBookRecipeSerializer;\n\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.world.item.crafting.RecipeSerializer;\nimport net.neoforged.neoforge.registries.DeferredRegister;\n\npublic final class RSRecipeSerializers {\n    public static final DeferredRegister<RecipeSerializer<?>> REGISTRY = DeferredRegister.create(BuiltInRegistries.RECIPE_SERIALIZER, RS.ID);\n\n    static {\n        REGISTRY.register(\"upgrade_with_enchanted_book\", UpgradeWithEnchantedBookRecipeSerializer::new);\n        REGISTRY.register(\"cover_recipe\", () -> CoverRecipe.SERIALIZER);\n        REGISTRY.register(\"hollow_cover_recipe\", () -> HollowCoverRecipe.SERIALIZER);\n    }\n\n    private RSRecipeSerializers() {\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/IRSAPI.java",
    "content": "package com.refinedmods.refinedstorage.api;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternRenderHandler;\nimport com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementList;\nimport com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementRegistry;\nimport com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElementRegistry;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingRequestInfo;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTaskRegistry;\nimport com.refinedmods.refinedstorage.api.network.INetworkManager;\nimport com.refinedmods.refinedstorage.api.network.grid.ICraftingGridBehavior;\nimport com.refinedmods.refinedstorage.api.network.grid.IGridManager;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNodeManager;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNodeRegistry;\nimport com.refinedmods.refinedstorage.api.storage.StorageType;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskManager;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskRegistry;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskSync;\nimport com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorageProvider;\nimport com.refinedmods.refinedstorage.api.storage.tracker.IStorageTrackerManager;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.api.util.IQuantityFormatter;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * Represents a Refined Storage API implementation.\n * Delivered by the {@link RSAPIInject} annotation.\n */\npublic interface IRSAPI {\n    /**\n     * @return the comparer\n     */\n    @Nonnull\n    IComparer getComparer();\n\n    /**\n     * @return the quantity formatter\n     */\n    @Nonnull\n    IQuantityFormatter getQuantityFormatter();\n\n    /**\n     * @return the network node factory\n     */\n    @Nonnull\n    INetworkNodeRegistry getNetworkNodeRegistry();\n\n    /**\n     * Gets a network node manager for a given level.\n     *\n     * @param level level\n     * @return the network node manager for a given level\n     */\n    INetworkNodeManager getNetworkNodeManager(ServerLevel level);\n\n    /**\n     * Gets a network manager for a given level.\n     *\n     * @param level level\n     * @return the network manager for a given level\n     */\n    INetworkManager getNetworkManager(ServerLevel level);\n\n    /**\n     * @return the crafting task registry\n     */\n    @Nonnull\n    ICraftingTaskRegistry getCraftingTaskRegistry();\n\n    /**\n     * @return the crafting monitor element registry\n     */\n    @Nonnull\n    ICraftingMonitorElementRegistry getCraftingMonitorElementRegistry();\n\n    /**\n     * @return the crafting preview element registry\n     */\n    @Nonnull\n    ICraftingPreviewElementRegistry getCraftingPreviewElementRegistry();\n\n    /**\n     * @return an empty item stack list\n     */\n    @Nonnull\n    IStackList<ItemStack> createItemStackList();\n\n    /**\n     * @return an empty fluid stack list\n     */\n    @Nonnull\n    IStackList<FluidStack> createFluidStackList();\n\n    /**\n     * @return an empty crafting monitor element list\n     */\n    @Nonnull\n    ICraftingMonitorElementList createCraftingMonitorElementList();\n\n    /**\n     * @return the grid manager\n     */\n    @Nonnull\n    IGridManager getGridManager();\n\n    /**\n     * @return the default crafting grid behavior\n     */\n    @Nonnull\n    ICraftingGridBehavior getCraftingGridBehavior();\n\n    /**\n     * @return the storage disk registry\n     */\n    @Nonnull\n    IStorageDiskRegistry getStorageDiskRegistry();\n\n    /**\n     * @param level any level associated with the server\n     * @return the storage disk manager\n     */\n    @Nonnull\n    IStorageDiskManager getStorageDiskManager(ServerLevel level);\n\n    /**\n     * @return the storage disk sync manager\n     */\n    @Nonnull\n    IStorageDiskSync getStorageDiskSync();\n\n    /**\n     * @return the storage tracker manager\n     */\n    @Nonnull\n    IStorageTrackerManager getStorageTrackerManager(ServerLevel level);\n\n    /**\n     * Adds an external storage provider for the given storage type.\n     *\n     * @param type     the storage type\n     * @param provider the external storage provider\n     */\n    void addExternalStorageProvider(StorageType type, IExternalStorageProvider<?> provider);\n\n    /**\n     * @param type the type\n     * @return a set of external storage providers\n     */\n    <T> Set<IExternalStorageProvider<T>> getExternalStorageProviders(StorageType type);\n\n    /**\n     * @param level    the level\n     * @param capacity the capacity\n     * @param owner    the owner or null if no owner\n     * @return a storage disk\n     */\n    @Nonnull\n    IStorageDisk<ItemStack> createDefaultItemDisk(ServerLevel level, int capacity, @Nullable Player owner);\n\n    /**\n     * @param level    the level\n     * @param capacity the capacity in mB\n     * @param owner    the owner or null if no owner\n     * @return a fluid storage disk\n     */\n    @Nonnull\n    IStorageDisk<FluidStack> createDefaultFluidDisk(ServerLevel level, int capacity, @Nullable Player owner);\n\n    /**\n     * Creates crafting request info for an item.\n     *\n     * @param stack the stack\n     * @param count the count\n     * @return the request info\n     */\n    ICraftingRequestInfo createCraftingRequestInfo(ItemStack stack, int count);\n\n    /**\n     * Creates crafting request info for a fluid.\n     *\n     * @param stack the stack\n     * @param count the count\n     * @return the request info\n     */\n    ICraftingRequestInfo createCraftingRequestInfo(FluidStack stack, int count);\n\n    /**\n     * Creates crafting request info from NBT.\n     *\n     * @param tag the nbt tag\n     * @return the request info\n     */\n    ICraftingRequestInfo createCraftingRequestInfo(CompoundTag tag) throws CraftingTaskReadException;\n\n    /**\n     * @param renderHandler the render handler to add\n     */\n    void addPatternRenderHandler(ICraftingPatternRenderHandler renderHandler);\n\n    /**\n     * @return a list of pattern render handlers\n     */\n    List<ICraftingPatternRenderHandler> getPatternRenderHandlers();\n\n    /**\n     * @param stack the stack\n     * @return a hashcode for the given stack\n     */\n    int getItemStackHashCode(ItemStack stack);\n\n    /**\n     * @param stack the stack\n     * @return a hashcode for the given stack\n     */\n    int getFluidStackHashCode(FluidStack stack);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/RSAPIInject.java",
    "content": "package com.refinedmods.refinedstorage.api;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Target;\n\n/**\n * Needs to be implemented on a public static {@link IRSAPI} field.\n */\n@Target(ElementType.FIELD)\npublic @interface RSAPIInject {\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/autocrafting/ICraftingManager.java",
    "content": "package com.refinedmods.refinedstorage.api.autocrafting;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorListener;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICalculationResult;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.*;\n\n/**\n * The crafting manager handles the storing, updating, adding and deleting of crafting tasks in a network.\n */\npublic interface ICraftingManager {\n    /**\n     * @return the crafting tasks in this network, do NOT modify this\n     */\n    Collection<ICraftingTask> getTasks();\n\n    /**\n     * Returns a crafting task by id.\n     *\n     * @param id the id\n     * @return the task, or null if no task was found for the given id\n     */\n    @Nullable\n    ICraftingTask getTask(UUID id);\n\n    /**\n     * @return named crafting pattern containers\n     */\n    Map<Component, List<IItemHandlerModifiable>> getNamedContainers();\n\n    /**\n     * Starts a crafting task.\n     *\n     * @param task the task to start\n     */\n    void start(@Nonnull ICraftingTask task);\n\n    /**\n     * Cancels a crafting task.\n     *\n     * @param id the id of the task to cancel, or null to cancel all\n     */\n    void cancel(@Nullable UUID id);\n\n    /**\n     * Creates a crafting task for a given stack, but doesn't add it to the list.\n     *\n     * @param stack    the stack to craft\n     * @param quantity the quantity to craft\n     * @return the calculation result\n     */\n    ICalculationResult create(ItemStack stack, int quantity);\n\n    /**\n     * Creates a crafting task for a given stack, but doesn't add it to the list.\n     *\n     * @param stack    the stack to craft\n     * @param quantity the quantity to craft\n     * @return the calculation result\n     */\n    ICalculationResult create(FluidStack stack, int quantity);\n\n    /**\n     * Schedules a crafting task if the task isn't scheduled yet.\n     *\n     * @param source the source\n     * @param stack  the stack\n     * @param amount the amount of items to request\n     * @return the crafting task created, or null if no task is created\n     */\n    @Nullable\n    ICraftingTask request(Object source, ItemStack stack, int amount);\n\n    /**\n     * Schedules a crafting task if the task isn't scheduled yet.\n     *\n     * @param source the source\n     * @param stack  the stack\n     * @param amount the mB of the fluid to request\n     * @return the crafting task created, or null if no task is created\n     */\n    @Nullable\n    ICraftingTask request(Object source, FluidStack stack, int amount);\n\n    /**\n     * Tracks an incoming stack.\n     *\n     * @param stack the stack, can be empty\n     */\n    int track(@Nonnull ItemStack stack, int size);\n\n    /**\n     * Tracks an incoming stack.\n     *\n     * @param stack the stack, can be empty\n     */\n    int track(@Nonnull FluidStack stack, int size);\n\n    /**\n     * @return the crafting patterns in this network\n     */\n    List<ICraftingPattern> getPatterns();\n\n    /**\n     * Rebuilds the pattern list.\n     */\n    void invalidate();\n\n    /**\n     * Return a crafting pattern from an item stack.\n     *\n     * @param pattern the stack to get a pattern for\n     * @return the crafting pattern, or null if none is found\n     */\n    @Nullable\n    ICraftingPattern getPattern(ItemStack pattern);\n\n    /**\n     * Return a crafting pattern from a fluid stack.\n     *\n     * @param pattern the stack to get a pattern for\n     * @return the crafting pattern, or null if none is found\n     */\n    @Nullable\n    ICraftingPattern getPattern(FluidStack pattern);\n\n    /**\n     * Updates the tasks in this manager.\n     */\n    void update();\n\n    /**\n     * @param tag the tag to read from\n     */\n    void readFromNbt(CompoundTag tag);\n\n    /**\n     * @param tag the tag to write to\n     * @return the written tag\n     */\n    CompoundTag writeToNbt(CompoundTag tag);\n\n    /**\n     * @param listener the listener\n     */\n    void addListener(ICraftingMonitorListener listener);\n\n    /**\n     * @param listener the listener\n     */\n    void removeListener(ICraftingMonitorListener listener);\n\n    /**\n     * Calls all {@link ICraftingMonitorListener}s.\n     */\n    void onTaskChanged();\n\n    /**\n     * @param pattern pattern to look for\n     * @return a set with all containers that have this pattern\n     */\n    Set<ICraftingPatternContainer> getAllContainers(ICraftingPattern pattern);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/autocrafting/ICraftingPattern.java",
    "content": "package com.refinedmods.refinedstorage.api.autocrafting;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTaskRegistry;\nimport net.minecraft.core.NonNullList;\nimport net.minecraft.core.RegistryAccess;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nullable;\nimport java.util.List;\n\n/**\n * Represents a crafting pattern.\n */\npublic interface ICraftingPattern {\n    /**\n     * @return the {@link ICraftingPatternContainer} where the pattern is in\n     */\n    ICraftingPatternContainer getContainer();\n\n    /**\n     * @return the crafting pattern stack\n     */\n    ItemStack getStack();\n\n    /**\n     * @return true if the crafting pattern is valid, false otherwise\n     */\n    boolean isValid();\n\n    /**\n     * @return an error message when this pattern is not valid, or null if there's no message\n     */\n    @Nullable\n    Component getErrorMessage();\n\n    /**\n     * @return true if the crafting pattern can be treated as a processing pattern, false otherwise\n     */\n    boolean isProcessing();\n\n    /**\n     * @return the inputs per slot\n     */\n    List<NonNullList<ItemStack>> getInputs();\n\n    /**\n     * @return the outputs\n     */\n    NonNullList<ItemStack> getOutputs();\n\n    /**\n     * @param took           the items took per slot\n     * @param registryAccess the registry accessor\n     * @return the output based on the items took\n     */\n    ItemStack getOutput(NonNullList<ItemStack> took, RegistryAccess registryAccess);\n\n    /**\n     * @return the byproducts\n     */\n    NonNullList<ItemStack> getByproducts();\n\n    /**\n     * @param took the items took per slot\n     * @return the byproducts based on the items took\n     */\n    NonNullList<ItemStack> getByproducts(NonNullList<ItemStack> took);\n\n    /**\n     * @return the fluid inputs per slot\n     */\n    List<NonNullList<FluidStack>> getFluidInputs();\n\n    /**\n     * @return the fluid outputs\n     */\n    NonNullList<FluidStack> getFluidOutputs();\n\n    /**\n     * @return the id of the factory that creates a crafting task for this pattern, as defined in the {@link ICraftingTaskRegistry}\n     */\n    ResourceLocation getCraftingTaskFactoryId();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/autocrafting/ICraftingPatternContainer.java",
    "content": "package com.refinedmods.refinedstorage.api.autocrafting;\n\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.fluids.capability.IFluidHandler;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport org.apache.logging.log4j.LogManager;\n\nimport javax.annotation.Nullable;\nimport java.util.*;\nimport java.util.stream.Collectors;\nimport java.util.stream.IntStream;\n\n/**\n * Represents a network node that contains crafting patterns.\n */\npublic interface ICraftingPatternContainer {\n    /**\n     * Returns the interval of when a crafting step with a pattern in this container can update.\n     * Minimum value is 0 (each tick).\n     * <p>\n     * Note: rather than maxing out the update interval, implementors might want to balance around {@link #getMaximumSuccessfulCraftingUpdates()}.\n     * This method merely speeds up the update rate, it might be more interesting to increase the output rate in {@link #getMaximumSuccessfulCraftingUpdates()}.\n     *\n     * @return the update interval\n     */\n    default int getUpdateInterval() {\n        return 10;\n    }\n\n    /**\n     * Returns the amount of successful crafting updates that this container can have per crafting step update.\n     * If this limit is reached, crafting patterns from this container won't be able to update until the next\n     * eligible crafting step update interval from {@link #getUpdateInterval()}.\n     *\n     * @return the maximum amount of successful crafting updates\n     */\n    default int getMaximumSuccessfulCraftingUpdates() {\n        return 1;\n    }\n\n    /**\n     * @return the inventory that this container is connected to, or null if no inventory is present\n     */\n    @Nullable\n    IItemHandler getConnectedInventory();\n\n    /**\n     * @return the fluid inventory that this container is connected to, or null if no fluid inventory is present\n     */\n    @Nullable\n    IFluidHandler getConnectedFluidInventory();\n\n    /**\n     * @return the block entity that this container is connected to, or null if no block entity is present\n     */\n    @Nullable\n    BlockEntity getConnectedBlockEntity();\n\n    /**\n     * @return the block entity that this container is facing\n     */\n    BlockEntity getFacingBlockEntity();\n\n    /**\n     * @return the direction to the facing block entity\n     */\n    Direction getDirection();\n\n    /**\n     * @return the patterns stored in this container\n     */\n    List<ICraftingPattern> getPatterns();\n\n    /**\n     * @return the pattern inventory, or null if no pattern inventory is present\n     */\n    @Nullable\n    IItemHandlerModifiable getPatternInventory();\n\n    /**\n     * The name of this container for categorizing in the Crafting Manager GUI.\n     * Will return the name of the root container if we're in a chained scenario.\n     *\n     * @return the name of this container\n     */\n    Component getName();\n\n    /**\n     * The custom name of this container, as set in an anvil for example.\n     * Can be null.\n     *\n     * @return the name of this container\n     */\n    @Nullable\n    default Component getCustomName() {\n        return null;\n    }\n\n    /**\n     * @return the position of this container\n     */\n    BlockPos getPosition();\n\n    /**\n     * Containers may be daisy-chained together.  If this container points to\n     * another one, gets the root container in the chain.  If containers are\n     * not daisy-chained, returns this container.  If there was a container\n     * loop, returns null.\n     *\n     * @return the root pattern container\n     */\n    @Nullable\n    ICraftingPatternContainer getRootContainer();\n\n    /**\n     * @return the UUID of this container\n     */\n    UUID getUuid();\n\n    /**\n     * @return true if the connected inventory is locked for processing patterns, false otherwise\n     */\n    default boolean isLocked() {\n        return false;\n    }\n\n    /**\n     * Unlock the container so it may be used by processing pattern\n     */\n    void unlock();\n\n    /**\n     * Called when this container is used by a processing pattern to insert items or fluids in the connected inventory.\n     */\n    default void onUsedForProcessing() {\n    }\n\n    /**\n     * @return whether the container is successfully connected to the inventory it wants to insert to\n     */\n    default boolean hasConnectedInventory() {\n        return getConnectedInventory() != null;\n    }\n\n    /**\n     * @return whether the container is successfully connected to the fluid inventory it wants to insert to\n     */\n    default boolean hasConnectedFluidInventory() {\n        return getConnectedFluidInventory() != null;\n    }\n\n    /**\n     * Called by Autocrafting when it uses this crafter in a processing recipe that has items as input\n     *\n     * @param toInsert Collection of Itemstack stacklist entries to insert into the inventory\n     * @param action   action to perform\n     * @return whether insertion was successful\n     */\n    default boolean insertItemsIntoInventory(Collection<ItemStack> toInsert, Action action) {\n        IItemHandler dest = getConnectedInventory();\n\n\n        if (toInsert.isEmpty()) {\n            return true;\n        }\n\n        if (dest == null) {\n            return false;\n        }\n\n        Deque<ItemStack> stacks = new ArrayDeque<>(toInsert);\n\n\n        ItemStack current = stacks.poll();\n\n        List<Integer> availableSlots = IntStream.range(0, dest.getSlots()).boxed().collect(Collectors.toList());\n\n        while (current != null && !availableSlots.isEmpty()) {\n            ItemStack remainder = ItemStack.EMPTY;\n\n            for (int i = 0; i < availableSlots.size(); ++i) {\n                int slot = availableSlots.get(i);\n\n                // .copy() is mandatory!\n                remainder = dest.insertItem(slot, current.copy(), action == Action.SIMULATE);\n\n                // If we inserted *something*\n                if (remainder.isEmpty() || current.getCount() != remainder.getCount()) {\n                    availableSlots.remove(i);\n                    break;\n                }\n            }\n\n            if (remainder.isEmpty()) { // If we inserted successfully, get a next stack.\n                current = stacks.poll();\n\n            } else if (current.getCount() == remainder.getCount()) { // If we didn't insert anything over ALL these slots, stop here.\n                break;\n            } else { // If we didn't insert all, continue with other slots and use our remainder.\n                current = remainder;\n            }\n        }\n\n        boolean success = current == null && stacks.isEmpty();\n\n        if (!success && action == Action.PERFORM) {\n            LogManager.getLogger().warn(\"Inventory unexpectedly didn't accept {}, the remainder has been voided!\", current != null ? current.getDescriptionId() : null);\n        }\n\n        return success;\n    }\n\n    /**\n     * Called by Autocrafting when it uses this crafter in a processing recipe that has fluids as input\n     *\n     * @param toInsert Collection of Fluidstack stacklist entries to insert into the inventory\n     * @param action   action to perform\n     * @return whether insertion was successful\n     */\n    default boolean insertFluidsIntoInventory(Collection<FluidStack> toInsert, Action action) {\n        IFluidHandler dest = getConnectedFluidInventory();\n\n        if (toInsert.isEmpty()) {\n            return true;\n        }\n\n        if (dest == null) {\n            return false;\n        }\n\n        for (FluidStack stack : toInsert) {\n            int filled = dest.fill(stack, action == Action.SIMULATE ? IFluidHandler.FluidAction.SIMULATE : IFluidHandler.FluidAction.EXECUTE);\n\n            if (filled != stack.getAmount()) {\n                if (action == Action.PERFORM) {\n                    LogManager.getLogger().warn(\"Inventory unexpectedly didn't accept all of {}, the remainder has been voided!\", stack.getTranslationKey());\n                }\n\n                return false;\n            }\n        }\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/autocrafting/ICraftingPatternProvider.java",
    "content": "package com.refinedmods.refinedstorage.api.autocrafting;\n\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\n\nimport javax.annotation.Nonnull;\n\n/**\n * Implement this interface on crafting pattern items.\n * When this interface is implemented on the item in question, they will be insertable in crafters.\n */\npublic interface ICraftingPatternProvider {\n    /**\n     * Creates a crafting pattern.\n     *\n     * @param level     the level\n     * @param stack     the pattern stack, the implementor needs to copy it\n     * @param container the {@link ICraftingPatternContainer} where the pattern is in\n     * @return the crafting pattern\n     */\n    @Nonnull\n    ICraftingPattern create(Level level, ItemStack stack, ICraftingPatternContainer container);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/autocrafting/ICraftingPatternRenderHandler.java",
    "content": "package com.refinedmods.refinedstorage.api.autocrafting;\n\nimport com.refinedmods.refinedstorage.api.IRSAPI;\nimport net.minecraft.world.item.ItemStack;\n\n/**\n * Defines the behavior of pattern rendering.\n * One can add this interface through {@link IRSAPI#addPatternRenderHandler(ICraftingPatternRenderHandler)}.\n */\npublic interface ICraftingPatternRenderHandler {\n    /**\n     * Returns true if the pattern can render its output.\n     * As soon as one {@link ICraftingPatternRenderHandler} returns true for this method, it will render the output.\n     *\n     * @param pattern the pattern\n     * @return true if this pattern can render its output, false otherwise\n     */\n    boolean canRenderOutput(ItemStack pattern);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/autocrafting/craftingmonitor/ICraftingMonitorElement.java",
    "content": "package com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor;\n\nimport com.refinedmods.refinedstorage.api.render.IElementDrawers;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementList;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.api.distmarker.Dist;\nimport net.neoforged.api.distmarker.OnlyIn;\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * Represents a crafting monitor element.\n */\npublic interface ICraftingMonitorElement {\n    /**\n     * @param graphics the graphics\n     * @param x        position on the x axis to render\n     * @param y        position on the y axis to render\n     * @param drawers  the drawers that this element can use\n     */\n    @OnlyIn(Dist.CLIENT)\n    void draw(GuiGraphics graphics, int x, int y, IElementDrawers drawers);\n\n    /**\n     * Returns the id for the base of this element, used for sorting in the {@link CraftingMonitorElementList}\n     *\n     * @return the id\n     */\n    ResourceLocation getBaseId();\n\n    /**\n     * Returns the id of this element, used for serialization and deserialization over the network.\n     *\n     * @return the id\n     */\n    ResourceLocation getId();\n\n    /**\n     * @return the tooltip of this element\n     */\n    default List<Component> getTooltip() {\n        return Collections.emptyList();\n    }\n\n    /**\n     * Writes the data to the network.\n     *\n     * @param buf the buffer\n     */\n    void write(FriendlyByteBuf buf);\n\n    /**\n     * Merge an element into the current element.\n     *\n     * @param element the element to merged with the current one\n     * @return true if merge was successful, false otherwise\n     */\n    boolean merge(ICraftingMonitorElement element);\n\n    /**\n     * @return the hash code for the underlying base item/fluid element\n     */\n    int baseElementHashCode();\n\n    /**\n     * @return the hash code for the underlying element\n     */\n    int elementHashCode();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/autocrafting/craftingmonitor/ICraftingMonitorElementList.java",
    "content": "package com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor;\n\nimport java.util.List;\n\npublic interface ICraftingMonitorElementList {\n    /**\n     * Directly add to the underlying list without trying to merge.\n     *\n     * @param element the {@link ICraftingMonitorElement}\n     */\n    void directAdd(ICraftingMonitorElement element);\n\n    /**\n     * Add a element to the Storage list, similar elements will be merged.\n     * A {@link #commit()} will stop any following adds to be merged with previous ones.\n     *\n     * @param element the {@link ICraftingMonitorElement}\n     */\n    void addStorage(ICraftingMonitorElement element);\n\n    /**\n     * Add a element to the Processing or Crafting list, similar elements will be merged.\n     * A {@link #commit()} will stop any following adds to be merged with previous ones.\n     *\n     * @param element      the {@link ICraftingMonitorElement}\n     * @param isProcessing whether to add to the processing list or the crafting list\n     */\n    void add(ICraftingMonitorElement element, boolean isProcessing);\n\n    /**\n     * Add a element to the list, similar elements will be merged.\n     * A {@link #commit()} will stop any following adds to be merged with previous ones.\n     *\n     * @param element the {@link ICraftingMonitorElement}\n     */\n    void add(ICraftingMonitorElement element);\n\n    /**\n     * Finishes a current merge operation.\n     */\n    void commit();\n\n    /**\n     * Gets all the elements in the list.\n     * This also commits the last changes.\n     *\n     * @return the current list of elements\n     */\n    List<ICraftingMonitorElement> getElements();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/autocrafting/craftingmonitor/ICraftingMonitorElementRegistry.java",
    "content": "package com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.resources.ResourceLocation;\n\nimport javax.annotation.Nullable;\nimport java.util.function.Function;\n\n/**\n * This registry holds factories for crafting monitor elements (for serialization and deserialization over the network).\n */\npublic interface ICraftingMonitorElementRegistry {\n    /**\n     * Adds a factory to the registry.\n     *\n     * @param id      the id, as specified in {@link ICraftingMonitorElement#getId()}\n     * @param factory the factory\n     */\n    void add(ResourceLocation id, Function<FriendlyByteBuf, ICraftingMonitorElement> factory);\n\n    /**\n     * Returns a factory from the registry.\n     *\n     * @param id the id, as specified in {@link ICraftingMonitorElement#getId()}\n     * @return the factory, or null if no factory was found\n     */\n    @Nullable\n    Function<FriendlyByteBuf, ICraftingMonitorElement> get(ResourceLocation id);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/autocrafting/craftingmonitor/ICraftingMonitorListener.java",
    "content": "package com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager;\n\n/**\n * Add this listener to a {@link ICraftingManager} to listen to crafting task changes.\n */\npublic interface ICraftingMonitorListener {\n    /**\n     * Called when this listener is attached to a {@link ICraftingManager}.\n     */\n    void onAttached();\n\n    /**\n     * Called when any task changes.\n     */\n    void onChanged();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/autocrafting/preview/ICraftingPreviewElement.java",
    "content": "package com.refinedmods.refinedstorage.api.autocrafting.preview;\n\nimport com.refinedmods.refinedstorage.api.render.IElementDrawers;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.api.distmarker.Dist;\nimport net.neoforged.api.distmarker.OnlyIn;\n\n/**\n * Represents a crafting preview element.\n */\npublic interface ICraftingPreviewElement {\n    /**\n     * @param graphics the graphics\n     * @param x        position on the x axis to render\n     * @param y        position on the y axis to render\n     * @param drawers  the drawers this element can use\n     */\n    @OnlyIn(Dist.CLIENT)\n    void draw(GuiGraphics graphics, int x, int y, IElementDrawers drawers);\n\n    /**\n     * @return true when this crafting preview elements signifies an error that disables starting a task\n     */\n    boolean doesDisableTaskStarting();\n\n    /**\n     * @param buf buffer to write to\n     */\n    void write(FriendlyByteBuf buf);\n\n    /**\n     * Returns the id of this element, used for serialization and deserialization over the network.\n     *\n     * @return the id\n     */\n    ResourceLocation getId();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/autocrafting/preview/ICraftingPreviewElementRegistry.java",
    "content": "package com.refinedmods.refinedstorage.api.autocrafting.preview;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.resources.ResourceLocation;\n\nimport javax.annotation.Nullable;\nimport java.util.function.Function;\n\n/**\n * This registry holds factories for crafting preview elements (for serialization and deserialization over the network).\n */\npublic interface ICraftingPreviewElementRegistry {\n    /**\n     * Adds a factory to the registry.\n     *\n     * @param id      the id, as specified in {@link ICraftingPreviewElement#getId()}\n     * @param factory the factory\n     */\n    void add(ResourceLocation id, Function<FriendlyByteBuf, ICraftingPreviewElement> factory);\n\n    /**\n     * Returns a factory from the registry.\n     *\n     * @param id the id, as specified in {@link ICraftingPreviewElement#getId()}\n     * @return the factory, or null if no factory was found\n     */\n    @Nullable\n    Function<FriendlyByteBuf, ICraftingPreviewElement> get(ResourceLocation id);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/autocrafting/task/CalculationResultType.java",
    "content": "package com.refinedmods.refinedstorage.api.autocrafting.task;\n\n/**\n * The result type.\n */\npublic enum CalculationResultType {\n    /**\n     * No problems.\n     */\n    OK,\n    /**\n     * Some requirements are missing.\n     */\n    MISSING,\n    /**\n     * There is no pattern for the requested stack.\n     */\n    NO_PATTERN,\n    /**\n     * When the crafting task would cause too much server strain or is too complex.\n     */\n    TOO_COMPLEX,\n    /**\n     * When one of the used patterns during the calculation reuses itself again and would cause an infinite loop.\n     */\n    RECURSIVE;\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/autocrafting/task/CraftingTaskReadException.java",
    "content": "package com.refinedmods.refinedstorage.api.autocrafting.task;\n\nimport com.refinedmods.refinedstorage.api.network.INetwork;\n\n/**\n * Gets thrown from {@link ICraftingTaskFactory#createFromNbt(INetwork, net.minecraft.nbt.CompoundNBT)}.\n */\npublic class CraftingTaskReadException extends Exception {\n    /**\n     * @param message the message\n     */\n    public CraftingTaskReadException(String message) {\n        super(message);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/autocrafting/task/ICalculationResult.java",
    "content": "package com.refinedmods.refinedstorage.api.autocrafting.task;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;\n\nimport javax.annotation.Nullable;\nimport java.util.List;\n\n/**\n * The result of the crafting calculation.\n */\npublic interface ICalculationResult {\n    /**\n     * @return the type\n     */\n    CalculationResultType getType();\n\n    /**\n     * @return get a list of preview elements\n     */\n    List<ICraftingPreviewElement> getPreviewElements();\n\n    /**\n     * @return the task if the calculation {@link #isOk()}, otherwise null\n     */\n    @Nullable\n    ICraftingTask getTask();\n\n    /**\n     * @return whether the calculation succeeded\n     */\n    boolean isOk();\n\n    /**\n     * If this result type is a {@link CalculationResultType#RECURSIVE}, the recursed pattern will be returned here.\n     *\n     * @return the recursed pattern, or null if this result is not {@link CalculationResultType#RECURSIVE}\n     */\n    @Nullable\n    ICraftingPattern getRecursedPattern();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/autocrafting/task/ICraftingRequestInfo.java",
    "content": "package com.refinedmods.refinedstorage.api.autocrafting.task;\n\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nullable;\n\n/**\n * Contains information about a crafting request.\n */\npublic interface ICraftingRequestInfo {\n    /**\n     * @return the item requested, or null if no item was requested\n     */\n    @Nullable\n    ItemStack getItem();\n\n    /**\n     * @return the fluid requested, or null if no fluid was requested\n     */\n    @Nullable\n    FluidStack getFluid();\n\n    /**\n     * @return the written tag\n     */\n    CompoundTag writeToNbt();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/autocrafting/task/ICraftingTask.java",
    "content": "package com.refinedmods.refinedstorage.api.autocrafting.task;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport java.util.List;\nimport java.util.UUID;\n\n/**\n * Represents a crafting task.\n */\npublic interface ICraftingTask {\n    /**\n     * Updates this task.\n     *\n     * @return true if this crafting task is finished, false otherwise\n     */\n    boolean update();\n\n    /**\n     * Called when this task is cancelled.\n     */\n    void onCancelled();\n\n    /**\n     * @return the amount of items that have to be crafted\n     */\n    int getQuantity();\n\n    /**\n     * @return the completion percentage\n     */\n    int getCompletionPercentage();\n\n    /**\n     * @return the stack requested\n     */\n    ICraftingRequestInfo getRequested();\n\n    /**\n     * Called when a stack is inserted into the system through {@link INetwork#insertItemTracked(ItemStack, int)}.\n     *\n     * @param stack the stack\n     * @return the remainder of this stack after processing of the task\n     */\n    int onTrackedInsert(ItemStack stack, int size);\n\n    /**\n     * Called when a stack is inserted into the system through {@link INetwork#insertFluidTracked(FluidStack, int)}.\n     *\n     * @param stack the stack\n     * @return the remainder of this stack after processing of the task\n     */\n    int onTrackedInsert(FluidStack stack, int size);\n\n    /**\n     * Writes this task to NBT.\n     *\n     * @param tag the tag\n     * @return the written tag\n     */\n    CompoundTag writeToNbt(CompoundTag tag);\n\n    /**\n     * @return the elements of this task for display in the crafting monitor\n     */\n    List<ICraftingMonitorElement> getCraftingMonitorElements();\n\n    /**\n     * @return the crafting pattern corresponding to this task\n     */\n    ICraftingPattern getPattern();\n\n    /**\n     * @return the unix time in ms when this task has started\n     */\n    long getStartTime();\n\n    /**\n     * @return the id of this task\n     */\n    UUID getId();\n\n    /**\n     * Start the CraftingTask\n     */\n    void start();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/autocrafting/task/ICraftingTaskFactory.java",
    "content": "package com.refinedmods.refinedstorage.api.autocrafting.task;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport net.minecraft.nbt.CompoundTag;\n\n/**\n * A factory that creates a crafting task.\n * Register this factory in the {@link ICraftingTaskRegistry}.\n */\npublic interface ICraftingTaskFactory {\n    /**\n     * Returns a crafting task for a given pattern.\n     *\n     * @param network   the network\n     * @param requested the request info\n     * @param pattern   the pattern\n     * @param quantity  the quantity\n     * @return the calculation result\n     */\n    ICalculationResult create(INetwork network, ICraftingRequestInfo requested, int quantity, ICraftingPattern pattern);\n\n    /**\n     * Returns a crafting task for a given NBT tag.\n     *\n     * @param network the network\n     * @param tag     the tag\n     * @return the crafting task\n     */\n    ICraftingTask createFromNbt(INetwork network, CompoundTag tag) throws CraftingTaskReadException;\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/autocrafting/task/ICraftingTaskRegistry.java",
    "content": "package com.refinedmods.refinedstorage.api.autocrafting.task;\n\nimport net.minecraft.resources.ResourceLocation;\n\nimport javax.annotation.Nullable;\n\n/**\n * A registry that stores crafting task factories.\n * Implement this to handle the loading of custom crafting tasks.\n */\npublic interface ICraftingTaskRegistry {\n    /**\n     * Adds a crafting task factory to the registry.\n     * The id is used for identifying tasks when they are read from disk.\n     *\n     * @param id      the id of the factory\n     * @param factory the factory\n     */\n    void add(ResourceLocation id, ICraftingTaskFactory factory);\n\n    /**\n     * Returns the crafting task factory by factory id.\n     *\n     * @param id the factory id\n     * @return the factory, or null if there is no factory\n     */\n    @Nullable\n    ICraftingTaskFactory get(ResourceLocation id);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/INetwork.java",
    "content": "package com.refinedmods.refinedstorage.api.network;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler;\nimport com.refinedmods.refinedstorage.api.network.item.INetworkItemManager;\nimport com.refinedmods.refinedstorage.api.network.security.ISecurityManager;\nimport com.refinedmods.refinedstorage.api.storage.IStorage;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;\nimport com.refinedmods.refinedstorage.api.storage.tracker.IStorageTracker;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.energy.IEnergyStorage;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nonnull;\nimport java.util.function.Predicate;\n\n/**\n * Represents a network.\n */\npublic interface INetwork {\n    /**\n     * @return the energy usage per tick of this network\n     */\n    int getEnergyUsage();\n\n    /**\n     * @return the energy storage\n     */\n    IEnergyStorage getEnergyStorage();\n\n    /**\n     * @return the network type\n     */\n    NetworkType getType();\n\n    /**\n     * @return true if this network is able to run (usually corresponds to the redstone configuration), false otherwise\n     */\n    boolean canRun();\n\n    /**\n     * Updates the network.\n     */\n    void update();\n\n    /**\n     * Called when the network is removed.\n     */\n    void onRemoved();\n\n    /**\n     * @return a graph of connected nodes to this network\n     */\n    INetworkNodeGraph getNodeGraph();\n\n    /**\n     * @return the {@link ISecurityManager} of this network\n     */\n    ISecurityManager getSecurityManager();\n\n    /**\n     * @return the {@link ICraftingManager} of this network\n     */\n    ICraftingManager getCraftingManager();\n\n    /**\n     * @return the {@link IItemGridHandler} of this network\n     */\n    IItemGridHandler getItemGridHandler();\n\n    /**\n     * @return the {@link IFluidGridHandler} of this network\n     */\n    IFluidGridHandler getFluidGridHandler();\n\n    /**\n     * @return the {@link INetworkItemManager} of this network\n     */\n    INetworkItemManager getNetworkItemManager();\n\n    /**\n     * @return the {@link IStorageCache<ItemStack>} of this network\n     */\n    IStorageCache<ItemStack> getItemStorageCache();\n\n    /**\n     * @return the {@link IStorageCache<FluidStack>} of this network\n     */\n    IStorageCache<FluidStack> getFluidStorageCache();\n\n    /**\n     * Inserts an item in this network.\n     *\n     * @param stack  the stack prototype to insert, can be empty, do NOT modify\n     * @param size   the amount of that prototype that has to be inserted\n     * @param action the action\n     * @return an empty stack if the insert was successful, or a stack with the remainder\n     */\n    @Nonnull\n    ItemStack insertItem(@Nonnull ItemStack stack, int size, Action action);\n\n    /**\n     * Inserts an item and notifies the crafting manager of the incoming item.\n     *\n     * @param stack the stack prototype to insert, can be empty, do NOT modify\n     * @param size  the amount of that prototype that has to be inserted\n     * @return an empty stack if the insert was successful, or a stack with the remainder\n     */\n    @Nonnull\n    default ItemStack insertItemTracked(@Nonnull ItemStack stack, int size) {\n        int remainder = getCraftingManager().track(stack, size);\n\n        if (remainder == 0) {\n            return ItemStack.EMPTY;\n        }\n\n        return insertItem(stack, remainder, Action.PERFORM);\n    }\n\n    /**\n     * Extracts an item from this network.\n     *\n     * @param stack  the prototype of the stack to extract, do NOT modify\n     * @param size   the amount of that prototype that has to be extracted\n     * @param flags  the flags to compare on, see {@link IComparer}\n     * @param action the action\n     * @param filter a filter for the storage\n     * @return an empty stack if nothing was extracted, or a stack with the result\n     */\n    @Nonnull\n    ItemStack extractItem(@Nonnull ItemStack stack, int size, int flags, Action action, Predicate<IStorage<ItemStack>> filter);\n\n    /**\n     * Extracts an item from this network.\n     *\n     * @param stack  the prototype of the stack to extract, do NOT modify\n     * @param size   the amount of that prototype that has to be extracted\n     * @param flags  the flags to compare on, see {@link IComparer}\n     * @param action the action\n     * @return an empty stack if nothing was extracted, or a stack with the result\n     */\n    @Nonnull\n    default ItemStack extractItem(@Nonnull ItemStack stack, int size, int flags, Action action) {\n        return extractItem(stack, size, flags, action, s -> true);\n    }\n\n    /**\n     * Extracts an item from this network.\n     *\n     * @param stack  the prototype of the stack to extract, do NOT modify\n     * @param size   the amount of that prototype that has to be extracted\n     * @param action the action\n     * @return an empty stack if nothing was extracted, or a stack with the result\n     */\n    @Nonnull\n    default ItemStack extractItem(@Nonnull ItemStack stack, int size, Action action) {\n        return extractItem(stack, size, IComparer.COMPARE_NBT, action);\n    }\n\n    /**\n     * Inserts a fluid in this network.\n     *\n     * @param stack  the stack prototype to insert, do NOT modify\n     * @param size   the amount of that prototype that has to be inserted\n     * @param action the action\n     * @return an empty stack if the insert was successful, or a stack with the remainder\n     */\n    @Nonnull\n    FluidStack insertFluid(@Nonnull FluidStack stack, int size, Action action);\n\n    /**\n     * Inserts a fluid and notifies the crafting manager of the incoming fluid.\n     *\n     * @param stack the stack prototype to insert, do NOT modify\n     * @param size  the amount of that prototype that has to be inserted\n     * @return an empty stack if the insert was successful, or a stack with the remainder\n     */\n    @Nonnull\n    default FluidStack insertFluidTracked(@Nonnull FluidStack stack, int size) {\n        int remainder = getCraftingManager().track(stack, size);\n\n        if (remainder == 0) {\n            return FluidStack.EMPTY;\n        }\n\n        return insertFluid(stack, remainder, Action.PERFORM);\n    }\n\n    /**\n     * Extracts a fluid from this network.\n     *\n     * @param stack  the prototype of the stack to extract, do NOT modify\n     * @param size   the amount of that prototype that has to be extracted\n     * @param flags  the flags to compare on, see {@link IComparer}\n     * @param action the action\n     * @return an empty stack if nothing was extracted, or a stack with the result\n     */\n    @Nonnull\n    FluidStack extractFluid(@Nonnull FluidStack stack, int size, int flags, Action action, Predicate<IStorage<FluidStack>> filter);\n\n    /**\n     * Extracts a fluid from this network.\n     *\n     * @param stack  the prototype of the stack to extract, do NOT modify\n     * @param size   the amount of that prototype that has to be extracted\n     * @param flags  the flags to compare on, see {@link IComparer}\n     * @param action the action\n     * @return an empty stack if nothing was extracted, or a stack with the result\n     */\n    @Nonnull\n    default FluidStack extractFluid(FluidStack stack, int size, int flags, Action action) {\n        return extractFluid(stack, size, flags, action, s -> true);\n    }\n\n    /**\n     * Extracts a fluid from this network.\n     *\n     * @param stack  the prototype of the stack to extract, do NOT modify\n     * @param size   the amount of that prototype that has to be extracted\n     * @param action the action\n     * @return an empty stack if nothing was extracted, or a stack with the result\n     */\n    @Nonnull\n    default FluidStack extractFluid(FluidStack stack, int size, Action action) {\n        return extractFluid(stack, size, IComparer.COMPARE_NBT, action);\n    }\n\n    /**\n     * @return the storage tracker for items\n     */\n    IStorageTracker<ItemStack> getItemStorageTracker();\n\n    /**\n     * @return the storage tracker for fluids\n     */\n    IStorageTracker<FluidStack> getFluidStorageTracker();\n\n    /**\n     * @return the level where this network is in\n     */\n    Level getLevel();\n\n    /**\n     * @return the position of this network in the level\n     */\n    BlockPos getPosition();\n\n    /**\n     * @return a read network\n     */\n    INetwork readFromNbt(CompoundTag tag);\n\n    /**\n     * @param tag the tag to write to\n     * @return a written tag\n     */\n    CompoundTag writeToNbt(CompoundTag tag);\n\n    /**\n     * @return sampled tick times\n     */\n    long[] getTickTimes();\n\n    /**\n     * Marks the network dirty.\n     */\n    void markDirty();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/INetworkManager.java",
    "content": "package com.refinedmods.refinedstorage.api.network;\n\nimport net.minecraft.core.BlockPos;\n\nimport javax.annotation.Nullable;\nimport java.util.Collection;\n\n/**\n * This is a registry for network nodes in the level.\n */\npublic interface INetworkManager {\n    /**\n     * Gets a network from the registry at a given position.\n     *\n     * @param pos the position of the network\n     * @return the network at the given position, or null if no network was found\n     */\n    @Nullable\n    INetwork getNetwork(BlockPos pos);\n\n    /**\n     * Removes a network from the registry at a given position.\n     *\n     * @param pos the position of the network\n     */\n    void removeNetwork(BlockPos pos);\n\n    /**\n     * Sets a network in the registry at a given position.\n     *\n     * @param pos  the position of the network\n     * @param node the node\n     */\n    void setNetwork(BlockPos pos, INetwork node);\n\n    /**\n     * @return all networks in this registry\n     */\n    Collection<INetwork> all();\n\n    /**\n     * Marks the network manager for saving.\n     */\n    void markForSaving();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/INetworkNodeGraph.java",
    "content": "package com.refinedmods.refinedstorage.api.network;\n\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.world.level.Level;\n\nimport java.util.Collection;\nimport java.util.function.Consumer;\n\n/**\n * Represents a graph of all the nodes connected to a network.\n */\npublic interface INetworkNodeGraph {\n    /**\n     * Rebuilds the network graph.\n     *\n     * @param action whether to perform or simulate\n     * @param level  the origin level\n     * @param origin the origin, usually the network position\n     */\n    void invalidate(Action action, Level level, BlockPos origin);\n\n    /**\n     * Runs an action on the network.\n     * If the network is rebuilding it's graph, the action will be executed after the graph was built.\n     *\n     * @param handler the action to run\n     */\n    void runActionWhenPossible(Consumer<INetwork> handler);\n\n    /**\n     * @return a collection of all connected entries\n     */\n    Collection<INetworkNodeGraphEntry> all();\n\n    /**\n     * @param listener the listener\n     */\n    void addListener(INetworkNodeGraphListener listener);\n\n    /**\n     * Disconnects and notifies all connected nodes.\n     */\n    void disconnectAll();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/INetworkNodeGraphEntry.java",
    "content": "package com.refinedmods.refinedstorage.api.network;\n\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\n\n/**\n * An entry in the network graph.\n * Implementors MUST implement equals and hashCode.\n */\npublic interface INetworkNodeGraphEntry {\n    INetworkNode getNode();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/INetworkNodeGraphListener.java",
    "content": "package com.refinedmods.refinedstorage.api.network;\n\n/**\n * A listener for the node graph.\n */\npublic interface INetworkNodeGraphListener {\n    /**\n     * Called when the graph changes.\n     */\n    void onChanged();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/INetworkNodeVisitor.java",
    "content": "package com.refinedmods.refinedstorage.api.network;\n\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.world.level.Level;\n\nimport javax.annotation.Nullable;\n\n/**\n * Allows the network nodes to implement more optimal or non-regular discovery of other (neighboring) nodes.\n */\npublic interface INetworkNodeVisitor {\n    /**\n     * Called by the network node graph when a {@link Operator} has requested this node to be visited.\n     *\n     * @param operator the operator\n     */\n    void visit(Operator operator);\n\n    /**\n     * An operator is passed to the {@link #visit(Operator)} method to allow the network node visitor to add positions of nodes to scan.\n     */\n    interface Operator {\n        /**\n         * Calling this method in {@link #visit(Operator)} will make the network graph scan the given level and position.\n         * If there is another {@link INetworkNodeVisitor} at that position, it will call that visitor.\n         * If there is no {@link INetworkNodeVisitor} at that position, it will use a default implementation which scans neighbors.\n         *\n         * @param level the level\n         * @param pos   the position\n         * @param side  the side\n         */\n        void apply(Level level, BlockPos pos, @Nullable Direction side);\n\n        /**\n         * Returns whether the network graph is scanning in simulation mode.\n         *\n         * @return the action\n         */\n        Action getAction();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/IWirelessTransmitter.java",
    "content": "package com.refinedmods.refinedstorage.api.network;\n\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.resources.ResourceKey;\nimport net.minecraft.world.level.Level;\n\n/**\n * Represents a node that can send a wireless signal.\n */\npublic interface IWirelessTransmitter {\n    /**\n     * @return the range in blocks of this transmitter, starting from {@link IWirelessTransmitter#getOrigin()}\n     */\n    int getRange();\n\n    /**\n     * @return the position where the wireless signal starts\n     */\n    BlockPos getOrigin();\n\n    /**\n     * @return the dimension in which the transmitter is\n     */\n    ResourceKey<Level> getDimension();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/NetworkType.java",
    "content": "package com.refinedmods.refinedstorage.api.network;\n\n/**\n * Represents a network type.\n */\npublic enum NetworkType {\n    /**\n     * A normal network.\n     */\n    NORMAL,\n    /**\n     * A creative network.\n     */\n    CREATIVE\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/grid/GridFactoryType.java",
    "content": "package com.refinedmods.refinedstorage.api.network.grid;\n\n/**\n * The type of grid factory.\n */\npublic enum GridFactoryType {\n    /**\n     * A grid factory for item stacks.\n     */\n    STACK,\n    /**\n     * A grid factory for blocks with a position.\n     */\n    BLOCK\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/grid/GridType.java",
    "content": "package com.refinedmods.refinedstorage.api.network.grid;\n\nimport net.minecraft.util.StringRepresentable;\n\nimport javax.annotation.Nonnull;\n\n/**\n * Represents a grid type.\n * Used in {@link IGrid} to determine grid GUI rendering.\n */\npublic enum GridType implements StringRepresentable {\n    /**\n     * A regular grid.\n     */\n    NORMAL(0, \"normal\"),\n    /**\n     * A crafting grid.\n     */\n    CRAFTING(1, \"crafting\"),\n    /**\n     * A pattern grid.\n     */\n    PATTERN(2, \"pattern\"),\n    /**\n     * A fluid grid.\n     */\n    FLUID(3, \"fluid\");\n\n    private final int id;\n    private final String name;\n\n    GridType(int id, String name) {\n        this.id = id;\n        this.name = name;\n    }\n\n    @Nonnull\n    @Override\n    public String getSerializedName() {\n        return name;\n    }\n\n    @Override\n    public String toString() {\n        return name;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/grid/ICraftingGridBehavior.java",
    "content": "package com.refinedmods.refinedstorage.api.network.grid;\n\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.crafting.CraftingRecipe;\n\nimport javax.annotation.Nullable;\n\n/**\n * Defines default behavior of crafting grids.\n */\npublic interface ICraftingGridBehavior {\n    /**\n     * Logic for regular crafting.\n     *\n     * @param grid           the grid\n     * @param recipe         the recipe\n     * @param player         the player\n     * @param availableItems the items available for shift crafting\n     * @param usedItems      the items used by shift crafting\n     */\n    void onCrafted(INetworkAwareGrid grid, CraftingRecipe recipe, Player player, @Nullable IStackList<ItemStack> availableItems, @Nullable IStackList<ItemStack> usedItems);\n\n    /**\n     * Logic for crafting with shift click (mass crafting).\n     *\n     * @param grid   the grid\n     * @param player the player\n     */\n    void onCraftedShift(INetworkAwareGrid grid, Player player);\n\n    /**\n     * Logic for when a recipe is transferred to the grid.\n     *\n     * @param grid   the grid\n     * @param player the player\n     * @param recipe the recipe\n     */\n    void onRecipeTransfer(INetworkAwareGrid grid, Player player, ItemStack[][] recipe);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/grid/ICraftingGridListener.java",
    "content": "package com.refinedmods.refinedstorage.api.network.grid;\n\n/**\n * A crafting listener for the grid.\n */\npublic interface ICraftingGridListener {\n    /**\n     * Called when the crafting matrix was changed.\n     * Usually you'd send slot updates for the crafting slots (and output slot) here, so that all clients get an actual view.\n     * This listener exists so the crafting result slot is only calculated on the server.\n     */\n    void onCraftingMatrixChanged();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/grid/IGrid.java",
    "content": "package com.refinedmods.refinedstorage.api.network.grid;\n\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener;\nimport com.refinedmods.refinedstorage.api.util.IFilter;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.CraftingContainer;\nimport net.minecraft.world.inventory.ResultContainer;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport javax.annotation.Nullable;\nimport java.util.List;\n\n/**\n * Represents a grid.\n */\npublic interface IGrid {\n    int TABS_PER_PAGE = 5;\n\n    int SORTING_DIRECTION_ASCENDING = 0;\n    int SORTING_DIRECTION_DESCENDING = 1;\n\n    int SORTING_TYPE_QUANTITY = 0;\n    int SORTING_TYPE_NAME = 1;\n    int SORTING_TYPE_ID = 2;\n    int SORTING_TYPE_LAST_MODIFIED = 4;\n\n    int SEARCH_BOX_MODE_NORMAL = 0;\n    int SEARCH_BOX_MODE_NORMAL_AUTOSELECTED = 1;\n    int SEARCH_BOX_MODE_JEI_SYNCHRONIZED = 2;\n    int SEARCH_BOX_MODE_JEI_SYNCHRONIZED_AUTOSELECTED = 3;\n    int SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY = 4;\n    int SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY_AUTOSELECTED = 5;\n\n    int VIEW_TYPE_NORMAL = 0;\n    int VIEW_TYPE_NON_CRAFTABLES = 1;\n    int VIEW_TYPE_CRAFTABLES = 2;\n\n    int SIZE_STRETCH = 0;\n    int SIZE_SMALL = 1;\n    int SIZE_MEDIUM = 2;\n    int SIZE_LARGE = 3;\n\n    static boolean isValidViewType(int type) {\n        return type == VIEW_TYPE_NORMAL ||\n                type == VIEW_TYPE_CRAFTABLES ||\n                type == VIEW_TYPE_NON_CRAFTABLES;\n    }\n\n    static boolean isValidSearchBoxMode(int mode) {\n        return mode == SEARCH_BOX_MODE_NORMAL ||\n                mode == SEARCH_BOX_MODE_NORMAL_AUTOSELECTED ||\n                mode == SEARCH_BOX_MODE_JEI_SYNCHRONIZED ||\n                mode == SEARCH_BOX_MODE_JEI_SYNCHRONIZED_AUTOSELECTED ||\n                mode == SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY ||\n                mode == SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY_AUTOSELECTED;\n    }\n\n    static boolean isSearchBoxModeWithAutoselection(int mode) {\n        return mode == SEARCH_BOX_MODE_NORMAL_AUTOSELECTED ||\n                mode == SEARCH_BOX_MODE_JEI_SYNCHRONIZED_AUTOSELECTED ||\n                mode == SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY_AUTOSELECTED;\n    }\n\n    static boolean doesSearchBoxModeUseJEI(int mode) {\n        return mode == SEARCH_BOX_MODE_JEI_SYNCHRONIZED ||\n                mode == SEARCH_BOX_MODE_JEI_SYNCHRONIZED_AUTOSELECTED ||\n                mode == SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY ||\n                mode == SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY_AUTOSELECTED;\n    }\n\n    static boolean isValidSortingType(int type) {\n        return type == SORTING_TYPE_QUANTITY ||\n                type == SORTING_TYPE_NAME ||\n                type == SORTING_TYPE_ID ||\n                type == SORTING_TYPE_LAST_MODIFIED;\n    }\n\n    static boolean isValidSortingDirection(int direction) {\n        return direction == SORTING_DIRECTION_ASCENDING || direction == SORTING_DIRECTION_DESCENDING;\n    }\n\n    static boolean isValidSize(int size) {\n        return size == SIZE_STRETCH ||\n                size == SIZE_SMALL ||\n                size == SIZE_MEDIUM ||\n                size == SIZE_LARGE;\n    }\n\n    /**\n     * @return the grid type\n     */\n    GridType getGridType();\n\n    /**\n     * @param player the player to create a listener for\n     * @return a listener for this grid, will be attached to the storage cache in {@link #getStorageCache()}\n     */\n    IStorageCacheListener createListener(ServerPlayer player);\n\n    /**\n     * @return the storage cache for this grid, or null if this grid is unavailable\n     */\n    @Nullable\n    IStorageCache getStorageCache();\n\n    /**\n     * @return the item grid handler, or null if there is no handler available\n     */\n    @Nullable\n    IItemGridHandler getItemHandler();\n\n    /**\n     * @return the fluid grid handler, or null if there is no handler available\n     */\n    @Nullable\n    IFluidGridHandler getFluidHandler();\n\n    /**\n     * @param listener the listener\n     */\n    default void addCraftingListener(ICraftingGridListener listener) {\n    }\n\n    /**\n     * @param listener the listener\n     */\n    default void removeCraftingListener(ICraftingGridListener listener) {\n    }\n\n    /**\n     * @return the title\n     */\n    Component getTitle();\n\n    /**\n     * @return the view type\n     */\n    int getViewType();\n\n    /**\n     * @return the sorting type\n     */\n    int getSortingType();\n\n    /**\n     * @return the sorting direction\n     */\n    int getSortingDirection();\n\n    /**\n     * @return the search box mode\n     */\n    int getSearchBoxMode();\n\n    /**\n     * @return the current tab that is selected\n     */\n    int getTabSelected();\n\n    /**\n     * @return the current page that the tab is on\n     */\n    int getTabPage();\n\n    /**\n     * @return the total amount of tab pages\n     */\n    int getTotalTabPages();\n\n    /**\n     * @return the size mode\n     */\n    int getSize();\n\n    /**\n     * @param type the new view type\n     */\n    void onViewTypeChanged(int type);\n\n    /**\n     * @param type the new sorting type\n     */\n    void onSortingTypeChanged(int type);\n\n    /**\n     * @param direction the new direction\n     */\n    void onSortingDirectionChanged(int direction);\n\n    /**\n     * @param searchBoxMode the new search box mode\n     */\n    void onSearchBoxModeChanged(int searchBoxMode);\n\n    /**\n     * @param size the new size mode\n     */\n    void onSizeChanged(int size);\n\n    /**\n     * @param tab the new selected tab\n     */\n    void onTabSelectionChanged(int tab);\n\n    /**\n     * @param page the new selected page\n     */\n    void onTabPageChanged(int page);\n\n    /**\n     * @return the filters\n     */\n    List<IFilter> getFilters();\n\n    /**\n     * @return the tabs\n     */\n    List<IGridTab> getTabs();\n\n    /**\n     * @return the inventory of the filters\n     */\n    IItemHandlerModifiable getFilter();\n\n    /**\n     * @return the crafting matrix, or null if not a crafting grid\n     */\n    @Nullable\n    CraftingContainer getCraftingMatrix();\n\n    /**\n     * @return the crafting result inventory, or null if not a crafting grid\n     */\n    @Nullable\n    ResultContainer getCraftingResult();\n\n    /**\n     * Called when the crafting matrix changes.\n     */\n    void onCraftingMatrixChanged();\n\n    /**\n     * Called when an item is crafted in a crafting grid.\n     *\n     * @param player         the player that crafted the item\n     * @param availableItems the items available for shift crafting\n     * @param usedItems      the items used by shift crafting\n     */\n    void onCrafted(Player player, @Nullable IStackList<ItemStack> availableItems, @Nullable IStackList<ItemStack> usedItems);\n\n    /**\n     * Called when the clear button is pressed in the pattern grid or crafting grid.\n     */\n    void onClear(Player player);\n\n    /**\n     * Called when an item is crafted with shift click (up to 64 items) in a crafting grid.\n     *\n     * @param player the player that crafted the item\n     */\n    void onCraftedShift(Player player);\n\n    /**\n     * Called when a JEI recipe transfer occurs.\n     *\n     * @param player the player\n     * @param recipe a 9*x array stack array, where x is the possible combinations for the given slot\n     */\n    void onRecipeTransfer(Player player, ItemStack[][] recipe);\n\n    /**\n     * Called when the grid is closed.\n     *\n     * @param player the player\n     */\n    void onClosed(Player player);\n\n    /**\n     * @return true if the grid is active, false otherwise\n     */\n    boolean isGridActive();\n\n    /**\n     * @return the slot id where this grid is located, if applicable, otherwise -1\n     */\n    int getSlotId();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/grid/IGridFactory.java",
    "content": "package com.refinedmods.refinedstorage.api.network.grid;\n\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\n\nimport javax.annotation.Nullable;\n\n/**\n * Creates a grid.\n */\npublic interface IGridFactory {\n    /**\n     * Creates a grid from a stack. Used when {@link #getType()} is STACK.\n     *\n     * @param player the player\n     * @param stack  the stack\n     * @param slot   the slot in the players inventory or curio slot, otherwise -1\n     * @return the grid, or null if a problem occurred\n     */\n    @Nullable\n    IGrid createFromStack(Player player, ItemStack stack, PlayerSlot slot);\n\n    /**\n     * Creates a grid from a block. Used when {@link #getType()} is BLOCK.\n     *\n     * @param player the player\n     * @param pos    the block position\n     * @return the grid, or null if a problem occurred\n     */\n    @Nullable\n    IGrid createFromBlock(Player player, BlockPos pos);\n\n    /**\n     * Returns a possible block entity for this grid if {@link #getType()} is BLOCK.\n     *\n     * @param level the level\n     * @param pos   the position\n     * @return the block entity, or null if no block entity is required\n     */\n    @Nullable\n    BlockEntity getRelevantBlockEntity(Level level, BlockPos pos);\n\n    /**\n     * @return the type\n     */\n    GridFactoryType getType();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/grid/IGridManager.java",
    "content": "package com.refinedmods.refinedstorage.api.network.grid;\n\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport org.apache.commons.lang3.tuple.Pair;\n\nimport javax.annotation.Nullable;\n\n/**\n * Manages {@link IGridFactory} instances and has code that opens grids.\n */\npublic interface IGridManager {\n    /**\n     * @param id      the id of this factory\n     * @param factory the factory\n     */\n    void add(ResourceLocation id, IGridFactory factory);\n\n    /**\n     * Opens a grid. Can only be called on the server.\n     *\n     * @param id     the grid factory id\n     * @param player the player\n     * @param pos    the block position\n     */\n    void openGrid(ResourceLocation id, ServerPlayer player, BlockPos pos);\n\n    /**\n     * Opens a grid. Can only be called on the server.\n     *\n     * @param id     the grid factory id\n     * @param player the player\n     * @param stack  the stack\n     * @param slot   the slot in the players inventory or curio slot, otherwise -1\n     */\n    void openGrid(ResourceLocation id, ServerPlayer player, ItemStack stack, PlayerSlot slot);\n\n    /**\n     * Creates a grid.\n     *\n     * @param id     the grid factory id\n     * @param player the player\n     * @param stack  the stack, if there is one\n     * @param pos    the block position, if there is one\n     * @param slot   the slot in the players inventory,or curio slot, otherwise -1\n     * @return a grid, or null if an error has occurred\n     */\n    @Nullable\n    Pair<IGrid, BlockEntity> createGrid(ResourceLocation id, Player player, @Nullable ItemStack stack, @Nullable BlockPos pos, PlayerSlot slot);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/grid/IGridTab.java",
    "content": "package com.refinedmods.refinedstorage.api.network.grid;\n\nimport com.refinedmods.refinedstorage.api.render.IElementDrawer;\nimport com.refinedmods.refinedstorage.api.util.IFilter;\nimport net.minecraft.client.gui.Font;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport java.util.List;\n\n/**\n * Represents a grid tab.\n */\npublic interface IGridTab {\n    int TAB_WIDTH = 28;\n    int TAB_HEIGHT = 31;\n\n    /**\n     * @return the filters\n     */\n    List<IFilter> getFilters();\n\n    /**\n     * Draws the tooltip of this tab at the given position.\n     *\n     * @param font     the font\n     * @param graphics the graphics\n     * @param x        the x position\n     * @param y        the y position\n     */\n    void drawTooltip(Font font, GuiGraphics graphics, int x, int y);\n\n    /**\n     * Draws the icon.\n     *\n     * @param graphics the graphics\n     * @param x        the x position\n     * @param y        the y position\n     */\n    void drawIcon(GuiGraphics graphics, int x, int y, IElementDrawer<ItemStack> itemDrawer, IElementDrawer<FluidStack> fluidDrawer);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/grid/INetworkAwareGrid.java",
    "content": "package com.refinedmods.refinedstorage.api.network.grid;\n\nimport com.refinedmods.refinedstorage.api.network.INetwork;\n\nimport javax.annotation.Nullable;\n\n/**\n * A grid that knows about a network.\n */\npublic interface INetworkAwareGrid extends IGrid {\n    /**\n     * @return the network, or null if no network is available\n     */\n    @Nullable\n    INetwork getNetwork();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/grid/handler/IFluidGridHandler.java",
    "content": "package com.refinedmods.refinedstorage.api.network.grid.handler;\n\nimport com.refinedmods.refinedstorage.api.util.StackListEntry;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.item.ItemStack;\n\nimport javax.annotation.Nonnull;\nimport java.util.UUID;\n\n/**\n * Defines the behavior of fluid grids.\n */\npublic interface IFluidGridHandler {\n    /**\n     * Called when a player tries to extract a fluid from the grid.\n     *\n     * @param player the player that is attempting the extraction\n     * @param id     the id of the fluid we're trying to extract, this id is the id from {@link StackListEntry}\n     * @param shift  true if shift click was used, false otherwise\n     */\n    void onExtract(ServerPlayer player, UUID id, boolean shift);\n\n    /**\n     * Called when a player tries to insert fluids in the grid.\n     *\n     * @param player    the player\n     * @param container a stack with a fluid container we're trying to insert\n     * @return the remainder, or an empty stack if there is no remainder\n     */\n    @Nonnull\n    ItemStack onInsert(ServerPlayer player, ItemStack container);\n\n    /**\n     * Called when a player is trying to insert a fluid that it is holding in their hand in the GUI.\n     *\n     * @param player the player that is attempting the insert\n     */\n    void onInsertHeldContainer(ServerPlayer player);\n\n    /**\n     * Called when a player requests the crafting preview window to be opened.\n     *\n     * @param player    the player\n     * @param id        the id of the fluid we're trying to extract, this id is the id from {@link StackListEntry}\n     * @param quantity  the amount of that item that we need a preview for\n     * @param noPreview true if the crafting preview window shouldn't be shown, false otherwise\n     */\n    void onCraftingPreviewRequested(ServerPlayer player, UUID id, int quantity, boolean noPreview);\n\n    /**\n     * Called when a player requested crafting for an item.\n     *\n     * @param player   the player that is requesting the crafting\n     * @param id       the id of the fluid we're trying to extract, this id is the id from {@link StackListEntry}\n     * @param quantity the amount of the item that has to be crafted\n     */\n    void onCraftingRequested(ServerPlayer player, UUID id, int quantity);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/grid/handler/IItemGridHandler.java",
    "content": "package com.refinedmods.refinedstorage.api.network.grid.handler;\n\nimport com.refinedmods.refinedstorage.api.util.StackListEntry;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.item.ItemStack;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.UUID;\n\n/**\n * Defines the behavior of item grids.\n */\npublic interface IItemGridHandler {\n    int EXTRACT_HALF = 1;\n    int EXTRACT_SINGLE = 2;\n    int EXTRACT_SHIFT = 4;\n\n    /**\n     * Called when a player tries to extract an item from the grid through the Inventory\n     *\n     * @param player        the player that is attempting the extraction\n     * @param stack         the stack we're trying to extract\n     * @param preferredSlot playerInventory slot to prefer when adding or -1\n     * @param flags         how we are extracting, see the flags in {@link IItemGridHandler}\n     */\n    void onExtract(ServerPlayer player, ItemStack stack, int preferredSlot, int flags);\n\n    /**\n     * Called when a player tries to extract an item from the grid.\n     *\n     * @param player        the player that is attempting the extraction\n     * @param id            the id of the item we're trying to extract, this id is the id from {@link StackListEntry}\n     * @param preferredSlot playerInventory slot to prefer when adding or -1\n     * @param flags         how we are extracting, see the flags in {@link IItemGridHandler}\n     */\n    void onExtract(ServerPlayer player, UUID id, int preferredSlot, int flags);\n\n    /**\n     * Called when a player tries to insert an item in the grid.\n     *\n     * @param player the player that is attempting the insert\n     * @param stack  the item we're trying to insert\n     * @param single true if we are only inserting a single item, false otherwise\n     * @return the remainder, or an empty stack if there is no remainder\n     */\n    @Nonnull\n    ItemStack onInsert(ServerPlayer player, ItemStack stack, boolean single);\n\n    /**\n     * Called when a player is trying to insert an item that it is holding in their hand in the GUI.\n     *\n     * @param player the player that is attempting the insert\n     * @param single true if we are only inserting a single item, false otherwise\n     */\n    void onInsertHeldItem(ServerPlayer player, boolean single);\n\n    /**\n     * Called when a player requests the crafting preview window to be opened.\n     *\n     * @param player    the player\n     * @param id        the id of the item we're trying to extract, this id is the id from {@link StackListEntry}\n     * @param quantity  the amount of that item that we need a preview for\n     * @param noPreview true if the crafting preview window shouldn't be shown, false otherwise\n     */\n    void onCraftingPreviewRequested(ServerPlayer player, UUID id, int quantity, boolean noPreview);\n\n    /**\n     * Called when a player requested crafting for an item.\n     *\n     * @param player   the player that is requesting the crafting\n     * @param id       the id of the item we're trying to extract, this id is the id from {@link StackListEntry}\n     * @param quantity the amount of the item that has to be crafted\n     */\n    void onCraftingRequested(ServerPlayer player, UUID id, int quantity);\n\n    /**\n     * Called when a player wants to cancel a crafting task.\n     *\n     * @param player the player that requested the cancel\n     * @param id     the task id, or null to cancel all tasks that are in the network currently\n     */\n    void onCraftingCancelRequested(ServerPlayer player, @Nullable UUID id);\n\n    /**\n     * Called when a player shift or ctrl scrolls in the player inventory\n     *\n     * @param player player that is scrolling\n     * @param slot   slot the mouse is hovering over\n     * @param shift  if true shift is pressed, if false ctrl is pressed\n     * @param up     whether the player is scrolling up or down\n     */\n    void onInventoryScroll(ServerPlayer player, int slot, boolean shift, boolean up);\n\n    /**\n     * Called when a player shift or ctrl scrolls in the Grid View\n     *\n     * @param player player that is scrolling\n     * @param id     UUID of the GridStack that the mouse is hovering over or null\n     * @param shift  if true shift is pressed, if false ctrl is pressed\n     * @param up     whether the player is scrolling up or down\n     */\n    void onGridScroll(ServerPlayer player, @Nullable UUID id, boolean shift, boolean up);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/item/INetworkItem.java",
    "content": "package com.refinedmods.refinedstorage.api.network.item;\n\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport net.minecraft.world.entity.player.Player;\n\n/**\n * Represents a network item (an item that is connected to the network somehow).\n * You do not implement this on the item itself, use an {@link INetworkItemProvider} for that.\n * This is an object used separately from the actual item, since this stores the player that is using it.\n */\npublic interface INetworkItem {\n    /**\n     * @return the player using the network item\n     */\n    Player getPlayer();\n\n    /**\n     * Called when the network item is being opened.\n     *\n     * @param network the network\n     * @return true if the item can be opened, false otherwise\n     */\n    boolean onOpen(INetwork network);\n\n    /**\n     * @param energy the energy to extract\n     */\n    void drainEnergy(int energy);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/item/INetworkItemManager.java",
    "content": "package com.refinedmods.refinedstorage.api.network.item;\n\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\n\nimport javax.annotation.Nullable;\n\n/**\n * This is the handler for network items of a network.\n * It stores which player is currently using what network item.\n */\npublic interface INetworkItemManager {\n    /**\n     * Called when a player opens a network item.\n     *\n     * @param player the player that opened the network item\n     * @param stack  the stack that has been opened\n     * @param slot   the slot in the players inventory or curio slot, otherwise -1\n     */\n    void open(Player player, ItemStack stack, PlayerSlot slot);\n\n    /**\n     * Called when the player closes a network item.\n     *\n     * @param player the player that closed the network item\n     */\n    void close(Player player);\n\n    /**\n     * Returns a {@link INetworkItem} for a player.\n     *\n     * @param player the player to get the network item for\n     * @return the {@link INetworkItem} that corresponds to a player, or null if the player isn't using a network item\n     */\n    @Nullable\n    INetworkItem getItem(Player player);\n\n    /**\n     * @param player the player\n     * @param energy energy to extract\n     */\n    void drainEnergy(Player player, int energy);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/item/INetworkItemProvider.java",
    "content": "package com.refinedmods.refinedstorage.api.network.item;\n\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\n\nimport javax.annotation.Nonnull;\n\n/**\n * Provider for network items, implement this on the item.\n */\npublic interface INetworkItemProvider {\n    /**\n     * Creates a network item for the given item stack.\n     *\n     * @param handler the network item handler\n     * @param player  the player\n     * @param stack   the stack\n     * @param slot    the slot in the players inventory or curio slot, otherwise -1\n     * @return the network item\n     */\n    @Nonnull\n    INetworkItem provide(INetworkItemManager handler, Player player, ItemStack stack, PlayerSlot slot);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/node/ICoverable.java",
    "content": "package com.refinedmods.refinedstorage.api.network.node;\n\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;\n\npublic interface ICoverable {\n\n    CoverManager getCoverManager();\n\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/node/INetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.api.network.node;\n\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.UUID;\n\n/**\n * Represents a node in the network.\n */\npublic interface INetworkNode {\n    /**\n     * @return the energy usage of this node\n     */\n    int getEnergyUsage();\n\n    /**\n     * Returns the stack that is displayed in the controller GUI.\n     * Can be an empty stack if no stack should be shown.\n     *\n     * @return the item stack of this node\n     */\n    @Nonnull\n    ItemStack getItemStack();\n\n    /**\n     * Called when this node is connected to a network.\n     *\n     * @param network the network\n     */\n    void onConnected(INetwork network);\n\n    /**\n     * Called when this node is disconnected from a network.\n     * This happens when the node is removed, or if the network is removed.\n     * If the network runs out of power or no longer runs due to redstone mode settings, this won't be called and has to be detected manually.\n     *\n     * @param network the network\n     */\n    void onDisconnected(INetwork network);\n\n    /**\n     * Whether this node is active, independent of the network.\n     *\n     * @return true if this node is active, false otherwise\n     */\n    boolean isActive();\n\n    /**\n     * @return the network, or null if this node is not connected to any network\n     */\n    @Nullable\n    INetwork getNetwork();\n\n    /**\n     * Updates a network node.\n     */\n    void update();\n\n    /**\n     * Writes the network node data to NBT.\n     *\n     * @param tag the tag\n     * @return the written tag\n     */\n    CompoundTag write(CompoundTag tag);\n\n    /**\n     * @return the position of this network node\n     */\n    BlockPos getPos();\n\n    /**\n     * @return the level of this network node\n     */\n    Level getLevel();\n\n    /**\n     * Marks this node as dirty for saving.\n     */\n    void markDirty();\n\n    /**\n     * @return the id of this node as specified in {@link INetworkNodeRegistry}\n     */\n    ResourceLocation getId();\n\n    /**\n     * @param direction the direction\n     * @return whether a network signal can be conducted in the given direction.\n     */\n    default boolean canConduct(Direction direction) {\n        return true;\n    }\n\n    /**\n     * @param direction the direction\n     * @return whether the network node can receiver network connections from this side\n     */\n    default boolean canReceive(Direction direction) {\n        return canConduct(direction);\n    }\n\n    /**\n     * @return the owner\n     */\n    @Nullable\n    UUID getOwner();\n\n    /**\n     * @param owner the owner\n     */\n    void setOwner(@Nullable UUID owner);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/node/INetworkNodeFactory.java",
    "content": "package com.refinedmods.refinedstorage.api.network.node;\n\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.world.level.Level;\n\nimport javax.annotation.Nonnull;\n\n/**\n * A factory for reading network nodes from the disk. Used in a {@link INetworkNodeRegistry}.\n */\npublic interface INetworkNodeFactory {\n    /**\n     * Creates a network node.\n     *\n     * @param tag   the tag on disk\n     * @param level the level\n     * @param pos   the pos\n     * @return the network node\n     */\n    @Nonnull\n    INetworkNode create(CompoundTag tag, Level level, BlockPos pos);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/node/INetworkNodeManager.java",
    "content": "package com.refinedmods.refinedstorage.api.network.node;\n\nimport net.minecraft.core.BlockPos;\n\nimport javax.annotation.Nullable;\nimport java.util.Collection;\n\n/**\n * This is a registry for network nodes in the level.\n */\npublic interface INetworkNodeManager {\n    /**\n     * Gets a network node from the registry at a given position.\n     *\n     * @param pos the position of the node\n     * @return the network node at the given position, or null if no network node was found\n     */\n    @Nullable\n    INetworkNode getNode(BlockPos pos);\n\n    /**\n     * Removes a node from the registry at a given position.\n     *\n     * @param pos the position of the node\n     */\n    void removeNode(BlockPos pos);\n\n    /**\n     * Sets a node in the registry at a given position.\n     *\n     * @param pos  the position of the node\n     * @param node the node\n     */\n    void setNode(BlockPos pos, INetworkNode node);\n\n    /**\n     * @return all nodes in this registry\n     */\n    Collection<INetworkNode> all();\n\n    /**\n     * Marks the network node manager for saving.\n     */\n    void markForSaving();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/node/INetworkNodeProxy.java",
    "content": "package com.refinedmods.refinedstorage.api.network.node;\n\nimport javax.annotation.Nonnull;\n\n/**\n * Makes a network node accessible from a tile entity. Implement this as a capability.\n *\n * @param <T> the network node\n */\npublic interface INetworkNodeProxy<T extends INetworkNode> {\n    /**\n     * Returns the node.\n     * Needs to work on the client and the server.\n     * If there is no node present, don't silently return null but throw an exception since the game is in a bad state if that happens.\n     *\n     * @return the node\n     */\n    @Nonnull\n    T getNode();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/node/INetworkNodeRegistry.java",
    "content": "package com.refinedmods.refinedstorage.api.network.node;\n\nimport net.minecraft.resources.ResourceLocation;\n\nimport javax.annotation.Nullable;\n\n/**\n * This registry holds factories for reading and writing network nodes from and to NBT.\n */\npublic interface INetworkNodeRegistry {\n    /**\n     * Adds a factory to the registry.\n     *\n     * @param id      the id, as specified in {@link INetworkNode#getId()}\n     * @param factory the factory\n     */\n    void add(ResourceLocation id, INetworkNodeFactory factory);\n\n    /**\n     * Returns a factory from the registry.\n     *\n     * @param id the id, as specified in {@link INetworkNode#getId()}\n     * @return the factory, or null if no factory was found\n     */\n    @Nullable\n    INetworkNodeFactory get(ResourceLocation id);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/security/ISecurityCard.java",
    "content": "package com.refinedmods.refinedstorage.api.network.security;\n\nimport javax.annotation.Nullable;\nimport java.util.UUID;\n\n/**\n * Represents a security card.\n */\npublic interface ISecurityCard {\n    /**\n     * @return the owner of this card, or null if this is a global card\n     */\n    @Nullable\n    UUID getOwner();\n\n    /**\n     * @param permission the permission to check for\n     * @return true if the bound player has the given permission, false otherwise\n     */\n    boolean hasPermission(Permission permission);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/security/ISecurityCardContainer.java",
    "content": "package com.refinedmods.refinedstorage.api.network.security;\n\nimport javax.annotation.Nullable;\nimport java.util.List;\n\n/**\n * Represents a network node that contains security cards.\n */\npublic interface ISecurityCardContainer {\n    /**\n     * @return the security cards in this container, {@link ISecurityCard#getOwner()} CANNOT be null for any card in this list!\n     */\n    List<ISecurityCard> getCards();\n\n    /**\n     * @return the global security card in this container, or null if there is none, {@link ISecurityCard#getOwner()}) can be null!\n     */\n    @Nullable\n    ISecurityCard getGlobalCard();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/security/ISecurityManager.java",
    "content": "package com.refinedmods.refinedstorage.api.network.security;\n\nimport net.minecraft.world.entity.player.Player;\n\n/**\n * The security manager of a network.\n */\npublic interface ISecurityManager {\n    /**\n     * @param permission the permission to check for\n     * @param player     the player to check that permission for\n     * @return true if the player has the given permission, false otherwise\n     */\n    boolean hasPermission(Permission permission, Player player);\n\n    /**\n     * Invalidates the security list.\n     */\n    void invalidate();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/network/security/Permission.java",
    "content": "package com.refinedmods.refinedstorage.api.network.security;\n\n/**\n * The various permissions a player can have in a network.\n */\npublic enum Permission {\n    /**\n     * Whether the player can insert items in a network.\n     */\n    INSERT(0),\n    /**\n     * Whether the player can extract items from a network.\n     */\n    EXTRACT(1),\n    /**\n     * Whether the player can start, cancel or view an autocrafting task.\n     */\n    AUTOCRAFTING(2),\n    /**\n     * Whether the player can open network GUIs.\n     */\n    MODIFY(3),\n    /**\n     * Whether the player can add or remove network blocks.\n     */\n    BUILD(4),\n    /**\n     * Whether the player can manage the security options for a network.\n     */\n    SECURITY(5);\n\n    private final int id;\n\n    Permission(int id) {\n        this.id = id;\n    }\n\n    public int getId() {\n        return id;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/render/IElementDrawer.java",
    "content": "package com.refinedmods.refinedstorage.api.render;\n\nimport net.minecraft.client.gui.GuiGraphics;\n\n/**\n * This {@link FunctionalInterface} is used to define a draw/render function.\n * This function use x and y coords and the element to draw.\n *\n * @param <T> the element to draw, usually {@link String}, {@link net.minecraft.world.item.ItemStack} or {@link net.neoforged.neoforge.fluids.FluidStack}\n */\n@FunctionalInterface\npublic interface IElementDrawer<T> {\n    /**\n     * @param graphics the graphics\n     * @param x        the x axis\n     * @param y        the y axis\n     * @param element  the element type\n     */\n    void draw(GuiGraphics graphics, int x, int y, T element);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/render/IElementDrawers.java",
    "content": "package com.refinedmods.refinedstorage.api.render;\n\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\n\n/**\n * Interface specifying default element drawers.\n */\npublic interface IElementDrawers {\n    /**\n     * @return an item drawer\n     */\n    default IElementDrawer<ItemStack> getItemDrawer() {\n        return getNullDrawer();\n    }\n\n    /**\n     * @return a fluid drawer\n     */\n    default IElementDrawer<FluidStack> getFluidDrawer() {\n        return getNullDrawer();\n    }\n\n    /**\n     * @return a string drawer\n     */\n    default IElementDrawer<String> getStringDrawer() {\n        return getNullDrawer();\n    }\n\n    /**\n     * @return an overlay drawer\n     */\n    default IElementDrawer<Integer> getOverlayDrawer() {\n        return getNullDrawer();\n    }\n\n    default IElementDrawer<Void> getErrorDrawer() {\n        return getNullDrawer();\n    }\n\n    /**\n     * DO NOT OVERRIDE!\n     *\n     * @param <T> any type of drawer\n     * @return a drawer that does nothing\n     */\n    default <T> IElementDrawer<T> getNullDrawer() {\n        return (poseStack, x, y, element) -> {\n            // NO OP\n        };\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/AccessType.java",
    "content": "package com.refinedmods.refinedstorage.api.storage;\n\n/**\n * The access type of a storage.\n */\npublic enum AccessType {\n    /**\n     * Insert and extract ability.\n     */\n    INSERT_EXTRACT(0),\n    /**\n     * Only insert ability.\n     */\n    INSERT(1),\n    /**\n     * Only extract ability.\n     */\n    EXTRACT(2);\n\n    private final int id;\n\n    /**\n     * @param id the id of this access type\n     */\n    AccessType(int id) {\n        this.id = id;\n    }\n\n    /**\n     * @return the id of this access type\n     */\n    public int getId() {\n        return id;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/IStorage.java",
    "content": "package com.refinedmods.refinedstorage.api.storage;\n\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.Collection;\nimport java.util.Comparator;\n\npublic interface IStorage<T> {\n    Comparator<IStorage<?>> COMPARATOR = (left, right) -> {\n        int compare = Integer.compare(right.getPriority(), left.getPriority());\n\n        return compare != 0 ? compare : Integer.compare(right.getStored(), left.getStored());\n    };\n\n    /**\n     * Returns the stacks of the storage.\n     * Empty stacks are allowed.\n     * Please do not copy the stacks for performance reasons.\n     * For the caller: modifying stacks is not allowed!\n     *\n     * @return stacks stored in this storage, empty stacks are allowed\n     */\n    Collection<T> getStacks();\n\n    /**\n     * Inserts a stack to this storage.\n     *\n     * @param stack  the stack prototype to insert, can be empty, do NOT modify\n     * @param size   the amount of that prototype that has to be inserted\n     * @param action the action\n     * @return an empty stack if the insert was successful, or a stack with the remainder\n     */\n    @Nonnull\n    T insert(@Nonnull T stack, int size, Action action);\n\n    /**\n     * Extracts a stack from this storage.\n     * <p>\n     * If the stack we found in the system is smaller than the requested size, return that stack anyway.\n     *\n     * @param stack  a prototype of the stack to extract, can be empty, do NOT modify\n     * @param size   the amount of that prototype that has to be extracted\n     * @param flags  the flags to compare on, see {@link IComparer}\n     * @param action the action\n     * @return an empty stack if nothing was extracted, or an extracted stack\n     */\n    @Nonnull\n    T extract(@Nonnull T stack, int size, int flags, Action action);\n\n    /**\n     * @return the amount stored in this storage\n     */\n    int getStored();\n\n    /**\n     * @return the priority of this storage\n     */\n    int getPriority();\n\n    /**\n     * @return the access type of this storage\n     */\n    AccessType getAccessType();\n\n    /**\n     * Returns the delta that needs to be added to the item or fluid storage cache AFTER insertion of the stack.\n     *\n     * @param storedPreInsertion the amount stored pre insertion\n     * @param size               the size of the stack being inserted\n     * @param remainder          the remainder that we got back, or null if no remainder was there\n     * @return the amount to increase the cache with\n     */\n    int getCacheDelta(int storedPreInsertion, int size, @Nullable T remainder);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/IStorageProvider.java",
    "content": "package com.refinedmods.refinedstorage.api.storage;\n\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport java.util.List;\n\n/**\n * Represents a node that provides the network with storage.\n */\npublic interface IStorageProvider {\n    /**\n     * @param storages the item storages\n     */\n    void addItemStorages(List<IStorage<ItemStack>> storages);\n\n    /**\n     * @param storages the fluid storages\n     */\n    void addFluidStorages(List<IStorage<FluidStack>> storages);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/StorageType.java",
    "content": "package com.refinedmods.refinedstorage.api.storage;\n\n/**\n * The storage type.\n */\npublic enum StorageType {\n    ITEM,\n    FLUID\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/cache/IStorageCache.java",
    "content": "package com.refinedmods.refinedstorage.api.storage.cache;\n\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.storage.IStorage;\nimport com.refinedmods.refinedstorage.api.storage.IStorageProvider;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\n\nimport javax.annotation.Nonnull;\nimport java.util.List;\n\n/**\n * This holds all stacks from all the connected storages from a {@link INetwork}.\n * <p>\n * Refined Storage uses this class mainly for use in Grids and Detectors to avoid querying\n * individual {@link IStorage}s constantly (performance impact) and to send and detect storage changes\n * more efficiently.\n */\npublic interface IStorageCache<T> {\n    /**\n     * Invalidates the cache.\n     * Will also call {@link IStorageCache#sort()} to sort the storages correctly.\n     * Typically called when a {@link IStorageProvider} is added or removed from the network.\n     *\n     * @param cause the cause of the invalidate\n     */\n    void invalidate(InvalidateCause cause);\n\n    /**\n     * Adds a stack to the cache.\n     * <p>\n     * Note that this doesn't modify any of the connected storages, but just modifies the cache.\n     * Use {@link IStorage#insert(Object, int, Action)} to add a stack to an actual storage.\n     * <p>\n     * Will merge it with another stack if it already exists.\n     *\n     * @param stack      the stack to add, do NOT modify\n     * @param size       the size to add\n     * @param rebuilding true if this method is called while rebuilding, false otherwise\n     * @param batched    true if this change needs to be batched\n     */\n    void add(@Nonnull T stack, int size, boolean rebuilding, boolean batched);\n\n    /**\n     * Removes a stack from the cache.\n     * <p>\n     * Note that this doesn't modify any of the connected storages, but just modifies the cache.\n     * Use {@link IStorage#extract(Object, int, int, Action)} to remove a stack from an actual storage.\n     *\n     * @param stack   the stack to remove, do NOT modify\n     * @param size    the size to remove\n     * @param batched true if this change needs to be batched, false otherwise\n     */\n    void remove(@Nonnull T stack, int size, boolean batched);\n\n    /**\n     * Notifies storage cache listeners about batched up storage cache changes.\n     */\n    void flush();\n\n    /**\n     * Adds a listener to be called when this storage cache changes.\n     *\n     * @param listener the listener\n     */\n    void addListener(IStorageCacheListener<T> listener);\n\n    /**\n     * Removes a listener from the storage cache.\n     *\n     * @param listener the listener\n     */\n    void removeListener(IStorageCacheListener<T> listener);\n\n    /**\n     * Re-attaches all listeners.\n     * In practice this means that all listeners will get a {@link IStorageCacheListener#onAttached()} call.\n     */\n    void reAttachListeners();\n\n    /**\n     * Resorts the storages in this cache according to their priority.\n     * This needs to be called when the priority of a storage changes.\n     */\n    void sort();\n\n    /**\n     * @return the list behind this cache\n     */\n    IStackList<T> getList();\n\n    /**\n     * @return a list of craftables\n     */\n    IStackList<T> getCraftablesList();\n\n    /**\n     * @return grid stacks to sync initially\n     */\n    List<? extends IGridStack> getGridStacks();\n\n    /**\n     * @return the storages connected to this network\n     */\n    List<IStorage<T>> getStorages();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/cache/IStorageCacheListener.java",
    "content": "package com.refinedmods.refinedstorage.api.storage.cache;\n\nimport com.refinedmods.refinedstorage.api.util.StackListResult;\n\nimport java.util.List;\n\n/**\n * Listens for storage cache changes.\n *\n * @param <T> the type\n */\npublic interface IStorageCacheListener<T> {\n    /**\n     * Called when this storage cache listener is attached to a storage cache.\n     */\n    void onAttached();\n\n    /**\n     * Called when the cache invalidates.\n     */\n    void onInvalidated();\n\n    /**\n     * Called when the storage cache changes.\n     *\n     * @param delta the delta\n     */\n    void onChanged(StackListResult<T> delta);\n\n    /**\n     * Called when the storage cache changes.\n     *\n     * @param deltas a list of deltas\n     */\n    void onChangedBulk(List<StackListResult<T>> deltas);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/cache/InvalidateCause.java",
    "content": "package com.refinedmods.refinedstorage.api.storage.cache;\n\npublic enum InvalidateCause {\n    UNKNOWN,\n    DISK_INVENTORY_CHANGED,\n    CONNECTED_STATE_CHANGED,\n    DEVICE_CONFIGURATION_CHANGED,\n    INITIAL_TICK_INVALIDATION,\n    NEIGHBOR_CHANGED\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/disk/IStorageDisk.java",
    "content": "package com.refinedmods.refinedstorage.api.storage.disk;\n\nimport com.refinedmods.refinedstorage.api.storage.IStorage;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\n\nimport javax.annotation.Nullable;\nimport java.util.UUID;\n\n/**\n * Represents a storage disk.\n *\n * @param <T> the storage\n */\npublic interface IStorageDisk<T> extends IStorage<T> {\n    /**\n     * @return the capacity of this storage disk\n     */\n    int getCapacity();\n\n    /**\n     * @return the id of the owner, or null if not present\n     */\n    @Nullable\n    UUID getOwner();\n\n    /**\n     * When this storage disk is inserted into a storage disk container, it has to adjust to the container's settings\n     * and use the following parameters instead.\n     *\n     * @param listener the listener to be called when the storage changes, or null for no listener\n     * @param context  the container context, containing some settings\n     */\n    void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context);\n\n    /**\n     * Writes the storage to NBT.\n     */\n    CompoundTag writeToNbt();\n\n    /**\n     * @return the factory id as registered in {@link IStorageDiskRegistry}\n     */\n    ResourceLocation getFactoryId();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/disk/IStorageDiskContainerContext.java",
    "content": "package com.refinedmods.refinedstorage.api.storage.disk;\n\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\n\n/**\n * Stores relevant information about the container where the {@link IStorageDisk} is in.\n */\npublic interface IStorageDiskContainerContext {\n    /**\n     * @return the access type\n     */\n    AccessType getAccessType();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/disk/IStorageDiskFactory.java",
    "content": "package com.refinedmods.refinedstorage.api.storage.disk;\n\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.item.ItemStack;\n\nimport javax.annotation.Nullable;\nimport java.util.UUID;\n\n/**\n * Creates a storage disk from NBT or on-demand.\n *\n * @param <T>\n */\npublic interface IStorageDiskFactory<T> {\n    /**\n     * Creates a storage disk based on NBT.\n     *\n     * @param level the level\n     * @param tag   the tag\n     * @return the storage disk\n     */\n    IStorageDisk<T> createFromNbt(ServerLevel level, CompoundTag tag);\n\n    /**\n     * Creates a storage disk item based on ID.\n     *\n     * @param disk the disk\n     * @param id   the disk id\n     * @return the storage disk\n     */\n    ItemStack createDiskItem(IStorageDisk<T> disk, UUID id);\n\n    /**\n     * Creates a storage disk on-demand.\n     *\n     * @param level    the level\n     * @param capacity the capacity\n     * @param owner    the owner, or null if no owner\n     * @return the storage disk\n     */\n    IStorageDisk<T> create(ServerLevel level, int capacity, @Nullable UUID owner);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/disk/IStorageDiskListener.java",
    "content": "package com.refinedmods.refinedstorage.api.storage.disk;\n\n/**\n * Listens to storage disk changes.\n */\npublic interface IStorageDiskListener {\n    /**\n     * Called when any change happens.\n     */\n    void onChanged();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/disk/IStorageDiskManager.java",
    "content": "package com.refinedmods.refinedstorage.api.storage.disk;\n\nimport net.minecraft.world.item.ItemStack;\n\nimport javax.annotation.Nullable;\nimport java.util.Map;\nimport java.util.UUID;\n\n/**\n * Stores storage disks.\n */\npublic interface IStorageDiskManager {\n    /**\n     * Gets a storage disk by id.\n     *\n     * @param id the id\n     * @return the storage disk, or null if no storage disk is found\n     */\n    @Nullable\n    IStorageDisk get(UUID id);\n\n    /**\n     * Gets a storage disk by disk stack (a {@link IStorageDiskProvider}).\n     *\n     * @param disk the disk stack\n     * @return the storage disk, or null if no storage disk is found\n     */\n    @Nullable\n    IStorageDisk getByStack(ItemStack disk);\n\n    /**\n     * @return a map of all storage disks\n     */\n    Map<UUID, IStorageDisk> getAll();\n\n    /**\n     * Sets a storage disk.\n     *\n     * @param id   the id\n     * @param disk the disk\n     */\n    void set(UUID id, IStorageDisk disk);\n\n    /**\n     * Removes a storage disk.\n     *\n     * @param id the id\n     */\n    void remove(UUID id);\n\n    /**\n     * Marks this manager for saving.\n     */\n    void markForSaving();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/disk/IStorageDiskProvider.java",
    "content": "package com.refinedmods.refinedstorage.api.storage.disk;\n\nimport com.refinedmods.refinedstorage.api.storage.StorageType;\nimport net.minecraft.world.item.ItemStack;\n\nimport java.util.UUID;\n\n/**\n * Maps disk items to an id.\n * Implement this on a disk item.\n */\npublic interface IStorageDiskProvider {\n    /**\n     * @param disk the disk\n     * @return the id of the disk\n     */\n    UUID getId(ItemStack disk);\n\n    /**\n     * @param disk the disk\n     * @param id   the id to set\n     */\n    void setId(ItemStack disk, UUID id);\n\n    /**\n     * @param disk the disk\n     * @return true if the given disk has an id set, false otherwise\n     */\n    boolean isValid(ItemStack disk);\n\n    /**\n     * @param disk the disk\n     * @return the capacity of the given disk\n     */\n    int getCapacity(ItemStack disk);\n\n    /**\n     * @return the storage type\n     */\n    StorageType getType();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/disk/IStorageDiskRegistry.java",
    "content": "package com.refinedmods.refinedstorage.api.storage.disk;\n\nimport net.minecraft.resources.ResourceLocation;\n\nimport javax.annotation.Nullable;\n\n/**\n * Stores factories for reproducing storage disks from disk.\n */\npublic interface IStorageDiskRegistry {\n    /**\n     * Adds a factory.\n     *\n     * @param id      the id of this factory\n     * @param factory the factory\n     */\n    void add(ResourceLocation id, IStorageDiskFactory<?> factory);\n\n    /**\n     * Gets a factory.\n     *\n     * @param id the factory id\n     * @return the factory, or null if no factory was found\n     */\n    @Nullable\n    IStorageDiskFactory get(ResourceLocation id);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/disk/IStorageDiskSync.java",
    "content": "package com.refinedmods.refinedstorage.api.storage.disk;\n\nimport javax.annotation.Nullable;\nimport java.util.UUID;\n\n/**\n * Used to send requests to the server to get storage disk information ({@link StorageDiskSyncData}).\n */\npublic interface IStorageDiskSync {\n    /**\n     * Gets disk data by disk id.\n     * Can return null if there is no response yet.\n     *\n     * @param id the disk id\n     * @return the disk data, or null if there was no response from the server yet\n     */\n    @Nullable\n    StorageDiskSyncData getData(UUID id);\n\n    /**\n     * Sends a request to the server to get information from a storage disk.\n     * Can be called in a loop or in high frequency, the request is throttled.\n     *\n     * @param id the disk id\n     */\n    void sendRequest(UUID id);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/disk/StorageDiskSyncData.java",
    "content": "package com.refinedmods.refinedstorage.api.storage.disk;\n\n/**\n * Contains synced info about a storage disk.\n */\npublic class StorageDiskSyncData {\n    private final int stored;\n    private final int capacity;\n\n    public StorageDiskSyncData(int stored, int capacity) {\n        this.stored = stored;\n        this.capacity = capacity;\n    }\n\n    /**\n     * @return the amount stored\n     */\n    public int getStored() {\n        return stored;\n    }\n\n    /**\n     * @return the capacity\n     */\n    public int getCapacity() {\n        return capacity;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/externalstorage/IExternalStorage.java",
    "content": "package com.refinedmods.refinedstorage.api.storage.externalstorage;\n\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.storage.IStorage;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;\n\n/**\n * An external storage handler.\n *\n * @param <T>\n */\npublic interface IExternalStorage<T> extends IStorage<T> {\n    /**\n     * For storage disks and blocks, the network detects changes and updates the {@link IStorageCache} accordingly.\n     * However, for blocks connected to an external storage the external storage itself is responsible for bookkeeping the changes\n     * and submitting them to the {@link IStorageCache}. That bookkeeping is supposed to happen in this method.\n     * <p>\n     * It's called every external storage tick.\n     *\n     * @param network the network\n     */\n    void update(INetwork network);\n\n    /**\n     * @return the capacity of the connected storage\n     */\n    long getCapacity();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/externalstorage/IExternalStorageContext.java",
    "content": "package com.refinedmods.refinedstorage.api.storage.externalstorage;\n\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\n\n/**\n * Provides information about an external storage.\n */\npublic interface IExternalStorageContext {\n    /**\n     * @return the priority of the external storage\n     */\n    int getPriority();\n\n    /**\n     * @return the access type of the external storage\n     */\n    AccessType getAccessType();\n\n    /**\n     * @param stack the stack to test\n     * @return true if the external storage accepts the item, false otherwise\n     */\n    boolean acceptsItem(ItemStack stack);\n\n    /**\n     * @param stack the stack to test\n     * @return true if the external storage accepts the fluid, false otherwise\n     */\n    boolean acceptsFluid(FluidStack stack);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/externalstorage/IExternalStorageProvider.java",
    "content": "package com.refinedmods.refinedstorage.api.storage.externalstorage;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\n\n/**\n * Provides an external storage handler to the external storage block.\n *\n * @param <T>\n */\npublic interface IExternalStorageProvider<T> {\n    /**\n     * @param level the level\n     * @param pos   the position\n     * @return true if the provider can provide, false otherwise\n     */\n    boolean canProvide(Level level, BlockPos pos, Direction direction);\n\n    /**\n     * @param context     the context of the external storage\n     * @param blockEntity the block entity\n     * @param direction   the direction of the external storage\n     * @return the external storage handler\n     */\n    @Nonnull\n    IExternalStorage<T> provide(IExternalStorageContext context, BlockEntity blockEntity, Direction direction);\n\n    /**\n     * Returns the priority of this external storage provider.\n     * The one with the highest priority is chosen.\n     * Refined Storage's default handlers for {@link net.neoforged.neoforge.items.IItemHandler} and {@link net.neoforged.neoforge.fluids.capability.IFluidHandler} return 0.\n     * This value can't be dynamic (only fixed), since the sorted order is cached.\n     *\n     * @return the priority\n     */\n    int getPriority();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/tracker/IStorageTracker.java",
    "content": "package com.refinedmods.refinedstorage.api.storage.tracker;\n\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.world.entity.player.Player;\n\nimport javax.annotation.Nullable;\n\n/**\n * Keeps track of when a stack is changed in the system.\n */\npublic interface IStorageTracker<T> {\n    /**\n     * Updates the storage tracker entry for a stack, changing it's player name and modification time.\n     *\n     * @param player player\n     * @param stack  the stack\n     */\n    void changed(Player player, T stack);\n\n    /**\n     * @param stack the stack\n     * @return the entry, or null if the stack hasn't been modified yet\n     */\n    @Nullable\n    StorageTrackerEntry get(T stack);\n\n    /**\n     * initialize tracker from nbt\n     *\n     * @param nbt to read from\n     */\n    void readFromNbt(ListTag nbt);\n\n    /**\n     * write data to nbt\n     *\n     * @return data as nbt\n     */\n    ListTag serializeNbt();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/tracker/IStorageTrackerManager.java",
    "content": "package com.refinedmods.refinedstorage.api.storage.tracker;\n\nimport com.refinedmods.refinedstorage.api.storage.StorageType;\n\nimport java.util.UUID;\n\npublic interface IStorageTrackerManager {\n\n    /**\n     * Marks this manager for saving.\n     */\n    void markForSaving();\n\n    /**\n     * get a storage tracker or create a new Storage Tracker if it doesn't exist\n     *\n     * @param itemStorageTrackerId UUID for that tracker\n     * @param type                 Storage type of that tracker\n     * @return StorageTracker\n     */\n    IStorageTracker<?> getOrCreate(UUID itemStorageTrackerId, StorageType type);\n\n    /**\n     * @param id of the Storage tracker that will be removed\n     */\n    void remove(UUID id);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/storage/tracker/StorageTrackerEntry.java",
    "content": "package com.refinedmods.refinedstorage.api.storage.tracker;\n\n/**\n * Represents a storage tracker entry.\n */\npublic class StorageTrackerEntry {\n    private final long time;\n    private final String name;\n\n    public StorageTrackerEntry(long time, String name) {\n        this.time = time;\n        this.name = name;\n    }\n\n    /**\n     * @return the modification time\n     */\n    public long getTime() {\n        return time;\n    }\n\n    /**\n     * @return the name of the player who modified this item\n     */\n    public String getName() {\n        return name;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/util/Action.java",
    "content": "package com.refinedmods.refinedstorage.api.util;\n\n/**\n * Defines how an action is performed.\n */\npublic enum Action {\n    /**\n     * Performs the action.\n     */\n    PERFORM,\n    /**\n     * Gives back the same return as called with PERFORM, but doesn't mutate the underlying structure.\n     */\n    SIMULATE\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/util/IComparer.java",
    "content": "package com.refinedmods.refinedstorage.api.util;\n\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nonnull;\n\n/**\n * Utilities for comparing item and fluid stacks.\n */\npublic interface IComparer {\n    int COMPARE_NBT = 1;\n    int COMPARE_QUANTITY = 2;\n\n    /**\n     * Compares two stacks by the given flags.\n     *\n     * @param left  the left stack\n     * @param right the right stack\n     * @param flags the flags to compare with\n     * @return true if the left and right stack are the same, false otherwise\n     */\n    boolean isEqual(@Nonnull ItemStack left, @Nonnull ItemStack right, int flags);\n\n    /**\n     * Compares two stacks by NBT, damage and quantity.\n     *\n     * @param left  the left stack\n     * @param right the right stack\n     * @return true if the left and right stack are the same, false otherwise\n     */\n    default boolean isEqual(@Nonnull ItemStack left, @Nonnull ItemStack right) {\n        return isEqual(left, right, COMPARE_NBT | COMPARE_QUANTITY);\n    }\n\n    /**\n     * Compares two stacks by NBT and damage.\n     *\n     * @param left  the left stack\n     * @param right the right stack\n     * @return true if the left and right stack are the same, false otherwise\n     */\n    default boolean isEqualNoQuantity(@Nonnull ItemStack left, @Nonnull ItemStack right) {\n        return isEqual(left, right, COMPARE_NBT);\n    }\n\n    /**\n     * Compares two stacks by the given flags.\n     *\n     * @param left  the left stack\n     * @param right the right stack\n     * @param flags the flags to compare with\n     * @return true if the left and right stack are the same, false otherwise\n     */\n    boolean isEqual(@Nonnull FluidStack left, @Nonnull FluidStack right, int flags);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/util/IFilter.java",
    "content": "package com.refinedmods.refinedstorage.api.util;\n\n/**\n * A filter.\n */\npublic interface IFilter {\n    int MODE_WHITELIST = 0;\n    int MODE_BLACKLIST = 1;\n\n    /**\n     * @return the stack being filtered\n     */\n    Object getStack();\n\n    /**\n     * @return the compare flags, see {@link IComparer}\n     */\n    int getCompare();\n\n    /**\n     * @return the mode, whitelist or blacklist\n     */\n    int getMode();\n\n    /**\n     * @return true if this is a mod filter, false otherwise\n     */\n    boolean isModFilter();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/util/IQuantityFormatter.java",
    "content": "package com.refinedmods.refinedstorage.api.util;\n\n/**\n * Utilities for formatting quantities.\n */\npublic interface IQuantityFormatter {\n    /**\n     * Formats a quantity as they are formatted in the Grid.\n     * Formatted as following: \"####0.#\".\n     * <p>\n     * If the quantity is equal to or bigger than 1000 it will be displayed as the quantity divided by 1000 (without any decimals) and a \"K\" appended.\n     * If the quantity is equal to or bigger than 1000000 it will be displayed as the quantity divided by 1000000 (without any decimals) and a \"M\" appended.\n     *\n     * @param qty the quantity\n     * @return the formatted quantity\n     */\n    String formatWithUnits(int qty);\n\n    /**\n     * Formats a quantity as they are formatted in the Grid.\n     * Formatted as following: \"####0.#\".\n     * <p>\n     * If the quantity is equal to or bigger than 1000 it will be displayed as the quantity divided by 1000 (without any decimals) and a \"K\" appended.\n     * If the quantity is equal to or bigger than 1000000 it will be displayed as the quantity divided by 1000000 (without any decimals) and a \"M\" appended.\n     *\n     * @param qty the quantity\n     * @return the formatted quantity\n     */\n    String formatWithUnits(long qty);\n\n    /**\n     * Formats a quantity as they are formatted on the disk tooltips.\n     * Formatted as following: \"#,###\".\n     *\n     * @param qty the quantity\n     * @return the formatted quantity\n     */\n    String format(int qty);\n\n    /**\n     * Formats a quantity as they are formatted on the disk tooltips.\n     * Formatted as following: \"#,###\".\n     *\n     * @param qty the quantity\n     * @return the formatted quantity\n     */\n    String format(long qty);\n\n    /**\n     * Divides quantity by 1000 and appends \"B\".\n     *\n     * @param qty the quantity\n     * @return the formatted quantity\n     */\n    String formatInBucketForm(int qty);\n\n    /**\n     * Used in Fluid Grid.\n     *\n     * @param qty the quantity\n     * @return the formatted quantity\n     */\n    String formatInBucketFormWithOnlyTrailingDigitsIfZero(int qty);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/util/IStackList.java",
    "content": "package com.refinedmods.refinedstorage.api.util;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.Collection;\nimport java.util.UUID;\n\n/**\n * A stack list.\n */\npublic interface IStackList<T> {\n    /**\n     * Adds a stack to the list, will merge it with another stack if it already exists in the list.\n     *\n     * @param stack the stack\n     * @param size  the size to add\n     * @return the result\n     */\n    StackListResult<T> add(@Nonnull T stack, int size);\n\n    /**\n     * Adds a stack to the list, will merge it with another stack if it already exists in the list.\n     *\n     * @param stack the stack\n     * @return the result\n     */\n    StackListResult<T> add(@Nonnull T stack);\n\n    /**\n     * Decrements the count of that stack in the list.\n     *\n     * @param stack the stack\n     * @param size  the size to remove\n     * @return the result, or null if the stack wasn't present\n     */\n    @Nullable\n    StackListResult<T> remove(@Nonnull T stack, int size);\n\n    /**\n     * Decrements the count of that stack in the list.\n     *\n     * @param stack the stack\n     * @return the result, or null if the stack wasn't present\n     */\n    @Nullable\n    StackListResult<T> remove(@Nonnull T stack);\n\n    /**\n     * Returns a stack.\n     *\n     * @param stack the stack to search for\n     * @return the stack, or null if no stack was found\n     */\n    @Nullable\n    default T get(@Nonnull T stack) {\n        return get(stack, IComparer.COMPARE_NBT);\n    }\n\n    /**\n     * Returns the amount in this list, based on the stack and the flags.\n     *\n     * @param stack the stack\n     * @param flags the flags\n     * @return the count, 0 if not found\n     */\n    int getCount(@Nonnull T stack, int flags);\n\n    /**\n     * @param stack the stack\n     * @return the count, 0 if not found\n     */\n    default int getCount(@Nonnull T stack) {\n        return getCount(stack, IComparer.COMPARE_NBT);\n    }\n\n    /**\n     * Returns a stack.\n     *\n     * @param stack the stack to search for\n     * @param flags the flags to compare on, see {@link IComparer}\n     * @return the stack, or null if no stack was found\n     */\n    @Nullable\n    T get(@Nonnull T stack, int flags);\n\n    /**\n     * Returns a stack entry.\n     *\n     * @param stack the stack to search for\n     * @param flags the flags to compare on, see {@link IComparer}\n     * @return the stack entry, or null if no stack entry was found\n     */\n    @Nullable\n    StackListEntry<T> getEntry(@Nonnull T stack, int flags);\n\n    /**\n     * Returns a stack.\n     *\n     * @param id the id of the entry to search for\n     * @return the stack, or null if no stack was found\n     */\n    @Nullable\n    T get(UUID id);\n\n    /**\n     * Clears the list.\n     */\n    void clear();\n\n    /**\n     * @return true if the list is empty, false otherwise\n     */\n    boolean isEmpty();\n\n    /**\n     * @return a collection of stacks in this list\n     */\n    @Nonnull\n    Collection<StackListEntry<T>> getStacks();\n\n    /**\n     * @return a collection of stacks matching the given type (ignoring NBT)\n     */\n    @Nonnull\n    Collection<StackListEntry<T>> getStacks(@Nonnull T stack);\n\n    /**\n     * @return a new copy of this list, with the stacks in it copied as well\n     */\n    @Nonnull\n    IStackList<T> copy();\n\n    /**\n     * @return the amount of elements in this list\n     */\n    int size();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/util/StackListEntry.java",
    "content": "package com.refinedmods.refinedstorage.api.util;\n\nimport java.util.UUID;\n\n/**\n * Represents a stack in a stack list.\n *\n * @param <T> the stack type\n */\npublic class StackListEntry<T> {\n    private final UUID id;\n    private final T stack;\n\n    public StackListEntry(T stack) {\n        this.stack = stack;\n        this.id = UUID.randomUUID();\n    }\n\n    public StackListEntry(UUID id, T stack) {\n        this.id = id;\n        this.stack = stack;\n    }\n\n    /**\n     * The unique id of the entry.\n     * This id is NOT persisted, nor does it hold any relation to the contained stack.\n     * It is randomly generated.\n     *\n     * @return the id\n     */\n    public UUID getId() {\n        return id;\n    }\n\n    /**\n     * @return the stack\n     */\n    public T getStack() {\n        return stack;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/api/util/StackListResult.java",
    "content": "package com.refinedmods.refinedstorage.api.util;\n\nimport java.util.UUID;\n\n/**\n * Contains the result of a stack list manipulation.\n *\n * @param <T> the stack type\n */\npublic class StackListResult<T> {\n    private final T stack;\n    private final UUID id;\n    private final int change;\n\n    public StackListResult(T stack, UUID id, int change) {\n        this.stack = stack;\n        this.id = id;\n        this.change = change;\n    }\n\n    /**\n     * @return the stack\n     */\n    public T getStack() {\n        return stack;\n    }\n\n    /**\n     * @return the id of the {@link StackListEntry}\n     */\n    public UUID getId() {\n        return id;\n    }\n\n    /**\n     * @return the change/delta value, is positive if this was a stack addition, or negative if it's a stack removal\n     */\n    public int getChange() {\n        return change;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/API.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl;\n\nimport com.refinedmods.refinedstorage.api.IRSAPI;\nimport com.refinedmods.refinedstorage.api.RSAPIInject;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternRenderHandler;\nimport com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementList;\nimport com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementRegistry;\nimport com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElementRegistry;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingRequestInfo;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTaskRegistry;\nimport com.refinedmods.refinedstorage.api.network.INetworkManager;\nimport com.refinedmods.refinedstorage.api.network.grid.ICraftingGridBehavior;\nimport com.refinedmods.refinedstorage.api.network.grid.IGridManager;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNodeManager;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNodeRegistry;\nimport com.refinedmods.refinedstorage.api.storage.StorageType;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskManager;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskRegistry;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskSync;\nimport com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorageProvider;\nimport com.refinedmods.refinedstorage.api.storage.tracker.IStorageTrackerManager;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.api.util.IQuantityFormatter;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementList;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementRegistry;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.CraftingPreviewElementRegistry;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.CraftingRequestInfo;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.CraftingTaskRegistry;\nimport com.refinedmods.refinedstorage.apiimpl.network.NetworkManager;\nimport com.refinedmods.refinedstorage.apiimpl.network.NetworkNodeManager;\nimport com.refinedmods.refinedstorage.apiimpl.network.NetworkNodeRegistry;\nimport com.refinedmods.refinedstorage.apiimpl.network.grid.CraftingGridBehavior;\nimport com.refinedmods.refinedstorage.apiimpl.network.grid.GridManager;\nimport com.refinedmods.refinedstorage.apiimpl.storage.disk.FluidStorageDisk;\nimport com.refinedmods.refinedstorage.apiimpl.storage.disk.ItemStorageDisk;\nimport com.refinedmods.refinedstorage.apiimpl.storage.disk.StorageDiskManager;\nimport com.refinedmods.refinedstorage.apiimpl.storage.disk.StorageDiskRegistry;\nimport com.refinedmods.refinedstorage.apiimpl.storage.disk.StorageDiskSync;\nimport com.refinedmods.refinedstorage.apiimpl.storage.tracker.StorageTrackerManager;\nimport com.refinedmods.refinedstorage.apiimpl.util.Comparer;\nimport com.refinedmods.refinedstorage.apiimpl.util.FluidStackList;\nimport com.refinedmods.refinedstorage.apiimpl.util.ItemStackList;\nimport com.refinedmods.refinedstorage.apiimpl.util.QuantityFormatter;\nimport com.refinedmods.refinedstorage.util.StackUtils;\n\nimport java.lang.reflect.Field;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.EnumMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.TreeSet;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.nbt.Tag;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.saveddata.SavedData;\nimport net.neoforged.fml.ModList;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\nimport net.neoforged.neoforgespi.language.ModFileScanData;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\nimport org.objectweb.asm.Type;\n\npublic class API implements IRSAPI {\n    private static final Logger LOGGER = LogManager.getLogger(API.class);\n\n    private static final IRSAPI INSTANCE = new API();\n\n    private final IComparer comparer = new Comparer();\n    private final IQuantityFormatter quantityFormatter = new QuantityFormatter();\n    private final INetworkNodeRegistry networkNodeRegistry = new NetworkNodeRegistry();\n    private final ICraftingTaskRegistry craftingTaskRegistry = new CraftingTaskRegistry();\n    private final ICraftingMonitorElementRegistry craftingMonitorElementRegistry = new CraftingMonitorElementRegistry();\n    private final ICraftingPreviewElementRegistry craftingPreviewElementRegistry = new CraftingPreviewElementRegistry();\n    private final IGridManager gridManager = new GridManager();\n    private final ICraftingGridBehavior craftingGridBehavior = new CraftingGridBehavior();\n    private final IStorageDiskRegistry storageDiskRegistry = new StorageDiskRegistry();\n    private final IStorageDiskSync storageDiskSync = new StorageDiskSync();\n    private final Map<StorageType, TreeSet<IExternalStorageProvider<?>>> externalStorageProviders =\n        new EnumMap<>(StorageType.class);\n    private final List<ICraftingPatternRenderHandler> patternRenderHandlers = new LinkedList<>();\n\n    public static IRSAPI instance() {\n        return INSTANCE;\n    }\n\n    public static void deliver() {\n        Type annotationType = Type.getType(RSAPIInject.class);\n\n        List<ModFileScanData.AnnotationData> annotations = ModList.get().getAllScanData().stream()\n            .map(ModFileScanData::getAnnotations)\n            .flatMap(Collection::stream)\n            .filter(a -> annotationType.equals(a.annotationType()))\n            .toList();\n\n        LOGGER.info(\"Found {} RS API injection {}\", annotations.size(), annotations.size() == 1 ? \"point\" : \"points\");\n\n        for (ModFileScanData.AnnotationData annotation : annotations) {\n            try {\n                Class<?> clazz = Class.forName(annotation.clazz().getClassName());\n                Field field = clazz.getField(annotation.memberName());\n\n                if (field.getType() == IRSAPI.class) {\n                    field.set(null, INSTANCE);\n                }\n\n                LOGGER.info(\"Injected RS API in {} {}\", annotation.clazz().getClassName(), annotation.memberName());\n            } catch (ClassNotFoundException | IllegalAccessException | IllegalArgumentException | NoSuchFieldException |\n                     SecurityException e) {\n                LOGGER.error(\"Could not inject RS API in {} {}\", annotation.clazz().getClassName(),\n                    annotation.memberName(), e);\n            }\n        }\n    }\n\n    @Nonnull\n    @Override\n    public IComparer getComparer() {\n        return comparer;\n    }\n\n    @Override\n    @Nonnull\n    public IQuantityFormatter getQuantityFormatter() {\n        return quantityFormatter;\n    }\n\n    @Override\n    @Nonnull\n    public INetworkNodeRegistry getNetworkNodeRegistry() {\n        return networkNodeRegistry;\n    }\n\n    @Override\n    public INetworkNodeManager getNetworkNodeManager(ServerLevel level) {\n        return level.getDataStorage().computeIfAbsent(new SavedData.Factory<>(\n            () -> new NetworkNodeManager(level),\n            tag -> {\n                NetworkNodeManager manager = new NetworkNodeManager(level);\n                manager.load(tag);\n                return manager;\n            }\n        ), NetworkNodeManager.NAME);\n    }\n\n    @Override\n    public INetworkManager getNetworkManager(ServerLevel level) {\n        return level.getDataStorage().computeIfAbsent(new SavedData.Factory<>(\n            () -> new NetworkManager(level),\n            tag -> {\n                NetworkManager manager = new NetworkManager(level);\n                manager.load(tag);\n                return manager;\n            }\n        ), NetworkManager.NAME);\n    }\n\n    @Override\n    @Nonnull\n    public ICraftingTaskRegistry getCraftingTaskRegistry() {\n        return craftingTaskRegistry;\n    }\n\n    @Override\n    @Nonnull\n    public ICraftingMonitorElementRegistry getCraftingMonitorElementRegistry() {\n        return craftingMonitorElementRegistry;\n    }\n\n    @Override\n    @Nonnull\n    public ICraftingPreviewElementRegistry getCraftingPreviewElementRegistry() {\n        return craftingPreviewElementRegistry;\n    }\n\n    @Nonnull\n    @Override\n    public IStackList<ItemStack> createItemStackList() {\n        return new ItemStackList();\n    }\n\n    @Override\n    @Nonnull\n    public IStackList<FluidStack> createFluidStackList() {\n        return new FluidStackList();\n    }\n\n    @Override\n    @Nonnull\n    public ICraftingMonitorElementList createCraftingMonitorElementList() {\n        return new CraftingMonitorElementList();\n    }\n\n    @Nonnull\n    @Override\n    public IGridManager getGridManager() {\n        return gridManager;\n    }\n\n    @Nonnull\n    @Override\n    public ICraftingGridBehavior getCraftingGridBehavior() {\n        return craftingGridBehavior;\n    }\n\n    @Nonnull\n    @Override\n    public IStorageDiskRegistry getStorageDiskRegistry() {\n        return storageDiskRegistry;\n    }\n\n    @Nonnull\n    @Override\n    public IStorageDiskManager getStorageDiskManager(ServerLevel level) {\n        ServerLevel overworld = level.getServer().overworld(); // Get the overworld\n\n        return overworld.getDataStorage().computeIfAbsent(new SavedData.Factory<>(\n            () -> new StorageDiskManager(overworld),\n            tag -> {\n                StorageDiskManager manager = new StorageDiskManager(overworld);\n                manager.load(tag);\n                return manager;\n            }\n        ), StorageDiskManager.NAME);\n    }\n\n    @Nonnull\n    @Override\n    public IStorageDiskSync getStorageDiskSync() {\n        return storageDiskSync;\n    }\n\n    @Nonnull\n    @Override\n    public IStorageTrackerManager getStorageTrackerManager(ServerLevel level) {\n        ServerLevel overworld = level.getServer().overworld(); // Get the overworld\n        return overworld.getDataStorage().computeIfAbsent(new SavedData.Factory<>(\n            StorageTrackerManager::new,\n            tag -> {\n                StorageTrackerManager manager = new StorageTrackerManager();\n                manager.load(tag);\n                return manager;\n            }\n        ), StorageTrackerManager.NAME);\n    }\n\n    @Override\n    public void addExternalStorageProvider(StorageType type, IExternalStorageProvider<?> provider) {\n        externalStorageProviders.computeIfAbsent(type,\n            k -> new TreeSet<>((a, b) -> Integer.compare(b.getPriority(), a.getPriority()))).add(provider);\n    }\n\n    @Override\n    public Set<IExternalStorageProvider<?>> getExternalStorageProviders(StorageType type) {\n        TreeSet<IExternalStorageProvider<?>> providers = externalStorageProviders.get(type);\n\n        return providers == null ? Collections.emptySet() : providers;\n    }\n\n    @Override\n    @Nonnull\n    public IStorageDisk<ItemStack> createDefaultItemDisk(ServerLevel level, int capacity, @Nullable Player owner) {\n        if (level == null) {\n            throw new IllegalArgumentException(\"Level cannot be null\");\n        }\n\n        return new ItemStorageDisk(level, capacity, owner == null ? null : owner.getGameProfile().getId());\n    }\n\n    @Override\n    @Nonnull\n    public IStorageDisk<FluidStack> createDefaultFluidDisk(ServerLevel level, int capacity, @Nullable Player owner) {\n        if (level == null) {\n            throw new IllegalArgumentException(\"Level cannot be null\");\n        }\n\n        return new FluidStorageDisk(level, capacity, owner == null ? null : owner.getGameProfile().getId());\n    }\n\n    @Override\n    public ICraftingRequestInfo createCraftingRequestInfo(ItemStack stack, int count) {\n        return new CraftingRequestInfo(ItemHandlerHelper.copyStackWithSize(stack, count));\n    }\n\n    @Override\n    public ICraftingRequestInfo createCraftingRequestInfo(FluidStack stack, int count) {\n        return new CraftingRequestInfo(StackUtils.copy(stack, count));\n    }\n\n    @Override\n    public ICraftingRequestInfo createCraftingRequestInfo(CompoundTag tag) throws CraftingTaskReadException {\n        return new CraftingRequestInfo(tag);\n    }\n\n    @Override\n    public void addPatternRenderHandler(ICraftingPatternRenderHandler renderHandler) {\n        patternRenderHandlers.add(renderHandler);\n    }\n\n    @Override\n    public List<ICraftingPatternRenderHandler> getPatternRenderHandlers() {\n        return patternRenderHandlers;\n    }\n\n    @Override\n    public int getItemStackHashCode(ItemStack stack) {\n        int result = stack.getItem().hashCode();\n\n        if (stack.hasTag()) {\n            result = getHashCode(stack.getTag(), result);\n        }\n\n        return result;\n    }\n\n    private int getHashCode(Tag tag, int result) {\n        if (tag instanceof CompoundTag) {\n            result = getHashCode((CompoundTag) tag, result);\n        } else if (tag instanceof ListTag) {\n            result = getHashCode((ListTag) tag, result);\n        } else {\n            result = 31 * result + tag.hashCode();\n        }\n\n        return result;\n    }\n\n    private int getHashCode(CompoundTag tag, int result) {\n        for (String key : tag.getAllKeys()) {\n            result = 31 * result + key.hashCode();\n            result = getHashCode(tag.get(key), result);\n        }\n\n        return result;\n    }\n\n    private int getHashCode(ListTag tag, int result) {\n        for (Tag tagItem : tag) {\n            result = getHashCode(tagItem, result);\n        }\n\n        return result;\n    }\n\n    @Override\n    public int getFluidStackHashCode(FluidStack stack) {\n        int result = stack.getFluid().hashCode();\n\n        if (stack.getTag() != null) {\n            result = getHashCode(stack.getTag(), result);\n        }\n\n        return result;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/AllowedTagList.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting;\n\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.nbt.StringTag;\nimport net.minecraft.nbt.Tag;\nimport net.minecraft.resources.ResourceLocation;\n\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\npublic class AllowedTagList {\n    private static final String NBT_ALLOWED_ITEM_TAGS = \"AllowedItemTags\";\n    private static final String NBT_ALLOWED_FLUID_TAGS = \"AllowedFluidTags\";\n    @Nullable\n    private final Runnable listener;\n    private List<Set<ResourceLocation>> allowedItemTags = new ArrayList<>();\n    private List<Set<ResourceLocation>> allowedFluidTags = new ArrayList<>();\n\n    public AllowedTagList(@Nullable Runnable listener, int size) {\n        for (int i = 0; i < size; ++i) {\n            allowedItemTags.add(new HashSet<>());\n            allowedFluidTags.add(new HashSet<>());\n        }\n\n        this.listener = listener;\n    }\n\n    public CompoundTag writeToNbt() {\n        CompoundTag tag = new CompoundTag();\n\n        tag.put(NBT_ALLOWED_ITEM_TAGS, getList(allowedItemTags));\n        tag.put(NBT_ALLOWED_FLUID_TAGS, getList(allowedFluidTags));\n\n        return tag;\n    }\n\n    public void readFromNbt(CompoundTag tag) {\n        if (tag.contains(NBT_ALLOWED_ITEM_TAGS)) {\n            applyList(allowedItemTags, tag.getList(NBT_ALLOWED_ITEM_TAGS, Tag.TAG_LIST));\n        }\n\n        if (tag.contains(NBT_ALLOWED_FLUID_TAGS)) {\n            applyList(allowedFluidTags, tag.getList(NBT_ALLOWED_FLUID_TAGS, Tag.TAG_LIST));\n        }\n    }\n\n    private ListTag getList(List<Set<ResourceLocation>> tagsPerSlot) {\n        ListTag list = new ListTag();\n\n        for (Set<ResourceLocation> tags : tagsPerSlot) {\n            ListTag subList = new ListTag();\n\n            tags.forEach(t -> subList.add(StringTag.valueOf(t.toString())));\n\n            list.add(subList);\n        }\n\n        return list;\n    }\n\n    private void applyList(List<Set<ResourceLocation>> list, ListTag tagList) {\n        for (int i = 0; i < tagList.size(); ++i) {\n            ListTag subList = tagList.getList(i);\n\n            for (int j = 0; j < subList.size(); ++j) {\n                list.get(i).add(new ResourceLocation(subList.getString(j)));\n            }\n        }\n    }\n\n    public List<Set<ResourceLocation>> getAllowedItemTags() {\n        return allowedItemTags;\n    }\n\n    public void setAllowedItemTags(List<Set<ResourceLocation>> allowedItemTags) {\n        this.allowedItemTags = allowedItemTags;\n\n        notifyListener();\n    }\n\n    public List<Set<ResourceLocation>> getAllowedFluidTags() {\n        return allowedFluidTags;\n    }\n\n    public void setAllowedFluidTags(List<Set<ResourceLocation>> allowedFluidTags) {\n        this.allowedFluidTags = allowedFluidTags;\n\n        notifyListener();\n    }\n\n    public void setAllowedItemTags(int slot, Set<ResourceLocation> allowedItemTags) {\n        this.allowedItemTags.set(slot, allowedItemTags);\n\n        notifyListener();\n    }\n\n    public void setAllowedFluidTags(int slot, Set<ResourceLocation> allowedFluidTags) {\n        this.allowedFluidTags.set(slot, allowedFluidTags);\n\n        notifyListener();\n    }\n\n    public void clearItemTags(int slot) {\n        this.allowedItemTags.get(slot).clear();\n\n        notifyListener();\n    }\n\n    public void clearFluidTags(int slot) {\n        this.allowedFluidTags.get(slot).clear();\n\n        notifyListener();\n    }\n\n    private void notifyListener() {\n        if (listener != null) {\n            listener.run();\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/CraftingManager.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer;\nimport com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorListener;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.*;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.INetworkNodeGraphEntry;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.calculator.CalculationResult;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.nbt.Tag;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.material.Fluid;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.*;\n\npublic class CraftingManager implements ICraftingManager {\n    private static final int THROTTLE_DELAY_MS = 3000;\n\n    private static final Logger LOGGER = LogManager.getLogger(CraftingManager.class);\n\n    private static final String NBT_TASKS = \"Tasks\";\n    private static final String NBT_TASK_TYPE = \"Type\";\n    private static final String NBT_TASK_DATA = \"Task\";\n\n    private final INetwork network;\n\n    private final Map<Component, List<IItemHandlerModifiable>> containerInventories = new LinkedHashMap<>();\n    private final Map<ICraftingPattern, Set<ICraftingPatternContainer>> patternToContainer = new HashMap<>();\n\n    private final List<ICraftingPattern> patterns = new ArrayList<>();\n    private final Map<FluidStackKey, ICraftingPattern> fluidPatternsByOutput = new HashMap<>();\n    private final Map<ItemStackKey, ICraftingPattern> itemPatternsByOutput = new HashMap<>();\n\n    private final Map<UUID, ICraftingTask> tasks = new LinkedHashMap<>();\n    private final List<ICraftingTask> tasksToAdd = new ArrayList<>();\n    private final List<UUID> tasksToCancel = new ArrayList<>();\n    private final Map<Object, Long> throttledRequesters = new HashMap<>();\n    private final Set<ICraftingMonitorListener> listeners = new HashSet<>();\n    private ListTag tasksToRead;\n\n    private static class FluidStackKey {\n        private final Fluid fluid;\n        private final CompoundTag tag;\n\n        public FluidStackKey(FluidStack fluidStack) {\n            this.fluid = fluidStack.getFluid();\n            this.tag = fluidStack.getTag();\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) return true;\n            if (o == null || getClass() != o.getClass()) return false;\n            FluidStackKey that = (FluidStackKey) o;\n            return fluid.equals(that.fluid) && Objects.equals(tag, that.tag);\n        }\n\n        @Override\n        public int hashCode() {\n            return Objects.hash(fluid, tag);\n        }\n    }\n\n    private static class ItemStackKey {\n        private final Item item;\n        private final CompoundTag tag;\n\n        public ItemStackKey(ItemStack itemStack) {\n            this.item = itemStack.getItem();\n            this.tag = itemStack.getTag();\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) return true;\n            if (o == null || getClass() != o.getClass()) return false;\n            ItemStackKey that = (ItemStackKey) o;\n            return item.equals(that.item) && Objects.equals(tag, that.tag);\n        }\n\n        @Override\n        public int hashCode() {\n            return Objects.hash(item, tag);\n        }\n    }\n\n    public CraftingManager(INetwork network) {\n        this.network = network;\n    }\n\n    @Override\n    public Collection<ICraftingTask> getTasks() {\n        return tasks.values();\n    }\n\n    @Override\n    @Nullable\n    public ICraftingTask getTask(UUID id) {\n        return tasks.get(id);\n    }\n\n    @Override\n    public Map<Component, List<IItemHandlerModifiable>> getNamedContainers() {\n        return containerInventories;\n    }\n\n    @Override\n    public void start(@Nonnull ICraftingTask task) {\n        task.start();\n        tasksToAdd.add(task);\n\n        network.markDirty();\n    }\n\n    @Override\n    public void cancel(@Nullable UUID id) {\n        if (id == null) {\n            tasksToCancel.addAll(tasks.keySet());\n        } else {\n            tasksToCancel.add(id);\n        }\n\n        network.markDirty();\n    }\n\n    @Override\n    public ICalculationResult create(ItemStack stack, int quantity) {\n        ICraftingPattern pattern = getPattern(stack);\n        if (pattern == null) {\n            return new CalculationResult(CalculationResultType.NO_PATTERN);\n        }\n\n        ICraftingTaskFactory factory = API.instance().getCraftingTaskRegistry().get(pattern.getCraftingTaskFactoryId());\n        if (factory == null) {\n            return new CalculationResult(CalculationResultType.NO_PATTERN);\n        }\n\n        return factory.create(network, API.instance().createCraftingRequestInfo(stack, quantity), quantity, pattern);\n    }\n\n    @Override\n    public ICalculationResult create(FluidStack stack, int quantity) {\n        ICraftingPattern pattern = getPattern(stack);\n        if (pattern == null) {\n            return new CalculationResult(CalculationResultType.NO_PATTERN);\n        }\n\n        ICraftingTaskFactory factory = API.instance().getCraftingTaskRegistry().get(pattern.getCraftingTaskFactoryId());\n        if (factory == null) {\n            return new CalculationResult(CalculationResultType.NO_PATTERN);\n        }\n\n        return factory.create(network, API.instance().createCraftingRequestInfo(stack, quantity), quantity, pattern);\n    }\n\n    @Override\n    public void update() {\n        if (network.canRun()) {\n            if (tasksToRead != null) {\n                readTasks();\n            }\n\n            boolean changed = !tasksToCancel.isEmpty() || !tasksToAdd.isEmpty();\n\n            processTasksToCancel();\n            processTasksToAdd();\n\n            boolean anyFinished = updateTasks();\n\n            if (changed || anyFinished) {\n                onTaskChanged();\n            }\n\n            if (!tasks.isEmpty()) {\n                network.markDirty();\n            }\n        }\n    }\n\n    private void processTasksToCancel() {\n        for (UUID idToCancel : tasksToCancel) {\n            if (this.tasks.containsKey(idToCancel)) {\n                this.tasks.get(idToCancel).onCancelled();\n                this.tasks.remove(idToCancel);\n            }\n        }\n        this.tasksToCancel.clear();\n    }\n\n    private void processTasksToAdd() {\n        for (ICraftingTask task : this.tasksToAdd) {\n            this.tasks.put(task.getId(), task);\n        }\n        this.tasksToAdd.clear();\n    }\n\n    private boolean updateTasks() {\n        boolean anyFinished = false;\n\n        Iterator<Map.Entry<UUID, ICraftingTask>> it = tasks.entrySet().iterator();\n        while (it.hasNext()) {\n            ICraftingTask task = it.next().getValue();\n\n            if (task.update()) {\n                anyFinished = true;\n\n                it.remove();\n            }\n        }\n\n        return anyFinished;\n    }\n\n    private void readTasks() {\n        for (int i = 0; i < tasksToRead.size(); ++i) {\n            CompoundTag taskTag = tasksToRead.getCompound(i);\n\n            ResourceLocation taskType = new ResourceLocation(taskTag.getString(NBT_TASK_TYPE));\n            CompoundTag taskData = taskTag.getCompound(NBT_TASK_DATA);\n\n            ICraftingTaskFactory factory = API.instance().getCraftingTaskRegistry().get(taskType);\n            if (factory != null) {\n                try {\n                    ICraftingTask task = factory.createFromNbt(network, taskData);\n\n                    tasks.put(task.getId(), task);\n                } catch (CraftingTaskReadException e) {\n                    LOGGER.error(\"Could not deserialize crafting task\", e);\n                }\n            }\n        }\n\n        this.tasksToRead = null;\n    }\n\n    @Override\n    public void readFromNbt(CompoundTag tag) {\n        this.tasksToRead = tag.getList(NBT_TASKS, Tag.TAG_COMPOUND);\n    }\n\n    @Override\n    public CompoundTag writeToNbt(CompoundTag tag) {\n        ListTag list = new ListTag();\n\n        for (ICraftingTask task : tasks.values()) {\n            CompoundTag taskTag = new CompoundTag();\n\n            taskTag.putString(NBT_TASK_TYPE, task.getPattern().getCraftingTaskFactoryId().toString());\n            taskTag.put(NBT_TASK_DATA, task.writeToNbt(new CompoundTag()));\n\n            list.add(taskTag);\n        }\n\n        tag.put(NBT_TASKS, list);\n\n        return tag;\n    }\n\n    @Override\n    public void addListener(ICraftingMonitorListener listener) {\n        listeners.add(listener);\n\n        listener.onAttached();\n    }\n\n    @Override\n    public void removeListener(ICraftingMonitorListener listener) {\n        listeners.remove(listener);\n    }\n\n    @Override\n    public void onTaskChanged() {\n        listeners.forEach(ICraftingMonitorListener::onChanged);\n    }\n\n    @Override\n    @Nullable\n    public ICraftingTask request(Object source, ItemStack stack, int amount) {\n        if (isThrottled(source)) {\n            return null;\n        }\n\n        for (ICraftingTask task : getTasks()) {\n            if (task.getRequested().getItem() != null && API.instance().getComparer().isEqualNoQuantity(task.getRequested().getItem(), stack)) {\n                amount -= task.getQuantity();\n            }\n        }\n\n        if (amount > 0) {\n            ICalculationResult result = create(stack, amount);\n\n            if (result.isOk()) {\n                start(result.getTask());\n\n                return result.getTask();\n            } else {\n                throttle(source);\n            }\n        }\n\n        return null;\n    }\n\n    @Nullable\n    @Override\n    public ICraftingTask request(Object source, FluidStack stack, int amount) {\n        if (isThrottled(source)) {\n            return null;\n        }\n\n        for (ICraftingTask task : getTasks()) {\n            if (task.getRequested().getFluid() != null && API.instance().getComparer().isEqual(task.getRequested().getFluid(), stack, IComparer.COMPARE_NBT)) {\n                amount -= task.getQuantity();\n            }\n        }\n\n        if (amount > 0) {\n            ICalculationResult result = create(stack, amount);\n\n            if (result.isOk()) {\n                start(result.getTask());\n\n                return result.getTask();\n            } else {\n                throttle(source);\n            }\n        }\n\n        return null;\n    }\n\n    private void throttle(Object source) {\n        if (source != null) {\n            throttledRequesters.put(source, System.currentTimeMillis());\n        }\n    }\n\n    private boolean isThrottled(Object source) {\n        if (source == null) {\n            return false;\n        }\n\n        Long throttledSince = throttledRequesters.get(source);\n        if (throttledSince == null) {\n            return false;\n        }\n\n        return System.currentTimeMillis() - throttledSince < THROTTLE_DELAY_MS;\n    }\n\n    @Override\n    public int track(@Nonnull ItemStack stack, int size) {\n        if (stack.isEmpty()) {\n            return 0;\n        }\n\n        for (ICraftingTask task : tasks.values()) {\n            size = task.onTrackedInsert(stack, size);\n\n            if (size == 0) {\n                return 0;\n            }\n        }\n\n        return size;\n    }\n\n    @Override\n    public int track(@Nonnull FluidStack stack, int size) {\n        if (stack.isEmpty()) {\n            return 0;\n        }\n\n        for (ICraftingTask task : tasks.values()) {\n            size = task.onTrackedInsert(stack, size);\n\n            if (size == 0) {\n                return 0;\n            }\n        }\n\n        return size;\n    }\n\n    @Override\n    public List<ICraftingPattern> getPatterns() {\n        return patterns;\n    }\n\n    @Override\n    public void invalidate() {\n        this.network.getItemStorageCache().getCraftablesList().clear();\n        this.network.getFluidStorageCache().getCraftablesList().clear();\n\n        this.patterns.clear();\n        this.fluidPatternsByOutput.clear();\n        this.itemPatternsByOutput.clear();\n        this.containerInventories.clear();\n        this.patternToContainer.clear();\n\n        List<ICraftingPatternContainer> containers = getContainers();\n\n        for (ICraftingPatternContainer container : containers) {\n            for (ICraftingPattern pattern : container.getPatterns()) {\n                this.patterns.add(pattern);\n\n                for (ItemStack output : pattern.getOutputs()) {\n                    network.getItemStorageCache().getCraftablesList().add(output);\n                    this.itemPatternsByOutput.put(new ItemStackKey(output), pattern);\n                }\n\n                for (FluidStack output : pattern.getFluidOutputs()) {\n                    network.getFluidStorageCache().getCraftablesList().add(output);\n                    this.fluidPatternsByOutput.put(new FluidStackKey(output), pattern);\n                }\n\n                Set<ICraftingPatternContainer> containersForPattern = this.patternToContainer.computeIfAbsent(pattern, key -> new LinkedHashSet<>());\n                containersForPattern.add(container);\n            }\n\n            IItemHandlerModifiable handler = container.getPatternInventory();\n            if (handler != null) {\n                this.containerInventories.computeIfAbsent(container.getName(), k -> new ArrayList<>()).add(handler);\n            }\n        }\n\n        this.network.getItemStorageCache().reAttachListeners();\n        this.network.getFluidStorageCache().reAttachListeners();\n    }\n\n    private List<ICraftingPatternContainer> getContainers() {\n        List<ICraftingPatternContainer> containers = new ArrayList<>();\n\n        for (INetworkNodeGraphEntry entry : network.getNodeGraph().all()) {\n            if (entry.getNode() instanceof ICraftingPatternContainer && entry.getNode().isActive()) {\n                containers.add((ICraftingPatternContainer) entry.getNode());\n            }\n        }\n\n        containers.sort((a, b) -> b.getPosition().compareTo(a.getPosition()));\n\n        return containers;\n    }\n\n    @Override\n    public Set<ICraftingPatternContainer> getAllContainers(ICraftingPattern pattern) {\n        return patternToContainer.getOrDefault(pattern, Collections.emptySet());\n    }\n\n    @Nullable\n    @Override\n    public ICraftingPattern getPattern(ItemStack pattern) {\n        return itemPatternsByOutput.get(new ItemStackKey(pattern));\n    }\n\n    @Nullable\n    @Override\n    public ICraftingPattern getPattern(FluidStack pattern) {\n        return fluidPatternsByOutput.get(new FluidStackKey(pattern));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/CraftingPattern.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.CraftingTaskFactory;\nimport net.minecraft.core.NonNullList;\nimport net.minecraft.core.RegistryAccess;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.minecraft.world.inventory.CraftingContainer;\nimport net.minecraft.world.inventory.TransientCraftingContainer;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.crafting.CraftingRecipe;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nullable;\nimport java.util.List;\n\npublic class CraftingPattern implements ICraftingPattern {\n    private final CraftingPatternContext context;\n    private final boolean processing;\n    private final boolean exact;\n    @Nullable\n    private final CraftingRecipe recipe;\n    private final CraftingPatternInputs inputs;\n    private final CraftingPatternOutputs outputs;\n    @Nullable\n    private final AllowedTagList allowedTagList;\n\n    public CraftingPattern(CraftingPatternContext context, boolean processing, boolean exact, @Nullable CraftingRecipe recipe, CraftingPatternInputs inputs, CraftingPatternOutputs outputs, @Nullable AllowedTagList allowedTagList) {\n        this.context = context;\n        this.processing = processing;\n        this.exact = exact;\n        this.recipe = recipe;\n        this.inputs = inputs;\n        this.outputs = outputs;\n        this.allowedTagList = allowedTagList;\n    }\n\n    @Nullable\n    public AllowedTagList getAllowedTagList() {\n        return allowedTagList;\n    }\n\n    @Override\n    public ICraftingPatternContainer getContainer() {\n        return context.getContainer();\n    }\n\n    @Override\n    public ItemStack getStack() {\n        return context.getStack();\n    }\n\n    @Override\n    public boolean isValid() {\n        return true;\n    }\n\n    @Nullable\n    @Override\n    public Component getErrorMessage() {\n        return null;\n    }\n\n    @Override\n    public boolean isProcessing() {\n        return processing;\n    }\n\n    @Override\n    public List<NonNullList<ItemStack>> getInputs() {\n        return inputs.getInputs();\n    }\n\n    @Override\n    public NonNullList<ItemStack> getOutputs() {\n        return outputs.getOutputs();\n    }\n\n    public ItemStack getOutput(NonNullList<ItemStack> took, RegistryAccess registryAccess) {\n        if (processing) {\n            throw new IllegalStateException(\"Cannot get crafting output from processing pattern\");\n        }\n\n        if (took.size() != inputs.getInputs().size()) {\n            throw new IllegalArgumentException(\"The items that are taken (\" + took.size() + \") should match the inputs for this pattern (\" + inputs.getInputs().size() + \")\");\n        }\n\n        CraftingContainer craftingContainer = new DummyCraftingContainer();\n\n        for (int i = 0; i < took.size(); ++i) {\n            craftingContainer.setItem(i, took.get(i));\n        }\n\n        ItemStack result = recipe.assemble(craftingContainer, registryAccess);\n        if (result.isEmpty()) {\n            throw new IllegalStateException(\"Cannot have empty result\");\n        }\n\n        return result;\n    }\n\n    @Override\n    public NonNullList<ItemStack> getByproducts() {\n        if (processing) {\n            throw new IllegalStateException(\"Cannot get byproduct outputs from processing pattern\");\n        }\n\n        return outputs.getByproducts();\n    }\n\n    @Override\n    public NonNullList<ItemStack> getByproducts(NonNullList<ItemStack> took) {\n        if (processing) {\n            throw new IllegalStateException(\"Cannot get byproduct outputs from processing pattern\");\n        }\n\n        if (took.size() != inputs.getInputs().size()) {\n            throw new IllegalArgumentException(\"The items that are taken (\" + took.size() + \") should match the inputs for this pattern (\" + inputs.getInputs().size() + \")\");\n        }\n\n        CraftingContainer craftingContainer = new DummyCraftingContainer();\n\n        for (int i = 0; i < took.size(); ++i) {\n            craftingContainer.setItem(i, took.get(i));\n        }\n\n        NonNullList<ItemStack> remainingItems = recipe.getRemainingItems(craftingContainer);\n        NonNullList<ItemStack> sanitized = NonNullList.create();\n\n        for (ItemStack item : remainingItems) {\n            if (!item.isEmpty()) {\n                sanitized.add(item);\n            }\n        }\n\n        return sanitized;\n    }\n\n    @Override\n    public List<NonNullList<FluidStack>> getFluidInputs() {\n        return inputs.getFluidInputs();\n    }\n\n    @Override\n    public NonNullList<FluidStack> getFluidOutputs() {\n        return outputs.getFluidOutputs();\n    }\n\n    @Override\n    public ResourceLocation getCraftingTaskFactoryId() {\n        return CraftingTaskFactory.ID;\n    }\n\n    @Override\n    public boolean equals(Object otherObj) {\n        if (!(otherObj instanceof ICraftingPattern)) {\n            return false;\n        }\n\n        ICraftingPattern other = (ICraftingPattern) otherObj;\n\n        if (other.isProcessing() != processing) {\n            return false;\n        }\n\n        if ((other.getInputs().size() != inputs.getInputs().size()) ||\n            (other.getFluidInputs().size() != inputs.getFluidInputs().size()) ||\n            (other.getOutputs().size() != outputs.getOutputs().size()) ||\n            (other.getFluidOutputs().size() != outputs.getFluidOutputs().size())) {\n            return false;\n        }\n\n        if (!processing && other.getByproducts().size() != outputs.getByproducts().size()) {\n            return false;\n        }\n\n        for (int i = 0; i < inputs.getInputs().size(); ++i) {\n            List<ItemStack> inputsForSlot = inputs.getInputs().get(i);\n            List<ItemStack> otherInputsForSlot = other.getInputs().get(i);\n\n            if (inputsForSlot.size() != otherInputsForSlot.size()) {\n                return false;\n            }\n\n            for (int j = 0; j < inputsForSlot.size(); ++j) {\n                if (!API.instance().getComparer().isEqual(inputsForSlot.get(j), otherInputsForSlot.get(j))) {\n                    return false;\n                }\n            }\n        }\n\n        for (int i = 0; i < inputs.getFluidInputs().size(); ++i) {\n            List<FluidStack> inputsForSlot = inputs.getFluidInputs().get(i);\n            List<FluidStack> otherInputsForSlot = other.getFluidInputs().get(i);\n\n            if (inputsForSlot.size() != otherInputsForSlot.size()) {\n                return false;\n            }\n\n            for (int j = 0; j < inputsForSlot.size(); ++j) {\n                if (!API.instance().getComparer().isEqual(inputsForSlot.get(j), otherInputsForSlot.get(j), IComparer.COMPARE_NBT | IComparer.COMPARE_QUANTITY)) {\n                    return false;\n                }\n            }\n        }\n\n        for (int i = 0; i < outputs.getOutputs().size(); ++i) {\n            if (!API.instance().getComparer().isEqual(outputs.getOutputs().get(i), other.getOutputs().get(i))) {\n                return false;\n            }\n        }\n\n        for (int i = 0; i < outputs.getFluidOutputs().size(); ++i) {\n            if (!API.instance().getComparer().isEqual(outputs.getFluidOutputs().get(i), other.getFluidOutputs().get(i), IComparer.COMPARE_NBT | IComparer.COMPARE_QUANTITY)) {\n                return false;\n            }\n        }\n\n        if (!processing) {\n            for (int i = 0; i < outputs.getByproducts().size(); ++i) {\n                if (!API.instance().getComparer().isEqual(outputs.getByproducts().get(i), other.getByproducts().get(i))) {\n                    return false;\n                }\n            }\n        }\n\n        return true;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = 0;\n\n        result = 31 * result + (processing ? 1 : 0);\n        result = 31 * result + (exact ? 1 : 0);\n\n        for (List<ItemStack> inputsForSlot : inputs.getInputs()) {\n            for (ItemStack input : inputsForSlot) {\n                result = 31 * result + API.instance().getItemStackHashCode(input);\n            }\n        }\n\n        for (List<FluidStack> inputsForSlot : inputs.getFluidInputs()) {\n            for (FluidStack input : inputsForSlot) {\n                result = 31 * result + API.instance().getFluidStackHashCode(input);\n            }\n        }\n\n        for (ItemStack output : outputs.getOutputs()) {\n            result = 31 * result + API.instance().getItemStackHashCode(output);\n        }\n\n        for (FluidStack output : outputs.getFluidOutputs()) {\n            result = 31 * result + API.instance().getFluidStackHashCode(output);\n        }\n\n        for (ItemStack byproduct : outputs.getByproducts()) {\n            result = 31 * result + API.instance().getItemStackHashCode(byproduct);\n        }\n\n        return result;\n    }\n\n    public static class DummyCraftingContainer extends TransientCraftingContainer {\n        public DummyCraftingContainer() {\n            super(new AbstractContainerMenu(null, 0) {\n                @Override\n                public ItemStack quickMoveStack(Player p_38941_, int p_38942_) {\n                    return ItemStack.EMPTY;\n                }\n\n                @Override\n                public boolean stillValid(Player player) {\n                    return true;\n                }\n            }, 3, 3);\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/CraftingPatternContext.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer;\nimport net.minecraft.world.item.ItemStack;\n\npublic class CraftingPatternContext {\n    private final ICraftingPatternContainer container;\n    private final ItemStack stack;\n\n    public CraftingPatternContext(ICraftingPatternContainer container, ItemStack stack) {\n        this.container = container;\n        this.stack = stack;\n    }\n\n    public ICraftingPatternContainer getContainer() {\n        return container;\n    }\n\n    public ItemStack getStack() {\n        return stack;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/CraftingPatternFactory.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode;\nimport com.refinedmods.refinedstorage.item.PatternItem;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.stream.Collectors;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.core.Holder;\nimport net.minecraft.core.NonNullList;\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.core.registries.Registries;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.tags.TagKey;\nimport net.minecraft.world.inventory.CraftingContainer;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.crafting.CraftingRecipe;\nimport net.minecraft.world.item.crafting.RecipeHolder;\nimport net.minecraft.world.item.crafting.RecipeType;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.material.Fluid;\nimport net.neoforged.neoforge.fluids.FluidStack;\n\npublic class CraftingPatternFactory {\n    public static final CraftingPatternFactory INSTANCE = new CraftingPatternFactory();\n\n    public ICraftingPattern create(Level level, ICraftingPatternContainer container, ItemStack stack) {\n        CraftingPatternContext context = new CraftingPatternContext(container, stack);\n\n        boolean processing = PatternItem.isProcessing(stack);\n        boolean exact = PatternItem.isExact(stack);\n        AllowedTagList allowedTagList = PatternItem.getAllowedTags(stack);\n\n        List<NonNullList<ItemStack>> inputs = new ArrayList<>();\n        NonNullList<ItemStack> outputs = NonNullList.create();\n        NonNullList<ItemStack> byproducts = NonNullList.create();\n        List<NonNullList<FluidStack>> fluidInputs = new ArrayList<>();\n        NonNullList<FluidStack> fluidOutputs = NonNullList.create();\n        CraftingRecipe recipe = null;\n\n        try {\n            if (processing) {\n                for (int i = 0; i < GridNetworkNode.PROCESSING_MATRIX_SIZE; ++i) {\n                    fillProcessingInputs(i, stack, inputs, outputs, allowedTagList);\n                    fillProcessingFluidInputs(i, stack, fluidInputs, fluidOutputs, allowedTagList);\n                }\n\n                if (outputs.isEmpty() && fluidOutputs.isEmpty()) {\n                    throw new CraftingPatternFactoryException(\n                        Component.translatable(\"misc.refinedstorage.pattern.error.processing_no_outputs\"));\n                }\n            } else {\n                CraftingContainer craftingContainer = new CraftingPattern.DummyCraftingContainer();\n\n                for (int i = 0; i < 9; ++i) {\n                    fillCraftingInputs(craftingContainer, stack, inputs, i);\n                }\n\n                Optional<CraftingRecipe> foundRecipe =\n                    level.getRecipeManager().getRecipeFor(RecipeType.CRAFTING, craftingContainer, level)\n                        .map(RecipeHolder::value);\n                if (foundRecipe.isPresent()) {\n                    recipe = foundRecipe.get();\n\n                    byproducts = recipe.getRemainingItems(craftingContainer);\n\n                    ItemStack output = recipe.assemble(craftingContainer, level.registryAccess());\n\n                    if (!output.isEmpty()) {\n                        outputs.add(output);\n\n                        if (!exact) {\n                            modifyCraftingInputsToUseAlternatives(recipe, inputs);\n                        }\n                    } else {\n                        throw new CraftingPatternFactoryException(\n                            Component.translatable(\"misc.refinedstorage.pattern.error.no_output\"));\n                    }\n                } else {\n                    throw new CraftingPatternFactoryException(\n                        Component.translatable(\"misc.refinedstorage.pattern.error.recipe_does_not_exist\"));\n                }\n            }\n        } catch (CraftingPatternFactoryException e) {\n            return new InvalidCraftingPattern(context, e.getErrorMessage());\n        }\n\n        return new CraftingPattern(\n            context,\n            processing,\n            exact,\n            recipe,\n            new CraftingPatternInputs(inputs, fluidInputs),\n            new CraftingPatternOutputs(outputs, byproducts, fluidOutputs),\n            allowedTagList\n        );\n    }\n\n    private void fillProcessingInputs(int i, ItemStack stack, List<NonNullList<ItemStack>> inputs,\n                                      NonNullList<ItemStack> outputs, @Nullable AllowedTagList allowedTagList)\n        throws CraftingPatternFactoryException {\n        ItemStack input = PatternItem.getInputSlot(stack, i);\n\n        if (input.isEmpty()) {\n            inputs.add(NonNullList.create());\n        } else {\n            NonNullList<ItemStack> possibilities = NonNullList.create();\n\n            possibilities.add(input.copy());\n\n            if (allowedTagList != null) {\n                Collection<ResourceLocation> tagsOfItem = BuiltInRegistries.ITEM.getResourceKey(input.getItem())\n                    .flatMap(k -> BuiltInRegistries.ITEM.getHolder(k)\n                        .map(holder -> holder.tags()\n                            .map(TagKey::location)\n                            .collect(Collectors.toSet())))\n                    .orElse(Collections.emptySet());\n                Set<ResourceLocation> declaredAllowedTags = allowedTagList.getAllowedItemTags().get(i);\n\n                for (ResourceLocation declaredAllowedTag : declaredAllowedTags) {\n                    if (!tagsOfItem.contains(declaredAllowedTag)) {\n                        throw new CraftingPatternFactoryException(\n                            Component.translatable(\n                                \"misc.refinedstorage.pattern.error.tag_no_longer_applicable\",\n                                declaredAllowedTag.toString(),\n                                input.getHoverName()\n                            )\n                        );\n                    } else {\n                        TagKey<Item> tagKey = TagKey.create(Registries.ITEM, declaredAllowedTag);\n                        for (Holder<Item> element : BuiltInRegistries.ITEM.getTagOrEmpty(tagKey)) {\n                            possibilities.add(new ItemStack(element, input.getCount()));\n                        }\n                    }\n                }\n            }\n\n            inputs.add(possibilities);\n        }\n\n        ItemStack output = PatternItem.getOutputSlot(stack, i);\n        if (!output.isEmpty()) {\n            outputs.add(output);\n        }\n    }\n\n    private void fillProcessingFluidInputs(int i, ItemStack stack, List<NonNullList<FluidStack>> fluidInputs,\n                                           NonNullList<FluidStack> fluidOutputs,\n                                           @Nullable AllowedTagList allowedTagList)\n        throws CraftingPatternFactoryException {\n        FluidStack input = PatternItem.getFluidInputSlot(stack, i);\n        if (input.isEmpty()) {\n            fluidInputs.add(NonNullList.create());\n        } else {\n            NonNullList<FluidStack> possibilities = NonNullList.create();\n\n            possibilities.add(input.copy());\n\n            if (allowedTagList != null) {\n                Collection<ResourceLocation> tagsOfFluid = BuiltInRegistries.FLUID.getResourceKey(input.getFluid())\n                    .flatMap(k -> BuiltInRegistries.FLUID.getHolder(k)\n                        .map(holder -> holder.tags()\n                            .map(TagKey::location)\n                            .collect(Collectors.toSet())))\n                    .orElse(Collections.emptySet());\n                Set<ResourceLocation> declaredAllowedTags = allowedTagList.getAllowedFluidTags().get(i);\n\n                for (ResourceLocation declaredAllowedTag : declaredAllowedTags) {\n                    if (!tagsOfFluid.contains(declaredAllowedTag)) {\n                        throw new CraftingPatternFactoryException(\n                            Component.translatable(\n                                \"misc.refinedstorage.pattern.error.tag_no_longer_applicable\",\n                                declaredAllowedTag.toString(),\n                                input.getDisplayName()\n                            )\n                        );\n                    } else {\n                        TagKey<Fluid> tagKey =\n                            TagKey.create(Registries.FLUID, declaredAllowedTag);\n                        for (Holder<Fluid> element : BuiltInRegistries.FLUID.getTagOrEmpty(tagKey)) {\n                            possibilities.add(new FluidStack(element, input.getAmount()));\n                        }\n                    }\n                }\n            }\n\n            fluidInputs.add(possibilities);\n        }\n\n        FluidStack output = PatternItem.getFluidOutputSlot(stack, i);\n        if (!output.isEmpty()) {\n            fluidOutputs.add(output);\n        }\n    }\n\n    private void fillCraftingInputs(CraftingContainer inv, ItemStack stack, List<NonNullList<ItemStack>> inputs,\n                                    int i) {\n        ItemStack input = PatternItem.getInputSlot(stack, i);\n\n        inputs.add(input.isEmpty() ? NonNullList.create() : NonNullList.of(ItemStack.EMPTY, input));\n\n        inv.setItem(i, input);\n    }\n\n    private void modifyCraftingInputsToUseAlternatives(CraftingRecipe recipe, List<NonNullList<ItemStack>> inputs) {\n        if (!recipe.getIngredients().isEmpty()) {\n            inputs.clear();\n\n            for (int i = 0; i < recipe.getIngredients().size(); ++i) {\n                inputs.add(i, NonNullList.of(ItemStack.EMPTY, recipe.getIngredients().get(i).getItems()));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/CraftingPatternFactoryException.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting;\n\nimport net.minecraft.network.chat.Component;\n\npublic class CraftingPatternFactoryException extends Exception {\n    private final transient Component errorMessage;\n\n    public CraftingPatternFactoryException(Component errorMessage) {\n        this.errorMessage = errorMessage;\n    }\n\n    public Component getErrorMessage() {\n        return errorMessage;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/CraftingPatternInputs.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting;\n\nimport net.minecraft.core.NonNullList;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport java.util.List;\n\npublic class CraftingPatternInputs {\n    private final List<NonNullList<ItemStack>> inputs;\n    private final List<NonNullList<FluidStack>> fluidInputs;\n\n    public CraftingPatternInputs(List<NonNullList<ItemStack>> inputs, List<NonNullList<FluidStack>> fluidInputs) {\n        this.inputs = inputs;\n        this.fluidInputs = fluidInputs;\n    }\n\n    public List<NonNullList<ItemStack>> getInputs() {\n        return inputs;\n    }\n\n    public List<NonNullList<FluidStack>> getFluidInputs() {\n        return fluidInputs;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/CraftingPatternOutputs.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting;\n\nimport net.minecraft.core.NonNullList;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\n\npublic class CraftingPatternOutputs {\n    private final NonNullList<ItemStack> outputs;\n    private final NonNullList<ItemStack> byproducts;\n    private final NonNullList<FluidStack> fluidOutputs;\n\n    public CraftingPatternOutputs(NonNullList<ItemStack> outputs, NonNullList<ItemStack> byproducts, NonNullList<FluidStack> fluidOutputs) {\n        this.outputs = outputs;\n        this.byproducts = byproducts;\n        this.fluidOutputs = fluidOutputs;\n    }\n\n    public NonNullList<ItemStack> getOutputs() {\n        return outputs;\n    }\n\n    public NonNullList<ItemStack> getByproducts() {\n        return byproducts;\n    }\n\n    public NonNullList<FluidStack> getFluidOutputs() {\n        return fluidOutputs;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/InvalidCraftingPattern.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer;\nimport net.minecraft.core.NonNullList;\nimport net.minecraft.core.RegistryAccess;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nullable;\nimport java.util.List;\n\npublic class InvalidCraftingPattern implements ICraftingPattern {\n    private static final String EXCEPTION_MESSAGE = \"Crafting pattern is invalid\";\n\n    private final CraftingPatternContext context;\n    private final Component errorMessage;\n\n    public InvalidCraftingPattern(CraftingPatternContext context, Component errorMessage) {\n        this.context = context;\n        this.errorMessage = errorMessage;\n    }\n\n    @Override\n    public ICraftingPatternContainer getContainer() {\n        return context.getContainer();\n    }\n\n    @Override\n    public ItemStack getStack() {\n        return context.getStack();\n    }\n\n    @Override\n    public boolean isValid() {\n        return false;\n    }\n\n    @Nullable\n    @Override\n    public Component getErrorMessage() {\n        return errorMessage;\n    }\n\n    @Override\n    public boolean isProcessing() {\n        return false;\n    }\n\n    @Override\n    public List<NonNullList<ItemStack>> getInputs() {\n        throw new UnsupportedOperationException(EXCEPTION_MESSAGE);\n    }\n\n    @Override\n    public NonNullList<ItemStack> getOutputs() {\n        throw new UnsupportedOperationException(EXCEPTION_MESSAGE);\n    }\n\n    @Override\n    public ItemStack getOutput(NonNullList<ItemStack> took, RegistryAccess registryAccess) {\n        throw new UnsupportedOperationException(EXCEPTION_MESSAGE);\n    }\n\n    @Override\n    public NonNullList<ItemStack> getByproducts() {\n        throw new UnsupportedOperationException(EXCEPTION_MESSAGE);\n    }\n\n    @Override\n    public NonNullList<ItemStack> getByproducts(NonNullList<ItemStack> took) {\n        throw new UnsupportedOperationException(EXCEPTION_MESSAGE);\n    }\n\n    @Override\n    public List<NonNullList<FluidStack>> getFluidInputs() {\n        throw new UnsupportedOperationException(EXCEPTION_MESSAGE);\n    }\n\n    @Override\n    public NonNullList<FluidStack> getFluidOutputs() {\n        throw new UnsupportedOperationException(EXCEPTION_MESSAGE);\n    }\n\n    @Override\n    public ResourceLocation getCraftingTaskFactoryId() {\n        throw new UnsupportedOperationException(EXCEPTION_MESSAGE);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/craftingmonitor/CraftingMonitorElementList.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement;\nimport com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementList;\nimport net.minecraft.resources.ResourceLocation;\n\nimport java.util.*;\n\npublic class CraftingMonitorElementList implements ICraftingMonitorElementList {\n    private final List<ICraftingMonitorElement> elements = new LinkedList<>();\n    private final Map<ResourceLocation, Map<Integer, ICraftingMonitorElement>> currentLists = new LinkedHashMap<>();\n    private final Map<ResourceLocation, Map<Integer, ICraftingMonitorElement>> currentCraftingLists = new LinkedHashMap<>();\n    private final Map<ResourceLocation, Map<Integer, ICraftingMonitorElement>> currentProcessingLists = new LinkedHashMap<>();\n    private final Map<ResourceLocation, Map<Integer, ICraftingMonitorElement>> currentStorageLists = new LinkedHashMap<>();\n\n    @Override\n    public void directAdd(ICraftingMonitorElement element) {\n        elements.add(element);\n    }\n\n    @Override\n    public void addStorage(ICraftingMonitorElement element) {\n        Map<Integer, ICraftingMonitorElement> craftingElements = currentCraftingLists.get(element.getBaseId());\n        Map<Integer, ICraftingMonitorElement> processingElements = currentProcessingLists.get(element.getBaseId());\n        Map<Integer, ICraftingMonitorElement> storedElements = currentStorageLists.get(element.getBaseId());\n        boolean merged = false;\n        if (craftingElements != null) {\n            ICraftingMonitorElement existingElement = craftingElements.get(element.baseElementHashCode());\n            if (existingElement != null) {\n                if (existingElement instanceof ErrorCraftingMonitorElement) {\n                    ((ErrorCraftingMonitorElement) existingElement).mergeBases(element);\n                } else {\n                    existingElement.merge(element);\n                }\n                merged = true;\n            }\n        }\n        if (processingElements != null) {\n            ICraftingMonitorElement existingElement = processingElements.get(element.baseElementHashCode());\n            if (existingElement != null) {\n                if (existingElement instanceof ErrorCraftingMonitorElement) {\n                    ((ErrorCraftingMonitorElement) existingElement).mergeBases(element);\n                } else {\n                    existingElement.merge(element);\n                }\n                merged = true;\n            }\n        }\n        if (!merged) {\n            if (storedElements == null) {\n                storedElements = new HashMap<>();\n            }\n            storedElements.put(element.baseElementHashCode(), element);\n            currentStorageLists.put(element.getBaseId(), storedElements);\n        }\n    }\n\n    @Override\n    public void add(ICraftingMonitorElement element, boolean isProcessing) {\n        Map<Integer, ICraftingMonitorElement> currentElements = isProcessing ? currentProcessingLists.get(element.getBaseId()) : currentCraftingLists.get(element.getBaseId());\n\n        if (currentElements == null) {\n            currentElements = new LinkedHashMap<>();\n        }\n\n        ICraftingMonitorElement existingElement = currentElements.get(element.baseElementHashCode());\n\n        if (existingElement == null) {\n            existingElement = element;\n        } else {\n            existingElement.merge(element);\n        }\n\n        currentElements.put(existingElement.baseElementHashCode(), existingElement);\n        if (isProcessing) {\n            currentProcessingLists.put(existingElement.getBaseId(), currentElements);\n        } else {\n            currentCraftingLists.put(existingElement.getBaseId(), currentElements);\n        }\n\n    }\n\n    @Override\n    public void add(ICraftingMonitorElement element) {\n        Map<Integer, ICraftingMonitorElement> currentElements = currentLists.get(element.getId());\n\n        if (currentElements == null) {\n            currentElements = new HashMap<>();\n        }\n\n        ICraftingMonitorElement exitingElement = currentElements.get(element.elementHashCode());\n\n        if (exitingElement == null) {\n            exitingElement = element;\n        } else {\n            exitingElement.merge(element);\n        }\n\n        currentElements.put(exitingElement.elementHashCode(), exitingElement);\n        currentLists.put(exitingElement.getId(), currentElements);\n    }\n\n    @Override\n    public void commit() {\n        currentLists.values().stream().map(Map::values).flatMap(Collection::stream).forEach(elements::add);\n        currentLists.clear();\n        currentCraftingLists.values().stream().map(Map::values).flatMap(Collection::stream).forEach(elements::add);\n        currentCraftingLists.clear();\n        currentProcessingLists.values().stream().map(Map::values).flatMap(Collection::stream).forEach(elements::add);\n        currentProcessingLists.clear();\n        currentStorageLists.values().stream().map(Map::values).flatMap(Collection::stream).forEach(elements::add);\n        currentStorageLists.clear();\n    }\n\n    @Override\n    public List<ICraftingMonitorElement> getElements() {\n        if (!currentLists.isEmpty() || !currentCraftingLists.isEmpty() || !currentProcessingLists.isEmpty() || !currentStorageLists.isEmpty()) {\n            commit();\n        }\n\n        return elements;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/craftingmonitor/CraftingMonitorElementRegistry.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement;\nimport com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementRegistry;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.resources.ResourceLocation;\n\nimport javax.annotation.Nullable;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.function.Function;\n\npublic class CraftingMonitorElementRegistry implements ICraftingMonitorElementRegistry {\n    private final Map<ResourceLocation, Function<FriendlyByteBuf, ICraftingMonitorElement>> registry = new HashMap<>();\n\n    @Override\n    public void add(ResourceLocation id, Function<FriendlyByteBuf, ICraftingMonitorElement> factory) {\n        registry.put(id, factory);\n    }\n\n    @Nullable\n    @Override\n    public Function<FriendlyByteBuf, ICraftingMonitorElement> get(ResourceLocation id) {\n        return registry.get(id);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/craftingmonitor/ErrorCraftingMonitorElement.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement;\nimport com.refinedmods.refinedstorage.api.render.IElementDrawers;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.render.Styles;\nimport com.refinedmods.refinedstorage.util.PacketBufferUtils;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\n\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class ErrorCraftingMonitorElement implements ICraftingMonitorElement {\n    public static final ResourceLocation ID = new ResourceLocation(\"error\");\n\n    private final ICraftingMonitorElement base;\n    private final String message;\n\n    public ErrorCraftingMonitorElement(ICraftingMonitorElement base, String message) {\n        this.base = base;\n        this.message = message;\n    }\n\n    public static ErrorCraftingMonitorElement read(FriendlyByteBuf buf) {\n        ResourceLocation id = buf.readResourceLocation();\n        String message = PacketBufferUtils.readString(buf);\n\n        return new ErrorCraftingMonitorElement(\n            API.instance().getCraftingMonitorElementRegistry().get(id).apply(buf),\n            message\n        );\n    }\n\n    @Override\n    public void draw(GuiGraphics graphics, int x, int y, IElementDrawers drawers) {\n        base.draw(graphics, x, y, drawers);\n        drawers.getErrorDrawer().draw(graphics, x, y, null);\n    }\n\n    @Nullable\n    @Override\n    public List<Component> getTooltip() {\n        List<Component> items = new ArrayList<>(base.getTooltip());\n        items.add(Component.translatable(message).setStyle(Styles.RED));\n        return items;\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    @Override\n    public ResourceLocation getBaseId() {\n        return base.getId();\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeResourceLocation(base.getId());\n        buf.writeUtf(message);\n\n        base.write(buf);\n    }\n\n    @Override\n    public boolean merge(ICraftingMonitorElement element) {\n        return elementHashCode() == element.elementHashCode() && base.merge(((ErrorCraftingMonitorElement) element).base);\n    }\n\n    @Override\n    public int baseElementHashCode() {\n        return base.elementHashCode();\n    }\n\n    @Override\n    public int elementHashCode() {\n        return base.elementHashCode() ^ message.hashCode();\n    }\n\n    public void mergeBases(ICraftingMonitorElement element) {\n        this.base.merge(element);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/craftingmonitor/FluidCraftingMonitorElement.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor;\n\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement;\nimport com.refinedmods.refinedstorage.api.render.IElementDrawers;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.api.distmarker.Dist;\nimport net.neoforged.api.distmarker.OnlyIn;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nullable;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class FluidCraftingMonitorElement implements ICraftingMonitorElement {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"fluid\");\n    private static final int COLOR_PROCESSING = 0xFFD9EDF7;\n    private static final int COLOR_MISSING = 0xFFF2DEDE;\n    private static final int COLOR_SCHEDULED = 0xFFE8E5CA;\n    private static final int COLOR_CRAFTING = 0xFFADDBC6;\n    private final FluidStack stack;\n    private int stored;\n    private int missing;\n    private int processing;\n    private int scheduled;\n    private int crafting;\n\n    public FluidCraftingMonitorElement(FluidStack stack, int stored, int missing, int processing, int scheduled, int crafting) {\n        this.stack = stack;\n        this.stored = stored;\n        this.missing = missing;\n        this.processing = processing;\n        this.scheduled = scheduled;\n        this.crafting = crafting;\n    }\n\n    public static FluidCraftingMonitorElement read(FriendlyByteBuf buf) {\n        return new FluidCraftingMonitorElement(\n            FluidStack.readFromPacket(buf),\n            buf.readInt(),\n            buf.readInt(),\n            buf.readInt(),\n            buf.readInt(),\n            buf.readInt()\n        );\n    }\n\n    @Override\n    @OnlyIn(Dist.CLIENT)\n    public void draw(GuiGraphics graphics, int x, int y, IElementDrawers drawers) {\n        if (missing > 0) {\n            drawers.getOverlayDrawer().draw(graphics, x, y, COLOR_MISSING);\n        } else if (processing > 0) {\n            drawers.getOverlayDrawer().draw(graphics, x, y, COLOR_PROCESSING);\n        } else if (scheduled > 0) {\n            drawers.getOverlayDrawer().draw(graphics, x, y, COLOR_SCHEDULED);\n        } else if (crafting > 0) {\n            drawers.getOverlayDrawer().draw(graphics, x, y, COLOR_CRAFTING);\n        }\n\n        drawers.getFluidDrawer().draw(graphics, x + 4, y + 6, stack);\n\n        float scale = Minecraft.getInstance().isEnforceUnicode() ? 1F : 0.5F;\n\n        PoseStack poseStack = graphics.pose();\n\n        poseStack.pushPose();\n        poseStack.scale(scale, scale, 1);\n\n        int yy = y + 7;\n\n        if (stored > 0) {\n            drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 25, scale), RenderUtils.getOffsetOnScale(yy, scale), I18n.get(\"gui.refinedstorage.crafting_monitor.stored\", API.instance().getQuantityFormatter().formatInBucketForm(stored)));\n\n            yy += 7;\n        }\n\n        if (missing > 0) {\n            drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 25, scale), RenderUtils.getOffsetOnScale(yy, scale), I18n.get(\"gui.refinedstorage.crafting_monitor.missing\", API.instance().getQuantityFormatter().formatInBucketForm(missing)));\n\n            yy += 7;\n        }\n\n        if (processing > 0) {\n            drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 25, scale), RenderUtils.getOffsetOnScale(yy, scale), I18n.get(\"gui.refinedstorage.crafting_monitor.processing\", API.instance().getQuantityFormatter().formatInBucketForm(processing)));\n\n            yy += 7;\n        }\n\n        if (scheduled > 0) {\n            drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 25, scale), RenderUtils.getOffsetOnScale(yy, scale), I18n.get(\"gui.refinedstorage.crafting_monitor.scheduled\", API.instance().getQuantityFormatter().formatInBucketForm(scheduled)));\n\n            yy += 7;\n        }\n\n        if (crafting > 0) {\n            drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 25, scale), RenderUtils.getOffsetOnScale(yy, scale), I18n.get(\"gui.refinedstorage.crafting_monitor.crafting\", API.instance().getQuantityFormatter().formatInBucketForm(crafting)));\n        }\n\n        poseStack.popPose();\n    }\n\n    @Override\n    public ResourceLocation getBaseId() {\n        return ID;\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    @Nullable\n    @Override\n    public List<Component> getTooltip() {\n        return Collections.singletonList(stack.getDisplayName());\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        stack.writeToPacket(buf);\n        buf.writeInt(stored);\n        buf.writeInt(missing);\n        buf.writeInt(processing);\n        buf.writeInt(scheduled);\n        buf.writeInt(crafting);\n    }\n\n    @Override\n    public boolean merge(ICraftingMonitorElement element) {\n        if (element.getId().equals(getId()) && elementHashCode() == element.elementHashCode()) {\n            this.stored += ((FluidCraftingMonitorElement) element).stored;\n            this.missing += ((FluidCraftingMonitorElement) element).missing;\n            this.processing += ((FluidCraftingMonitorElement) element).processing;\n            this.scheduled += ((FluidCraftingMonitorElement) element).scheduled;\n            this.crafting += ((FluidCraftingMonitorElement) element).crafting;\n\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public int baseElementHashCode() {\n        return elementHashCode();\n    }\n\n    @Override\n    public int elementHashCode() {\n        return API.instance().getFluidStackHashCode(stack);\n    }\n\n    public static class Builder {\n        private final FluidStack stack;\n        private int stored;\n        private int missing;\n        private int processing;\n        private int scheduled;\n        private int crafting;\n\n        public Builder(FluidStack stack) {\n            this.stack = stack;\n        }\n\n        public static FluidCraftingMonitorElement.Builder forStack(FluidStack stack) {\n            return new FluidCraftingMonitorElement.Builder(stack);\n        }\n\n        public FluidCraftingMonitorElement.Builder stored(int stored) {\n            this.stored = stored;\n            return this;\n        }\n\n        public FluidCraftingMonitorElement.Builder missing(int missing) {\n            this.missing = missing;\n            return this;\n        }\n\n        public FluidCraftingMonitorElement.Builder processing(int processing) {\n            this.processing = processing;\n            return this;\n        }\n\n        public FluidCraftingMonitorElement.Builder scheduled(int scheduled) {\n            this.scheduled = scheduled;\n            return this;\n        }\n\n        public FluidCraftingMonitorElement.Builder crafting(int crafting) {\n            this.crafting = crafting;\n            return this;\n        }\n\n        public FluidCraftingMonitorElement build() {\n            return new FluidCraftingMonitorElement(stack, stored, missing, processing, scheduled, crafting);\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/craftingmonitor/ItemCraftingMonitorElement.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor;\n\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement;\nimport com.refinedmods.refinedstorage.api.render.IElementDrawers;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.api.distmarker.Dist;\nimport net.neoforged.api.distmarker.OnlyIn;\nimport javax.annotation.Nullable;\nimport java.util.List;\n\npublic class ItemCraftingMonitorElement implements ICraftingMonitorElement {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"item\");\n    private static final int COLOR_PROCESSING = 0xFFD9EDF7;\n    private static final int COLOR_MISSING = 0xFFF2DEDE;\n    private static final int COLOR_SCHEDULED = 0xFFE8E5CA;\n    private static final int COLOR_CRAFTING = 0xFFADDBC6;\n    private final ItemStack stack;\n    private int stored;\n    private int missing;\n    private int processing;\n    private int scheduled;\n    private int crafting;\n\n    public ItemCraftingMonitorElement(ItemStack stack, int stored, int missing, int processing, int scheduled, int crafting) {\n        this.stack = stack;\n        this.stored = stored;\n        this.missing = missing;\n        this.processing = processing;\n        this.scheduled = scheduled;\n        this.crafting = crafting;\n    }\n\n    public static ItemCraftingMonitorElement read(FriendlyByteBuf buf) {\n        return new ItemCraftingMonitorElement(\n            StackUtils.readItemStack(buf),\n            buf.readInt(),\n            buf.readInt(),\n            buf.readInt(),\n            buf.readInt(),\n            buf.readInt()\n        );\n    }\n\n    @Override\n    @OnlyIn(Dist.CLIENT)\n    public void draw(GuiGraphics graphics, int x, int y, IElementDrawers drawers) {\n        if (missing > 0) {\n            drawers.getOverlayDrawer().draw(graphics, x, y, COLOR_MISSING);\n        } else if (processing > 0) {\n            drawers.getOverlayDrawer().draw(graphics, x, y, COLOR_PROCESSING);\n        } else if (scheduled > 0) {\n            drawers.getOverlayDrawer().draw(graphics, x, y, COLOR_SCHEDULED);\n        } else if (crafting > 0) {\n            drawers.getOverlayDrawer().draw(graphics, x, y, COLOR_CRAFTING);\n        }\n\n        drawers.getItemDrawer().draw(graphics, x + 4, y + 6, stack);\n\n        float scale = Minecraft.getInstance().isEnforceUnicode() ? 1F : 0.5F;\n\n        PoseStack poseStack = graphics.pose();\n\n        poseStack.pushPose();\n        poseStack.scale(scale, scale, 1);\n\n        int yy = y + 7;\n\n        if (stored > 0) {\n            drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 25, scale), RenderUtils.getOffsetOnScale(yy, scale), I18n.get(\"gui.refinedstorage.crafting_monitor.stored\", stored));\n\n            yy += 7;\n        }\n\n        if (missing > 0) {\n            drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 25, scale), RenderUtils.getOffsetOnScale(yy, scale), I18n.get(\"gui.refinedstorage.crafting_monitor.missing\", missing));\n\n            yy += 7;\n        }\n\n        if (processing > 0) {\n            drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 25, scale), RenderUtils.getOffsetOnScale(yy, scale), I18n.get(\"gui.refinedstorage.crafting_monitor.processing\", processing));\n\n            yy += 7;\n        }\n\n        if (scheduled > 0) {\n            drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 25, scale), RenderUtils.getOffsetOnScale(yy, scale), I18n.get(\"gui.refinedstorage.crafting_monitor.scheduled\", scheduled));\n\n            yy += 7;\n        }\n\n        if (crafting > 0) {\n            drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 25, scale), RenderUtils.getOffsetOnScale(yy, scale), I18n.get(\"gui.refinedstorage.crafting_monitor.crafting\", crafting));\n        }\n\n        poseStack.popPose();\n    }\n\n    @Override\n    public ResourceLocation getBaseId() {\n        return ID;\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    @Nullable\n    @Override\n    public List<Component> getTooltip() {\n        return RenderUtils.getTooltipFromItem(this.stack);\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        StackUtils.writeItemStack(buf, stack);\n        buf.writeInt(stored);\n        buf.writeInt(missing);\n        buf.writeInt(processing);\n        buf.writeInt(scheduled);\n        buf.writeInt(crafting);\n    }\n\n    @Override\n    public boolean merge(ICraftingMonitorElement element) {\n        if (element.getId().equals(getId()) && elementHashCode() == element.elementHashCode()) {\n            this.stored += ((ItemCraftingMonitorElement) element).stored;\n            this.missing += ((ItemCraftingMonitorElement) element).missing;\n            this.processing += ((ItemCraftingMonitorElement) element).processing;\n            this.scheduled += ((ItemCraftingMonitorElement) element).scheduled;\n            this.crafting += ((ItemCraftingMonitorElement) element).crafting;\n\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public int baseElementHashCode() {\n        return elementHashCode();\n    }\n\n    @Override\n    public int elementHashCode() {\n        return API.instance().getItemStackHashCode(stack);\n    }\n\n    public static class Builder {\n        private final ItemStack stack;\n        private int stored;\n        private int missing;\n        private int processing;\n        private int scheduled;\n        private int crafting;\n\n        public Builder(ItemStack stack) {\n            this.stack = stack;\n        }\n\n        public static Builder forStack(ItemStack stack) {\n            return new Builder(stack);\n        }\n\n        public Builder stored(int stored) {\n            this.stored = stored;\n            return this;\n        }\n\n        public Builder missing(int missing) {\n            this.missing = missing;\n            return this;\n        }\n\n        public Builder processing(int processing) {\n            this.processing = processing;\n            return this;\n        }\n\n        public Builder scheduled(int scheduled) {\n            this.scheduled = scheduled;\n            return this;\n        }\n\n        public Builder crafting(int crafting) {\n            this.crafting = crafting;\n            return this;\n        }\n\n        public ItemCraftingMonitorElement build() {\n            return new ItemCraftingMonitorElement(stack, stored, missing, processing, scheduled, crafting);\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/preview/CraftingPreviewElementRegistry.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.preview;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;\nimport com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElementRegistry;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.resources.ResourceLocation;\n\nimport javax.annotation.Nullable;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.function.Function;\n\npublic class CraftingPreviewElementRegistry implements ICraftingPreviewElementRegistry {\n    private final Map<ResourceLocation, Function<FriendlyByteBuf, ICraftingPreviewElement>> registry = new HashMap<>();\n\n    @Override\n    public void add(ResourceLocation id, Function<FriendlyByteBuf, ICraftingPreviewElement> factory) {\n        registry.put(id, factory);\n    }\n\n    @Nullable\n    @Override\n    public Function<FriendlyByteBuf, ICraftingPreviewElement> get(ResourceLocation id) {\n        return registry.get(id);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/preview/ErrorCraftingPreviewElement.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.preview;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.CalculationResultType;\nimport com.refinedmods.refinedstorage.api.render.IElementDrawers;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\n\npublic class ErrorCraftingPreviewElement implements ICraftingPreviewElement {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"error\");\n\n    private final CalculationResultType type;\n    private final ItemStack recursedPattern;\n\n    public ErrorCraftingPreviewElement(CalculationResultType type, ItemStack recursedPattern) {\n        this.type = type;\n        this.recursedPattern = recursedPattern;\n    }\n\n    public static ErrorCraftingPreviewElement read(FriendlyByteBuf buf) {\n        int errorIdx = buf.readInt();\n        CalculationResultType error = errorIdx >= 0 && errorIdx < CalculationResultType.values().length ? CalculationResultType.values()[errorIdx] : CalculationResultType.TOO_COMPLEX;\n        ItemStack stack = buf.readItem();\n\n        return new ErrorCraftingPreviewElement(error, stack);\n    }\n\n    public ItemStack getRecursedPattern() {\n        return recursedPattern;\n    }\n\n    @Override\n    public void draw(GuiGraphics graphics, int x, int y, IElementDrawers drawers) {\n        // NO OP\n    }\n\n    @Override\n    public boolean doesDisableTaskStarting() {\n        return true;\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeInt(type.ordinal());\n        buf.writeItem(recursedPattern);\n    }\n\n    public CalculationResultType getType() {\n        return type;\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/preview/FluidCraftingPreviewElement.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.preview;\n\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;\nimport com.refinedmods.refinedstorage.api.render.IElementDrawers;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.api.distmarker.Dist;\nimport net.neoforged.api.distmarker.OnlyIn;\nimport net.neoforged.neoforge.fluids.FluidStack;\n\npublic class FluidCraftingPreviewElement implements ICraftingPreviewElement {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"fluid\");\n\n    private final FluidStack stack;\n    private int available;\n    private boolean missing;\n    // If missing is true then toCraft is the missing amount\n    private int toCraft;\n\n    public FluidCraftingPreviewElement(FluidStack stack) {\n        this.stack = stack.copy();\n    }\n\n    public FluidCraftingPreviewElement(FluidStack stack, int available, boolean missing, int toCraft) {\n        this.stack = stack.copy();\n        this.available = available;\n        this.missing = missing;\n        this.toCraft = toCraft;\n    }\n\n    public static FluidCraftingPreviewElement read(FriendlyByteBuf buf) {\n        FluidStack stack = FluidStack.readFromPacket(buf);\n        int available = buf.readInt();\n        boolean missing = buf.readBoolean();\n        int toCraft = buf.readInt();\n\n        return new FluidCraftingPreviewElement(stack, available, missing, toCraft);\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        stack.writeToPacket(buf);\n        buf.writeInt(available);\n        buf.writeBoolean(missing);\n        buf.writeInt(toCraft);\n    }\n\n    public FluidStack getStack() {\n        return stack;\n    }\n\n    @Override\n    @OnlyIn(Dist.CLIENT)\n    public void draw(GuiGraphics graphics, int x, int y, IElementDrawers drawers) {\n        if (missing) {\n            drawers.getOverlayDrawer().draw(graphics, x, y, 0xFFF2DEDE);\n        }\n\n        x += 5;\n        y += 7;\n\n        drawers.getFluidDrawer().draw(graphics, x, y, getStack());\n\n        float scale = Minecraft.getInstance().isEnforceUnicode() ? 1F : 0.5F;\n\n        y += 2;\n\n        PoseStack poseStack = graphics.pose();\n\n        poseStack.pushPose();\n        poseStack.scale(scale, scale, 1);\n\n        if (toCraft > 0) {\n            String format = doesDisableTaskStarting() ? \"gui.refinedstorage.crafting_preview.missing\" : \"gui.refinedstorage.crafting_preview.to_craft\";\n            drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 23, scale), RenderUtils.getOffsetOnScale(y, scale), I18n.get(format, API.instance().getQuantityFormatter().formatInBucketForm(toCraft)));\n\n            y += 7;\n        }\n\n        if (available > 0) {\n            drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 23, scale), RenderUtils.getOffsetOnScale(y, scale), I18n.get(\"gui.refinedstorage.crafting_preview.available\", API.instance().getQuantityFormatter().formatInBucketForm(available)));\n        }\n\n        poseStack.popPose();\n    }\n\n    public void addAvailable(int amount) {\n        this.available += amount;\n    }\n\n    public void addToCraft(int amount) {\n        this.toCraft += amount;\n    }\n\n    public void setMissing(boolean missing) {\n        this.missing = missing;\n    }\n\n    @Override\n    public boolean doesDisableTaskStarting() {\n        return missing;\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/preview/ItemCraftingPreviewElement.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.preview;\n\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;\nimport com.refinedmods.refinedstorage.api.render.IElementDrawers;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.api.distmarker.Dist;\nimport net.neoforged.api.distmarker.OnlyIn;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\n\npublic class ItemCraftingPreviewElement implements ICraftingPreviewElement {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"item\");\n\n    private final ItemStack stack;\n    private int available;\n    private boolean missing;\n    // If missing is true then toCraft is the missing amount\n    private int toCraft;\n\n    public ItemCraftingPreviewElement(ItemStack stack) {\n        this.stack = ItemHandlerHelper.copyStackWithSize(stack, 1);\n    }\n\n    public ItemCraftingPreviewElement(ItemStack stack, int available, boolean missing, int toCraft) {\n        this.stack = stack;\n        this.available = available;\n        this.missing = missing;\n        this.toCraft = toCraft;\n    }\n\n    public static ItemCraftingPreviewElement read(FriendlyByteBuf buf) {\n        ItemStack stack = buf.readItem();\n        int available = buf.readInt();\n        boolean missing = buf.readBoolean();\n        int toCraft = buf.readInt();\n\n        return new ItemCraftingPreviewElement(stack, available, missing, toCraft);\n    }\n\n    public ItemStack getStack() {\n        return stack;\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeItem(stack);\n        buf.writeInt(available);\n        buf.writeBoolean(missing);\n        buf.writeInt(toCraft);\n    }\n\n    @Override\n    @OnlyIn(Dist.CLIENT)\n    public void draw(GuiGraphics graphics, int x, int y, IElementDrawers drawers) {\n        if (missing) {\n            drawers.getOverlayDrawer().draw(graphics, x, y, 0xFFF2DEDE);\n        }\n\n        x += 5;\n        y += 7;\n\n        drawers.getItemDrawer().draw(graphics, x, y, stack);\n\n        float scale = Minecraft.getInstance().isEnforceUnicode() ? 1F : 0.5F;\n\n        y += 2;\n\n        PoseStack poseStack = graphics.pose();\n\n        poseStack.pushPose();\n        poseStack.scale(scale, scale, 1);\n\n        if (toCraft > 0) {\n            String format = doesDisableTaskStarting() ? \"gui.refinedstorage.crafting_preview.missing\" : \"gui.refinedstorage.crafting_preview.to_craft\";\n            drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 23, scale), RenderUtils.getOffsetOnScale(y, scale), I18n.get(format, toCraft));\n\n            y += 7;\n        }\n\n        if (available > 0) {\n            drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 23, scale), RenderUtils.getOffsetOnScale(y, scale), I18n.get(\"gui.refinedstorage.crafting_preview.available\", available));\n        }\n\n        poseStack.popPose();\n    }\n\n    public void addAvailable(int amount) {\n        this.available += amount;\n    }\n\n    public void addToCraft(int amount) {\n        this.toCraft += amount;\n    }\n\n    public void setMissing(boolean missing) {\n        this.missing = missing;\n    }\n\n    @Override\n    public boolean doesDisableTaskStarting() {\n        return missing;\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/CraftingRequestInfo.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.task;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingRequestInfo;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nullable;\n\npublic class CraftingRequestInfo implements ICraftingRequestInfo {\n    private static final String NBT_FLUID = \"Fluid\";\n    private static final String NBT_STACK = \"Stack\";\n\n    private ItemStack item;\n    private FluidStack fluid;\n\n    public CraftingRequestInfo(CompoundTag tag) throws CraftingTaskReadException {\n        if (!tag.getBoolean(NBT_FLUID)) {\n            item = StackUtils.deserializeStackFromNbt(tag.getCompound(NBT_STACK));\n\n            if (item.isEmpty()) {\n                throw new CraftingTaskReadException(\"Extractor stack is empty\");\n            }\n        } else {\n            fluid = FluidStack.loadFluidStackFromNBT(tag.getCompound(NBT_STACK));\n\n            if (fluid.isEmpty()) {\n                throw new CraftingTaskReadException(\"Extractor fluid stack is empty\");\n            }\n        }\n    }\n\n    public CraftingRequestInfo(ItemStack item) {\n        this.item = item;\n    }\n\n    public CraftingRequestInfo(FluidStack fluid) {\n        this.fluid = fluid;\n    }\n\n    @Nullable\n    @Override\n    public ItemStack getItem() {\n        return item;\n    }\n\n    @Nullable\n    @Override\n    public FluidStack getFluid() {\n        return fluid;\n    }\n\n    @Override\n    public CompoundTag writeToNbt() {\n        CompoundTag tag = new CompoundTag();\n\n        tag.putBoolean(NBT_FLUID, fluid != null);\n\n        if (fluid != null) {\n            tag.put(NBT_STACK, fluid.writeToNBT(new CompoundTag()));\n        } else {\n            tag.put(NBT_STACK, StackUtils.serializeStackToNbt(item));\n        }\n\n        return tag;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/CraftingTaskRegistry.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.task;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTaskFactory;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTaskRegistry;\nimport net.minecraft.resources.ResourceLocation;\n\nimport javax.annotation.Nullable;\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class CraftingTaskRegistry implements ICraftingTaskRegistry {\n    private final Map<ResourceLocation, ICraftingTaskFactory> registry = new HashMap<>();\n\n    @Override\n    public void add(ResourceLocation id, ICraftingTaskFactory factory) {\n        registry.put(id, factory);\n    }\n\n    @Override\n    @Nullable\n    public ICraftingTaskFactory get(ResourceLocation id) {\n        return registry.get(id);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/README.md",
    "content": "# Autocrafting\n\nAutocrafting has had several refactors.\n\nSome history:\n\n|RS version|Autocrafting version|\n|----------|--------------------|\n|v0.6|v1|\n|v1.0|v2|\n|v1.2|v3|\n|v1.6|v4|\n|v1.6.4|v5|\n|v1.8.3|v6|"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/CraftingPatternInputs.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport net.minecraft.core.NonNullList;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class CraftingPatternInputs {\n    private final NonNullList<ItemStack> recipe = NonNullList.create();\n    private final List<Ingredient<ItemStack>> itemIngredients = new ArrayList<>();\n    private final List<Ingredient<FluidStack>> fluidIngredients = new ArrayList<>();\n\n    public CraftingPatternInputs(ICraftingPattern pattern) {\n        fillOutRecipe(pattern);\n        combineItemInputs(pattern);\n        combineFluidInputs(pattern);\n    }\n\n    private void fillOutRecipe(ICraftingPattern pattern) {\n        for (NonNullList<ItemStack> inputsForSlot : pattern.getInputs()) {\n            if (inputsForSlot.isEmpty()) {\n                recipe.add(ItemStack.EMPTY);\n            } else {\n                recipe.add(inputsForSlot.get(0));\n            }\n        }\n    }\n\n    private void combineItemInputs(ICraftingPattern pattern) {\n        for (NonNullList<ItemStack> inputsForSlot : pattern.getInputs()) {\n            if (inputsForSlot.isEmpty()) {\n                continue;\n            }\n\n            Ingredient<ItemStack> matchingIngredient = findMatchingItemIngredient(inputsForSlot);\n\n            if (matchingIngredient == null) {\n                itemIngredients.add(new Ingredient<>(inputsForSlot, inputsForSlot.get(0).getCount()));\n            } else {\n                matchingIngredient.increaseCount(inputsForSlot.get(0).getCount());\n            }\n        }\n    }\n\n    private void combineFluidInputs(ICraftingPattern pattern) {\n        for (NonNullList<FluidStack> inputsForSlot : pattern.getFluidInputs()) {\n            if (inputsForSlot.isEmpty()) {\n                continue;\n            }\n\n            Ingredient<FluidStack> matchingIngredient = findMatchingFluidIngredient(inputsForSlot);\n\n            if (matchingIngredient == null) {\n                fluidIngredients.add(new Ingredient<>(inputsForSlot, inputsForSlot.get(0).getAmount()));\n            } else {\n                matchingIngredient.increaseCount(inputsForSlot.get(0).getAmount());\n            }\n        }\n    }\n\n    @Nullable\n    private Ingredient<ItemStack> findMatchingItemIngredient(NonNullList<ItemStack> inputsForSlot) {\n        for (Ingredient<ItemStack> existingIngredient : itemIngredients) {\n            if (existingIngredient.getInputs().size() == inputsForSlot.size()) {\n                boolean found = true;\n\n                for (int i = 0; i < inputsForSlot.size(); i++) {\n                    if (!API.instance().getComparer().isEqualNoQuantity(existingIngredient.getInputs().get(i), inputsForSlot.get(i))) {\n                        found = false;\n                        break;\n                    }\n                }\n\n                if (found) {\n                    return existingIngredient;\n                }\n            }\n        }\n\n        return null;\n    }\n\n    @Nullable\n    private Ingredient<FluidStack> findMatchingFluidIngredient(NonNullList<FluidStack> inputsForSlot) {\n        for (Ingredient<FluidStack> existingIngredient : fluidIngredients) {\n            if (existingIngredient.getInputs().size() == inputsForSlot.size()) {\n                boolean found = true;\n\n                for (int i = 0; i < inputsForSlot.size(); i++) {\n                    if (!API.instance().getComparer().isEqual(existingIngredient.getInputs().get(i), inputsForSlot.get(i), IComparer.COMPARE_NBT)) {\n                        found = false;\n                        break;\n                    }\n                }\n\n                if (found) {\n                    return existingIngredient;\n                }\n            }\n        }\n\n        return null;\n    }\n\n    public NonNullList<ItemStack> getRecipe() {\n        return recipe;\n    }\n\n    public List<Ingredient<ItemStack>> getItemIngredients() {\n        return itemIngredients;\n    }\n\n    public List<Ingredient<FluidStack>> getFluidIngredients() {\n        return fluidIngredients;\n    }\n\n    public static class Ingredient<T> {\n        private final NonNullList<T> inputs;\n        private int count;\n\n        public Ingredient(NonNullList<T> inputs, int count) {\n            this.inputs = inputs;\n            this.count = count;\n        }\n\n        public NonNullList<T> getInputs() {\n            return inputs;\n        }\n\n        public int getCount() {\n            return count;\n        }\n\n        public void increaseCount(int count) {\n            this.count += count;\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/CraftingTask.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingRequestInfo;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.monitor.CraftingMonitorElementFactory;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.Node;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.NodeList;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.NodeListener;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.ProcessingNode;\nimport com.refinedmods.refinedstorage.apiimpl.storage.disk.FluidStorageDisk;\nimport com.refinedmods.refinedstorage.apiimpl.storage.disk.ItemStorageDisk;\nimport com.refinedmods.refinedstorage.apiimpl.storage.disk.factory.FluidStorageDiskFactory;\nimport com.refinedmods.refinedstorage.apiimpl.storage.disk.factory.ItemStorageDiskFactory;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.nbt.Tag;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.UUID;\n\npublic class CraftingTask implements ICraftingTask, NodeListener {\n    private static final String NBT_REQUESTED = \"Requested\";\n    private static final String NBT_QUANTITY = \"Quantity\";\n    private static final String NBT_PATTERN = \"Pattern\";\n    private static final String NBT_TICKS = \"Ticks\";\n    private static final String NBT_ID = \"Id\";\n    private static final String NBT_EXECUTION_STARTED = \"ExecutionStarted\";\n    private static final String NBT_INTERNAL_STORAGE = \"InternalStorage\";\n    private static final String NBT_INTERNAL_FLUID_STORAGE = \"InternalFluidStorage\";\n    private static final String NBT_TO_EXTRACT_INITIAL = \"ToExtractInitial\";\n    private static final String NBT_TO_EXTRACT_INITIAL_FLUIDS = \"ToExtractInitialFluids\";\n    private static final String NBT_CRAFTS = \"Crafts\";\n    private static final String NBT_TOTAL_STEPS = \"TotalSteps\";\n    private static final String NBT_CURRENT_STEP = \"CurrentStep\";\n\n    private final IStorageDisk<ItemStack> internalStorage;\n    private final IStorageDisk<FluidStack> internalFluidStorage;\n\n    private final INetwork network;\n    private final ICraftingRequestInfo requested;\n    private final int quantity;\n    private final ICraftingPattern pattern;\n    private final UUID id;\n    private final NodeList nodes;\n    private final IStackList<ItemStack> toExtractInitial;\n    private final IStackList<FluidStack> toExtractInitialFluids;\n    private final CraftingMonitorElementFactory craftingMonitorElementFactory = new CraftingMonitorElementFactory();\n    private int ticks;\n    private long startTime = -1;\n    private int totalSteps;\n    private int currentStep;\n\n    public CraftingTask(INetwork network,\n                        ICraftingRequestInfo requested,\n                        int quantity,\n                        ICraftingPattern pattern,\n                        NodeList nodes,\n                        IStackList<ItemStack> toExtractInitial,\n                        IStackList<FluidStack> toExtractInitialFluids) {\n        this.network = network;\n\n        this.requested = requested;\n        this.quantity = quantity;\n        this.pattern = pattern;\n        this.id = UUID.randomUUID();\n        this.nodes = nodes;\n\n        this.internalStorage = new ItemStorageDisk(null, -1, null);\n        this.internalFluidStorage = new FluidStorageDisk(null, -1, null);\n\n        this.toExtractInitial = toExtractInitial;\n        this.toExtractInitialFluids = toExtractInitialFluids;\n    }\n\n    public CraftingTask(INetwork network, CompoundTag tag) throws CraftingTaskReadException {\n        this.network = network;\n\n        this.requested = API.instance().createCraftingRequestInfo(tag.getCompound(NBT_REQUESTED));\n        this.quantity = tag.getInt(NBT_QUANTITY);\n        this.pattern = SerializationUtil.readPatternFromNbt(tag.getCompound(NBT_PATTERN), network.getLevel());\n        this.id = tag.getUUID(NBT_ID);\n        this.nodes = new NodeList();\n\n        this.ticks = tag.getInt(NBT_TICKS);\n        this.startTime = tag.getLong(NBT_EXECUTION_STARTED);\n        this.totalSteps = tag.getInt(NBT_TOTAL_STEPS);\n        this.currentStep = tag.getInt(NBT_CURRENT_STEP);\n\n        this.internalStorage = new ItemStorageDiskFactory().createFromNbt(null, tag.getCompound(NBT_INTERNAL_STORAGE));\n        this.internalFluidStorage = new FluidStorageDiskFactory().createFromNbt(null, tag.getCompound(NBT_INTERNAL_FLUID_STORAGE));\n\n        this.toExtractInitial = SerializationUtil.readItemStackList(tag.getList(NBT_TO_EXTRACT_INITIAL, Tag.TAG_COMPOUND));\n        this.toExtractInitialFluids = SerializationUtil.readFluidStackList(tag.getList(NBT_TO_EXTRACT_INITIAL_FLUIDS, Tag.TAG_COMPOUND));\n\n        ListTag nodeList = tag.getList(NBT_CRAFTS, Tag.TAG_COMPOUND);\n        for (int i = 0; i < nodeList.size(); ++i) {\n            Node node = Node.fromNbt(network, nodeList.getCompound(i));\n            nodes.put(node.getPattern(), node);\n        }\n    }\n\n    @Override\n    public CompoundTag writeToNbt(CompoundTag tag) {\n        tag.put(NBT_REQUESTED, requested.writeToNbt());\n        tag.putInt(NBT_QUANTITY, quantity);\n        tag.put(NBT_PATTERN, SerializationUtil.writePatternToNbt(pattern));\n        tag.putInt(NBT_TICKS, ticks);\n        tag.putUUID(NBT_ID, id);\n        tag.putLong(NBT_EXECUTION_STARTED, startTime);\n        tag.put(NBT_INTERNAL_STORAGE, internalStorage.writeToNbt());\n        tag.put(NBT_INTERNAL_FLUID_STORAGE, internalFluidStorage.writeToNbt());\n        tag.put(NBT_TO_EXTRACT_INITIAL, SerializationUtil.writeItemStackList(toExtractInitial));\n        tag.put(NBT_TO_EXTRACT_INITIAL_FLUIDS, SerializationUtil.writeFluidStackList(toExtractInitialFluids));\n        tag.putInt(NBT_TOTAL_STEPS, totalSteps);\n        tag.putInt(NBT_CURRENT_STEP, currentStep);\n\n        ListTag nodeList = new ListTag();\n        for (Node node : this.nodes.all()) {\n            nodeList.add(node.writeToNbt());\n        }\n        tag.put(NBT_CRAFTS, nodeList);\n\n        return tag;\n    }\n\n    @Override\n    public void start() {\n        nodes.all().forEach(node -> {\n            totalSteps += node.getQuantity();\n\n            node.onCalculationFinished();\n        });\n\n        startTime = System.currentTimeMillis();\n\n        IoUtil.extractItemsFromNetwork(toExtractInitial, network, internalStorage);\n        IoUtil.extractFluidsFromNetwork(toExtractInitialFluids, network, internalFluidStorage);\n    }\n\n    @Override\n    public int getCompletionPercentage() {\n        if (totalSteps == 0) {\n            return 0;\n        }\n\n        return (int) ((float) currentStep * 100 / totalSteps);\n    }\n\n    @Override\n    public boolean update() {\n        ++ticks;\n\n        if (nodes.isEmpty()) {\n            List<Runnable> toPerform = new ArrayList<>();\n\n            for (ItemStack stack : internalStorage.getStacks()) {\n                ItemStack remainder = network.insertItem(stack, stack.getCount(), Action.PERFORM);\n\n                toPerform.add(() -> internalStorage.extract(stack, stack.getCount() - remainder.getCount(), IComparer.COMPARE_NBT, Action.PERFORM));\n            }\n\n            for (FluidStack stack : internalFluidStorage.getStacks()) {\n                FluidStack remainder = network.insertFluid(stack, stack.getAmount(), Action.PERFORM);\n\n                toPerform.add(() -> internalFluidStorage.extract(stack, stack.getAmount() - remainder.getAmount(), IComparer.COMPARE_NBT, Action.PERFORM));\n            }\n\n            // Prevent CME.\n            toPerform.forEach(Runnable::run);\n\n            return internalStorage.getStacks().isEmpty() && internalFluidStorage.getStacks().isEmpty();\n        } else {\n            IoUtil.extractItemsFromNetwork(toExtractInitial, network, internalStorage);\n            IoUtil.extractFluidsFromNetwork(toExtractInitialFluids, network, internalFluidStorage);\n\n            for (Node node : nodes.all()) {\n                node.update(network, ticks, nodes, internalStorage, internalFluidStorage, this);\n            }\n\n            nodes.removeMarkedForRemoval();\n\n            return false;\n        }\n    }\n\n    @Override\n    public void onCancelled() {\n        nodes.unlockAll(network);\n\n        for (ItemStack remainder : internalStorage.getStacks()) {\n            network.insertItem(remainder, remainder.getCount(), Action.PERFORM);\n        }\n\n        for (FluidStack remainder : internalFluidStorage.getStacks()) {\n            network.insertFluid(remainder, remainder.getAmount(), Action.PERFORM);\n        }\n    }\n\n    @Override\n    public int getQuantity() {\n        return quantity;\n    }\n\n    @Override\n    public ICraftingRequestInfo getRequested() {\n        return requested;\n    }\n\n    @Override\n    public int onTrackedInsert(ItemStack stack, int size) {\n        for (Node node : this.nodes.all()) {\n            if (node instanceof ProcessingNode) {\n                ProcessingNode processing = (ProcessingNode) node;\n\n                int needed = processing.getNeeded(stack);\n                if (needed > 0) {\n                    if (needed > size) {\n                        needed = size;\n                    }\n\n                    processing.markReceived(stack, needed);\n\n                    size -= needed;\n\n                    if (!processing.isRoot()) {\n                        internalStorage.insert(stack, needed, Action.PERFORM);\n                    } else {\n                        ItemStack remainder = network.insertItem(stack, needed, Action.PERFORM);\n\n                        internalStorage.insert(remainder, remainder.getCount(), Action.PERFORM);\n                    }\n\n                    network.getCraftingManager().onTaskChanged();\n\n                    if (size == 0) {\n                        return 0;\n                    }\n                }\n            }\n        }\n\n        return size;\n    }\n\n    @Override\n    public int onTrackedInsert(FluidStack stack, int size) {\n        for (Node node : this.nodes.all()) {\n            if (node instanceof ProcessingNode) {\n                ProcessingNode processing = (ProcessingNode) node;\n\n                int needed = processing.getNeeded(stack);\n\n                if (needed > 0) {\n                    if (needed > size) {\n                        needed = size;\n                    }\n\n                    processing.markReceived(stack, needed);\n\n                    size -= needed;\n\n                    if (!processing.isRoot()) {\n                        internalFluidStorage.insert(stack, needed, Action.PERFORM);\n                    } else {\n                        FluidStack remainder = network.insertFluid(stack, needed, Action.PERFORM);\n\n                        internalFluidStorage.insert(remainder, remainder.getAmount(), Action.PERFORM);\n                    }\n\n                    network.getCraftingManager().onTaskChanged();\n\n                    if (size == 0) {\n                        return 0;\n                    }\n                }\n            }\n        }\n\n        return size;\n    }\n\n    @Override\n    public List<ICraftingMonitorElement> getCraftingMonitorElements() {\n        return craftingMonitorElementFactory.getElements(nodes.all(), internalStorage, internalFluidStorage);\n    }\n\n    @Override\n    public ICraftingPattern getPattern() {\n        return pattern;\n    }\n\n    @Override\n    public long getStartTime() {\n        return startTime;\n    }\n\n    @Override\n    public UUID getId() {\n        return id;\n    }\n\n    @Override\n    public void onAllDone(Node node) {\n        nodes.remove(node);\n    }\n\n    @Override\n    public void onSingleDone(Node node) {\n        currentStep++;\n        network.getCraftingManager().onTaskChanged();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/CraftingTaskFactory.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.*;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.calculator.CraftingCalculator;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\n\npublic class CraftingTaskFactory implements ICraftingTaskFactory {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"v6\");\n\n    @Override\n    public ICalculationResult create(INetwork network, ICraftingRequestInfo requested, int quantity, ICraftingPattern pattern) {\n        CraftingCalculator calculator = new CraftingCalculator(network, requested, quantity, pattern);\n        return calculator.calculate();\n    }\n\n    @Override\n    public ICraftingTask createFromNbt(INetwork network, CompoundTag tag) throws CraftingTaskReadException {\n        return new CraftingTask(network, tag);\n    }\n}"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/IoUtil.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6;\n\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.api.util.StackListEntry;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic final class IoUtil {\n    private static final int DEFAULT_EXTRACT_FLAGS = IComparer.COMPARE_NBT;\n\n    private IoUtil() {\n    }\n\n    public static List<ItemStack> extractFromInternalItemStorage(List<ItemStack> list, IStorageDisk<ItemStack> storage, Action action) {\n        List<ItemStack> extracted = new ArrayList<>();\n\n        for (ItemStack stack : list) {\n            ItemStack result = storage.extract(stack, stack.getCount(), DEFAULT_EXTRACT_FLAGS, action);\n\n            if (result.isEmpty() || result.getCount() != stack.getCount()) {\n                if (action == Action.PERFORM) {\n                    throw new IllegalStateException(\"The internal crafting inventory reported that \" + stack + \" was available but we got \" + result);\n                }\n\n                return null;\n            }\n\n            extracted.add(result);\n        }\n\n        return extracted;\n    }\n\n    public static List<FluidStack> extractFromInternalFluidStorage(List<FluidStack> list, IStorageDisk<FluidStack> storage, Action action) {\n        List<FluidStack> extracted = new ArrayList<>();\n\n        for (FluidStack stack : list) {\n            FluidStack result = storage.extract(stack, stack.getAmount(), DEFAULT_EXTRACT_FLAGS, action);\n\n            if (result.isEmpty() || result.getAmount() != stack.getAmount()) {\n                if (action == Action.PERFORM) {\n                    throw new IllegalStateException(\"The internal crafting inventory reported that \" + stack + \" was available but we got \" + result);\n                }\n\n                return null;\n            }\n\n            extracted.add(result);\n        }\n\n        return extracted;\n    }\n\n    public static void extractItemsFromNetwork(IStackList<ItemStack> toExtractInitial, INetwork network, IStorageDisk<ItemStack> internalStorage) {\n        if (toExtractInitial.isEmpty()) {\n            return;\n        }\n\n        List<ItemStack> toRemove = new ArrayList<>();\n\n        for (StackListEntry<ItemStack> toExtract : toExtractInitial.getStacks()) {\n            ItemStack result = network.extractItem(toExtract.getStack(), toExtract.getStack().getCount(), Action.PERFORM);\n\n            if (!result.isEmpty()) {\n                internalStorage.insert(toExtract.getStack(), result.getCount(), Action.PERFORM);\n\n                toRemove.add(result);\n            }\n        }\n\n        for (ItemStack stack : toRemove) {\n            toExtractInitial.remove(stack);\n        }\n\n        if (!toRemove.isEmpty()) {\n            network.getCraftingManager().onTaskChanged();\n        }\n    }\n\n    public static void extractFluidsFromNetwork(IStackList<FluidStack> toExtractInitial, INetwork network, IStorageDisk<FluidStack> internalStorage) {\n        if (toExtractInitial.isEmpty()) {\n            return;\n        }\n\n        List<FluidStack> toRemove = new ArrayList<>();\n\n        for (StackListEntry<FluidStack> toExtract : toExtractInitial.getStacks()) {\n            FluidStack result = network.extractFluid(toExtract.getStack(), toExtract.getStack().getAmount(), Action.PERFORM);\n\n            if (!result.isEmpty()) {\n                internalStorage.insert(result, result.getAmount(), Action.PERFORM);\n\n                toRemove.add(result);\n            }\n        }\n\n        for (FluidStack stack : toRemove) {\n            toExtractInitial.remove(stack);\n        }\n\n        if (!toRemove.isEmpty()) {\n            network.getCraftingManager().onTaskChanged();\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/SerializationUtil.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternProvider;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.api.util.StackListEntry;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.fluids.FluidStack;\n\npublic class SerializationUtil {\n    private static final String NBT_PATTERN_STACK = \"Stack\";\n    private static final String NBT_PATTERN_CONTAINER_POS = \"ContainerPos\";\n\n    private SerializationUtil() {\n    }\n\n    public static ListTag writeItemStackList(IStackList<ItemStack> stacks) {\n        ListTag list = new ListTag();\n\n        for (StackListEntry<ItemStack> entry : stacks.getStacks()) {\n            list.add(StackUtils.serializeStackToNbt(entry.getStack()));\n        }\n\n        return list;\n    }\n\n    public static IStackList<ItemStack> readItemStackList(ListTag list) throws CraftingTaskReadException {\n        IStackList<ItemStack> stacks = API.instance().createItemStackList();\n\n        for (int i = 0; i < list.size(); ++i) {\n            ItemStack stack = StackUtils.deserializeStackFromNbt(list.getCompound(i));\n\n            if (stack.isEmpty()) {\n                throw new CraftingTaskReadException(\"Empty stack!\");\n            }\n\n            stacks.add(stack);\n        }\n\n        return stacks;\n    }\n\n    public static ListTag writeFluidStackList(IStackList<FluidStack> stacks) {\n        ListTag list = new ListTag();\n\n        for (StackListEntry<FluidStack> entry : stacks.getStacks()) {\n            list.add(entry.getStack().writeToNBT(new CompoundTag()));\n        }\n\n        return list;\n    }\n\n    public static IStackList<FluidStack> readFluidStackList(ListTag list) throws CraftingTaskReadException {\n        IStackList<FluidStack> stacks = API.instance().createFluidStackList();\n\n        for (int i = 0; i < list.size(); ++i) {\n            FluidStack stack = FluidStack.loadFluidStackFromNBT(list.getCompound(i));\n\n            if (stack.isEmpty()) {\n                throw new CraftingTaskReadException(\"Empty stack!\");\n            }\n\n            stacks.add(stack);\n        }\n\n        return stacks;\n    }\n\n    public static CompoundTag writePatternToNbt(ICraftingPattern pattern) {\n        CompoundTag tag = new CompoundTag();\n\n        tag.put(NBT_PATTERN_STACK, pattern.getStack().save(new CompoundTag()));\n        tag.putLong(NBT_PATTERN_CONTAINER_POS, pattern.getContainer().getPosition().asLong());\n\n        return tag;\n    }\n\n    public static ICraftingPattern readPatternFromNbt(CompoundTag tag, Level level) throws CraftingTaskReadException {\n        BlockPos containerPos = BlockPos.of(tag.getLong(NBT_PATTERN_CONTAINER_POS));\n\n        INetworkNode node = API.instance().getNetworkNodeManager((ServerLevel) level).getNode(containerPos);\n\n        if (node instanceof ICraftingPatternContainer) {\n            ItemStack stack = ItemStack.of(tag.getCompound(NBT_PATTERN_STACK));\n\n            if (stack.getItem() instanceof ICraftingPatternProvider) {\n                return ((ICraftingPatternProvider) stack.getItem()).create(level, stack, (ICraftingPatternContainer) node);\n            } else {\n                throw new CraftingTaskReadException(\"Pattern stack is not a crafting pattern provider\");\n            }\n        } else {\n            throw new CraftingTaskReadException(\"Crafting pattern container doesn't exist anymore\");\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/calculator/CalculationResult.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.calculator;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.CalculationResultType;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICalculationResult;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask;\n\nimport javax.annotation.Nullable;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class CalculationResult implements ICalculationResult {\n    private final CalculationResultType type;\n    private final ICraftingPattern recursedPattern;\n    private final List<ICraftingPreviewElement> previewElements;\n    private final ICraftingTask craftingTask;\n\n    public CalculationResult(CalculationResultType type) {\n        this.type = type;\n        this.recursedPattern = null;\n        this.previewElements = Collections.emptyList();\n        this.craftingTask = null;\n    }\n\n    public CalculationResult(CalculationResultType type, ICraftingPattern recursedPattern) {\n        this.type = type;\n        this.recursedPattern = recursedPattern;\n        this.previewElements = Collections.emptyList();\n        this.craftingTask = null;\n    }\n\n    public CalculationResult(CalculationResultType type, List<ICraftingPreviewElement> previewElements, @Nullable ICraftingTask craftingTask) {\n        this.type = type;\n        this.recursedPattern = null;\n        this.previewElements = previewElements;\n        this.craftingTask = craftingTask;\n    }\n\n    @Override\n    public CalculationResultType getType() {\n        return type;\n    }\n\n    @Override\n    public List<ICraftingPreviewElement> getPreviewElements() {\n        return previewElements;\n    }\n\n    @Nullable\n    @Override\n    public ICraftingTask getTask() {\n        return craftingTask;\n    }\n\n    @Override\n    public boolean isOk() {\n        return type == CalculationResultType.OK;\n    }\n\n    @Override\n    @Nullable\n    public ICraftingPattern getRecursedPattern() {\n        return recursedPattern;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/calculator/CraftingCalculator.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.calculator;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.CalculationResultType;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICalculationResult;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingRequestInfo;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.CraftingPatternInputs;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.CraftingTask;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.CraftingNode;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.Node;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.NodeList;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.ProcessingNode;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.preview.CraftingPreviewElementFactory;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.preview.CraftingPreviewInfo;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\nimport javax.annotation.Nullable;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\npublic class CraftingCalculator {\n    private final INetwork network;\n    private final ICraftingRequestInfo requested;\n    private final int quantity;\n    private final ICraftingPattern pattern;\n\n    private final Set<ICraftingPattern> patternsUsed = new HashSet<>();\n\n    private final CraftingPreviewInfo craftingPreviewInfo = new CraftingPreviewInfo();\n\n    private final NodeList nodes = new NodeList();\n\n    private final IStackList<ItemStack> toExtractInitial = API.instance().createItemStackList();\n    private final IStackList<FluidStack> toExtractInitialFluids = API.instance().createFluidStackList();\n\n    private long calculationStarted = -1;\n\n    public CraftingCalculator(INetwork network, ICraftingRequestInfo requested, int quantity, ICraftingPattern pattern) {\n        this.network = network;\n        this.requested = requested;\n        this.quantity = quantity;\n        this.pattern = pattern;\n    }\n\n    public ICalculationResult calculate() {\n        this.calculationStarted = System.currentTimeMillis();\n\n        IStackList<ItemStack> results = API.instance().createItemStackList();\n        IStackList<FluidStack> fluidResults = API.instance().createFluidStackList();\n\n        IStackList<ItemStack> storageSource = network.getItemStorageCache().getList().copy();\n        IStackList<FluidStack> fluidStorageSource = network.getFluidStorageCache().getList().copy();\n\n        int qtyPerCraft = getQuantityPerCraft(requested.getItem(), requested.getFluid(), pattern);\n        int qty = ((quantity - 1) / qtyPerCraft) + 1;\n\n        try {\n            calculateInternal(qty, storageSource, fluidStorageSource, results, fluidResults, pattern, true);\n        } catch (CraftingCalculatorException e) {\n            return new CalculationResult(e.getType(), e.getRecursedPattern());\n        }\n\n        if (requested.getItem() != null) {\n            craftingPreviewInfo.getToCraft().add(ItemHandlerHelper.copyStackWithSize(requested.getItem(), qty * qtyPerCraft));\n        } else if (requested.getFluid() != null) {\n            craftingPreviewInfo.getToCraftFluids().add(StackUtils.copy(requested.getFluid(), qty * qtyPerCraft));\n        }\n\n        List<ICraftingPreviewElement> previewElements = new CraftingPreviewElementFactory().getElements(craftingPreviewInfo);\n\n        if (craftingPreviewInfo.hasMissing()) {\n            return new CalculationResult(CalculationResultType.MISSING, previewElements, null);\n        }\n\n        return new CalculationResult(\n            CalculationResultType.OK,\n            previewElements,\n            new CraftingTask(network, requested, quantity, pattern, nodes, toExtractInitial, toExtractInitialFluids)\n        );\n    }\n\n    private void calculateInternal(\n        int qty,\n        IStackList<ItemStack> storageSource,\n        IStackList<FluidStack> fluidStorageSource,\n        IStackList<ItemStack> results,\n        IStackList<FluidStack> fluidResults,\n        ICraftingPattern pattern,\n        boolean root) throws CraftingCalculatorException {\n\n        if (System.currentTimeMillis() - calculationStarted > RS.SERVER_CONFIG.getAutocrafting().getCalculationTimeoutMs()) {\n            throw new CraftingCalculatorException(CalculationResultType.TOO_COMPLEX, null);\n        }\n\n        if (!patternsUsed.add(pattern)) {\n            throw new CraftingCalculatorException(CalculationResultType.RECURSIVE, pattern);\n        }\n\n        IStackList<ItemStack> itemsToExtract = API.instance().createItemStackList();\n        IStackList<FluidStack> fluidsToExtract = API.instance().createFluidStackList();\n\n        CraftingPatternInputs inputs = new CraftingPatternInputs(pattern);\n\n        Node node = nodes.createOrAddToExistingNode(pattern, root, inputs.getRecipe(), qty);\n\n        calculateForItems(qty, storageSource, fluidStorageSource, results, fluidResults, itemsToExtract, inputs, node);\n\n        if (node instanceof CraftingNode) {\n            ItemStack output = pattern.getOutput(inputs.getRecipe(), network.getLevel().registryAccess());\n            results.add(output, output.getCount() * qty);\n\n            for (ItemStack byproduct : pattern.getByproducts(inputs.getRecipe())) {\n                results.add(byproduct, byproduct.getCount() * qty);\n            }\n        } else if (node instanceof ProcessingNode) {\n            ProcessingNode processing = (ProcessingNode) node;\n\n            calculateForFluids(qty, storageSource, fluidStorageSource, results, fluidResults, inputs, fluidsToExtract, processing);\n\n            for (ItemStack output : pattern.getOutputs()) {\n                results.add(output, output.getCount() * qty);\n            }\n\n            for (FluidStack output : pattern.getFluidOutputs()) {\n                fluidResults.add(output, output.getAmount() * qty);\n            }\n        }\n\n        patternsUsed.remove(pattern);\n    }\n\n    private void calculateForItems(int qty,\n                                   IStackList<ItemStack> storageSource,\n                                   IStackList<FluidStack> fluidStorageSource,\n                                   IStackList<ItemStack> results,\n                                   IStackList<FluidStack> fluidResults,\n                                   IStackList<ItemStack> itemsToExtract,\n                                   CraftingPatternInputs inputs,\n                                   Node node) throws CraftingCalculatorException {\n        int ingredientNumber = -1;\n\n        for (CraftingPatternInputs.Ingredient<ItemStack> ingredient : inputs.getItemIngredients()) {\n            ingredientNumber++;\n\n            PossibleInputs<ItemStack> possibleInputs = new PossibleInputs<>(ingredient.getInputs());\n            possibleInputs.sort(storageSource, results);\n\n            ItemStack possibleInput = possibleInputs.get();\n\n            ItemStack fromSelf = results.get(possibleInput);\n            ItemStack fromNetwork = storageSource.get(possibleInput);\n\n            int remaining = ingredient.getCount() * qty;\n\n            if (remaining < 0) { // int overflow\n                throw new CraftingCalculatorException(CalculationResultType.TOO_COMPLEX);\n            }\n\n            while (remaining > 0) {\n                if (fromSelf != null) {\n                    int toTake = Math.min(remaining, fromSelf.getCount());\n\n                    node.getRequirements().addItemRequirement(ingredientNumber, possibleInput, toTake, ingredient.getCount());\n\n                    results.remove(fromSelf, toTake);\n\n                    remaining -= toTake;\n\n                    fromSelf = results.get(possibleInput);\n                }\n\n                if (fromNetwork != null && remaining > 0) {\n                    int toTake = Math.min(remaining, fromNetwork.getCount());\n\n                    craftingPreviewInfo.getToTake().add(possibleInput, toTake);\n\n                    node.getRequirements().addItemRequirement(ingredientNumber, possibleInput, toTake, ingredient.getCount());\n\n                    storageSource.remove(fromNetwork, toTake);\n\n                    remaining -= toTake;\n\n                    fromNetwork = storageSource.get(possibleInput);\n\n                    toExtractInitial.add(possibleInput, toTake);\n                }\n\n                if (remaining > 0) {\n                    ICraftingPattern subPattern = network.getCraftingManager().getPattern(possibleInput);\n\n                    if (subPattern != null) {\n                        int qtyPerCraft = getQuantityPerCraft(possibleInput, null, subPattern);\n                        int subQty = ((remaining - 1) / qtyPerCraft) + 1;\n\n                        calculateInternal(subQty, storageSource, fluidStorageSource, results, fluidResults, subPattern, false);\n\n                        fromSelf = results.get(possibleInput);\n                        if (fromSelf == null) {\n                            throw new IllegalStateException(\"Recursive calculation didn't yield anything\");\n                        }\n\n                        fromNetwork = storageSource.get(possibleInput);\n\n                        // fromSelf contains the amount crafted after the loop.\n                        craftingPreviewInfo.getToCraft().add(fromSelf.copy());\n                    } else {\n                        if (!possibleInputs.cycle()) {\n                            // Give up.\n                            possibleInput = possibleInputs.get(); // Revert back to 0.\n\n                            craftingPreviewInfo.getMissing().add(possibleInput, remaining);\n\n                            itemsToExtract.add(possibleInput, remaining);\n\n                            remaining = 0;\n                        } else {\n                            // Retry with new input...\n                            possibleInput = possibleInputs.get();\n\n                            fromSelf = results.get(possibleInput);\n                            fromNetwork = storageSource.get(possibleInput);\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    private void calculateForFluids(int qty,\n                                    IStackList<ItemStack> storageSource,\n                                    IStackList<FluidStack> fluidStorageSource,\n                                    IStackList<ItemStack> results,\n                                    IStackList<FluidStack> fluidResults,\n                                    CraftingPatternInputs inputs,\n                                    IStackList<FluidStack> fluidsToExtract,\n                                    ProcessingNode node) throws CraftingCalculatorException {\n        int ingredientNumber = -1;\n\n        for (CraftingPatternInputs.Ingredient<FluidStack> ingredient : inputs.getFluidIngredients()) {\n            ingredientNumber++;\n\n            PossibleInputs<FluidStack> possibleInputs = new PossibleInputs<>(ingredient.getInputs());\n            possibleInputs.sort(fluidStorageSource, fluidResults);\n\n            FluidStack possibleInput = possibleInputs.get();\n\n            FluidStack fromSelf = fluidResults.get(possibleInput, IComparer.COMPARE_NBT);\n            FluidStack fromNetwork = fluidStorageSource.get(possibleInput, IComparer.COMPARE_NBT);\n\n            int remaining = ingredient.getCount() * qty;\n\n            if (remaining < 0) { // int overflow\n                throw new CraftingCalculatorException(CalculationResultType.TOO_COMPLEX);\n            }\n\n            while (remaining > 0) {\n                if (fromSelf != null) {\n                    int toTake = Math.min(remaining, fromSelf.getAmount());\n\n                    node.getRequirements().addFluidRequirement(ingredientNumber, possibleInput, toTake, ingredient.getCount());\n\n                    fluidResults.remove(possibleInput, toTake);\n\n                    remaining -= toTake;\n\n                    fromSelf = fluidResults.get(possibleInput, IComparer.COMPARE_NBT);\n                }\n\n                if (fromNetwork != null && remaining > 0) {\n                    int toTake = Math.min(remaining, fromNetwork.getAmount());\n\n                    node.getRequirements().addFluidRequirement(ingredientNumber, possibleInput, toTake, ingredient.getCount());\n\n                    craftingPreviewInfo.getToTakeFluids().add(possibleInput, toTake);\n\n                    fluidStorageSource.remove(fromNetwork, toTake);\n\n                    remaining -= toTake;\n\n                    fromNetwork = fluidStorageSource.get(possibleInput, IComparer.COMPARE_NBT);\n\n                    toExtractInitialFluids.add(possibleInput, toTake);\n                }\n\n                if (remaining > 0) {\n                    ICraftingPattern subPattern = network.getCraftingManager().getPattern(possibleInput);\n\n                    if (subPattern != null) {\n                        int qtyPerCraft = getQuantityPerCraft(null, possibleInput, subPattern);\n                        int subQty = ((remaining - 1) / qtyPerCraft) + 1;\n\n                        calculateInternal(subQty, storageSource, fluidStorageSource, results, fluidResults, subPattern, false);\n\n                        fromSelf = fluidResults.get(possibleInput, IComparer.COMPARE_NBT);\n                        if (fromSelf == null) {\n                            throw new IllegalStateException(\"Recursive fluid calculation didn't yield anything\");\n                        }\n\n                        fromNetwork = fluidStorageSource.get(possibleInput, IComparer.COMPARE_NBT);\n\n                        // fromSelf contains the amount crafted after the loop.\n                        craftingPreviewInfo.getToCraftFluids().add(fromSelf.copy());\n                    } else {\n                        if (!possibleInputs.cycle()) {\n                            // Give up.\n                            possibleInput = possibleInputs.get(); // Revert back to 0.\n\n                            craftingPreviewInfo.getMissingFluids().add(possibleInput, remaining);\n\n                            fluidsToExtract.add(possibleInput, remaining);\n\n                            remaining = 0;\n                        } else {\n                            // Retry with new input...\n                            possibleInput = possibleInputs.get();\n\n                            fromSelf = fluidResults.get(possibleInput);\n                            fromNetwork = fluidStorageSource.get(possibleInput);\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    private int getQuantityPerCraft(@Nullable ItemStack item, @Nullable FluidStack fluid, ICraftingPattern pattern) {\n        if (item != null) {\n            return getQuantityPerCraftForItem(item, pattern);\n        } else if (fluid != null) {\n            return getQuantityPerCraftForFluid(fluid, pattern);\n        } else {\n            return 0;\n        }\n    }\n\n    private int getQuantityPerCraftForFluid(FluidStack fluid, ICraftingPattern pattern) {\n        int qty = 0;\n\n        for (FluidStack output : pattern.getFluidOutputs()) {\n            if (API.instance().getComparer().isEqual(output, fluid, IComparer.COMPARE_NBT)) {\n                qty += output.getAmount();\n            }\n        }\n\n        return qty;\n    }\n\n    private int getQuantityPerCraftForItem(ItemStack item, ICraftingPattern pattern) {\n        int qty = 0;\n\n        for (ItemStack output : pattern.getOutputs()) {\n            if (API.instance().getComparer().isEqualNoQuantity(output, item)) {\n                qty += output.getCount();\n\n                if (!pattern.isProcessing()) {\n                    break;\n                }\n            }\n        }\n\n        return qty;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/calculator/CraftingCalculatorException.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.calculator;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.CalculationResultType;\n\nimport javax.annotation.Nullable;\n\npublic class CraftingCalculatorException extends Exception {\n    private final CalculationResultType type;\n    @Nullable\n    private final transient ICraftingPattern recursedPattern;\n\n    public CraftingCalculatorException(CalculationResultType type) {\n        this.type = type;\n        this.recursedPattern = null;\n    }\n\n    public CraftingCalculatorException(CalculationResultType type, @Nullable ICraftingPattern recursedPattern) {\n        this.type = type;\n        this.recursedPattern = recursedPattern;\n    }\n\n    public CalculationResultType getType() {\n        return type;\n    }\n\n    @Nullable\n    public ICraftingPattern getRecursedPattern() {\n        return recursedPattern;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/calculator/PossibleInputs.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.calculator;\n\nimport com.refinedmods.refinedstorage.api.util.IStackList;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class PossibleInputs<T> {\n    private final List<T> possibilities;\n    private int pos;\n\n    public PossibleInputs(List<T> possibilities) {\n        this.possibilities = new ArrayList<>(possibilities);\n    }\n\n    public T get() {\n        return possibilities.get(pos);\n    }\n\n    // Return false if we're exhausted.\n    public boolean cycle() {\n        if (pos + 1 >= possibilities.size()) {\n            pos = 0;\n\n            return false;\n        }\n\n        pos++;\n\n        return true;\n    }\n\n    public void sort(IStackList<T> mutatedStorage, IStackList<T> results) {\n        possibilities.sort((a, b) -> {\n            int ar = mutatedStorage.getCount(a);\n            int br = mutatedStorage.getCount(b);\n\n            return br - ar;\n        });\n\n        possibilities.sort((a, b) -> {\n            int ar = results.getCount(a);\n            int br = results.getCount(b);\n\n            return br - ar;\n        });\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/monitor/CraftingMonitorElementFactory.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.monitor;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement;\nimport com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementList;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.util.StackListEntry;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor.ErrorCraftingMonitorElement;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor.FluidCraftingMonitorElement;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor.ItemCraftingMonitorElement;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.CraftingNode;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.Node;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.ProcessingNode;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.ProcessingState;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport java.util.Collection;\nimport java.util.List;\n\npublic class CraftingMonitorElementFactory {\n    public List<ICraftingMonitorElement> getElements(Collection<Node> nodes, IStorageDisk<ItemStack> internalStorage, IStorageDisk<FluidStack> internalFluidStorage) {\n        ICraftingMonitorElementList list = API.instance().createCraftingMonitorElementList();\n\n        for (Node node : nodes) {\n            if (node instanceof CraftingNode) {\n                addForRecipe(list, (CraftingNode) node);\n            } else {\n                addForProcessing(list, (ProcessingNode) node);\n            }\n        }\n\n        for (ItemStack stack : internalStorage.getStacks()) {\n            list.addStorage(new ItemCraftingMonitorElement(stack, stack.getCount(), 0, 0, 0, 0));\n        }\n\n        for (FluidStack stack : internalFluidStorage.getStacks()) {\n            list.addStorage(new FluidCraftingMonitorElement(stack, stack.getAmount(), 0, 0, 0, 0));\n        }\n\n        list.commit();\n\n        return list.getElements();\n    }\n\n    private void addForProcessing(ICraftingMonitorElementList list, ProcessingNode node) {\n        if (node.getState() == ProcessingState.PROCESSED) {\n            return;\n        }\n\n        for (StackListEntry<ItemStack> requirement : node.getSingleItemSetToRequire().getStacks()) {\n            if (node.getCurrentlyProcessing() > 0) {\n                ICraftingMonitorElement element = ItemCraftingMonitorElement.Builder\n                    .forStack(requirement.getStack())\n                    .processing(requirement.getStack().getCount() * node.getCurrentlyProcessing())\n                    .build();\n\n                list.add(element, true);\n            }\n        }\n\n        for (StackListEntry<ItemStack> toReceive : node.getSingleItemSetToReceive().getStacks()) {\n            int needed = node.getNeeded(toReceive.getStack());\n\n            if (needed > 0) {\n                ICraftingMonitorElement element = ItemCraftingMonitorElement.Builder\n                    .forStack(toReceive.getStack())\n                    .scheduled(needed)\n                    .build();\n\n                element = wrapWithProcessingState(element, node.getState(), \"item\");\n\n                list.add(element, true);\n            }\n        }\n\n        for (StackListEntry<FluidStack> requirement : node.getSingleFluidSetToRequire().getStacks()) {\n            if (node.getCurrentlyProcessing() > 0) {\n                ICraftingMonitorElement element = FluidCraftingMonitorElement.Builder\n                    .forStack(requirement.getStack())\n                    .processing(requirement.getStack().getAmount() * node.getCurrentlyProcessing())\n                    .build();\n\n                list.add(element, true);\n            }\n        }\n\n        for (StackListEntry<FluidStack> toReceive : node.getSingleFluidSetToReceive().getStacks()) {\n            int needed = node.getNeeded(toReceive.getStack());\n\n            if (needed > 0) {\n                ICraftingMonitorElement element = FluidCraftingMonitorElement.Builder\n                    .forStack(toReceive.getStack())\n                    .scheduled(needed)\n                    .build();\n\n                element = wrapWithProcessingState(element, node.getState(), \"fluid\");\n\n                list.add(element, true);\n            }\n        }\n    }\n\n    private ICraftingMonitorElement wrapWithProcessingState(ICraftingMonitorElement element, ProcessingState state, String type) {\n        if (state == ProcessingState.MACHINE_DOES_NOT_ACCEPT) {\n            return new ErrorCraftingMonitorElement(element, \"gui.refinedstorage.crafting_monitor.machine_does_not_accept_\" + type);\n        } else if (state == ProcessingState.MACHINE_NONE) {\n            return new ErrorCraftingMonitorElement(element, \"gui.refinedstorage.crafting_monitor.machine_none\");\n        } else if (state == ProcessingState.LOCKED) {\n            return new ErrorCraftingMonitorElement(element, \"gui.refinedstorage.crafting_monitor.crafter_is_locked\");\n        }\n\n        return element;\n    }\n\n    private void addForRecipe(ICraftingMonitorElementList list, CraftingNode node) {\n        if (node.getQuantity() > 0) {\n            for (ItemStack receive : node.getPattern().getOutputs()) {\n                list.add(new ItemCraftingMonitorElement(receive, 0, 0, 0, 0, receive.getCount() * node.getQuantity()), false);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/node/CraftingNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.IoUtil;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.core.NonNullList;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.nbt.Tag;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\n\npublic class CraftingNode extends Node {\n    private static final String NBT_RECIPE = \"Recipe\";\n\n    private final NonNullList<ItemStack> recipe;\n\n    public CraftingNode(ICraftingPattern pattern, boolean root, NonNullList<ItemStack> recipe) {\n        super(pattern, root);\n\n        this.recipe = recipe;\n    }\n\n    public CraftingNode(INetwork network, CompoundTag tag) throws CraftingTaskReadException {\n        super(network, tag);\n\n        this.recipe = NonNullList.create();\n\n        ListTag tookList = tag.getList(NBT_RECIPE, Tag.TAG_COMPOUND);\n        for (int i = 0; i < tookList.size(); ++i) {\n            recipe.add(StackUtils.deserializeStackFromNbt(tookList.getCompound(i)));\n        }\n    }\n\n    @Override\n    public void update(INetwork network, int ticks, NodeList nodes, IStorageDisk<ItemStack> internalStorage, IStorageDisk<FluidStack> internalFluidStorage, NodeListener listener) {\n        for (ICraftingPatternContainer container : network.getCraftingManager().getAllContainers(getPattern())) {\n            int interval = container.getUpdateInterval();\n            if (interval < 0) {\n                throw new IllegalStateException(container + \" has an update interval of < 0\");\n            }\n\n            if (interval == 0 || ticks % interval == 0) {\n                for (int i = 0; i < container.getMaximumSuccessfulCraftingUpdates(); i++) {\n\n                    var simulatedRequirements = requirements.getSingleItemRequirementSet(true);\n                    if(simulatedRequirements == null) {\n                        return;\n                    }\n\n                    if (IoUtil.extractFromInternalItemStorage(simulatedRequirements, internalStorage, Action.SIMULATE) != null) {\n\n                        var actualRequirements = requirements.getSingleItemRequirementSet(false);\n                        if(actualRequirements == null) {\n                            return;\n                        }\n\n                        IoUtil.extractFromInternalItemStorage(actualRequirements, internalStorage, Action.PERFORM);\n\n                        ItemStack output = getPattern().getOutput(recipe, network.getLevel().registryAccess());\n\n                        if (!isRoot()) {\n                            internalStorage.insert(output, output.getCount(), Action.PERFORM);\n                        } else {\n                            ItemStack remainder = network.insertItem(output, output.getCount(), Action.PERFORM);\n\n                            internalStorage.insert(remainder, remainder.getCount(), Action.PERFORM);\n                        }\n\n                        // Byproducts need to always be inserted in the internal storage for later reuse further in the task.\n                        // Regular outputs can be inserted into the network *IF* it's a root since it's *NOT* expected to be used later on.\n                        for (ItemStack byp : getPattern().getByproducts(recipe)) {\n                            internalStorage.insert(byp, byp.getCount(), Action.PERFORM);\n                        }\n\n                        next();\n\n                        listener.onSingleDone(this);\n\n                        if (getQuantity() <= 0) {\n                            listener.onAllDone(this);\n                            return;\n                        }\n                    } else {\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    @Override\n    public CompoundTag writeToNbt() {\n        CompoundTag tag = super.writeToNbt();\n\n        ListTag tookList = new ListTag();\n        for (ItemStack took : this.recipe) {\n            tookList.add(StackUtils.serializeStackToNbt(took));\n        }\n\n        tag.put(NBT_RECIPE, tookList);\n\n        return tag;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/node/Node.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.SerializationUtil;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\n\npublic abstract class Node {\n    private static final String NBT_PATTERN = \"Pattern\";\n    private static final String NBT_ROOT = \"Root\";\n    private static final String NBT_IS_PROCESSING = \"IsProcessing\";\n    private static final String NBT_QUANTITY = \"Quantity\";\n    private static final String NBT_QUANTITY_TOTAL = \"TotalQuantity\";\n    protected final NodeRequirements requirements = new NodeRequirements();\n    private final boolean root;\n    private final ICraftingPattern pattern;\n    protected int quantity;\n    protected int totalQuantity;\n\n    protected Node(ICraftingPattern pattern, boolean root) {\n        this.pattern = pattern;\n        this.root = root;\n    }\n\n    protected Node(INetwork network, CompoundTag tag) throws CraftingTaskReadException {\n        this.quantity = tag.getInt(NBT_QUANTITY);\n        this.totalQuantity = tag.getInt(NBT_QUANTITY_TOTAL);\n        this.pattern = SerializationUtil.readPatternFromNbt(tag.getCompound(NBT_PATTERN), network.getLevel());\n        this.root = tag.getBoolean(NBT_ROOT);\n        this.requirements.readFromNbt(tag);\n    }\n\n    public static Node fromNbt(INetwork network, CompoundTag tag) throws CraftingTaskReadException {\n        return tag.getBoolean(NBT_IS_PROCESSING) ? new ProcessingNode(network, tag) : new CraftingNode(network, tag);\n    }\n\n    public abstract void update(INetwork network, int ticks, NodeList nodes, IStorageDisk<ItemStack> internalStorage, IStorageDisk<FluidStack> internalFluidStorage, NodeListener listener);\n\n    public void onCalculationFinished() {\n        this.totalQuantity = quantity;\n    }\n\n    public ICraftingPattern getPattern() {\n        return pattern;\n    }\n\n    public int getQuantity() {\n        return quantity;\n    }\n\n    public void addQuantity(int quantity) {\n        this.quantity += quantity;\n    }\n\n    protected void next() {\n        quantity--;\n    }\n\n    public boolean isRoot() {\n        return root;\n    }\n\n    public NodeRequirements getRequirements() {\n        return requirements;\n    }\n\n    public CompoundTag writeToNbt() {\n        CompoundTag tag = new CompoundTag();\n\n        tag.putInt(NBT_QUANTITY, quantity);\n        tag.putInt(NBT_QUANTITY_TOTAL, totalQuantity);\n        tag.putBoolean(NBT_IS_PROCESSING, this instanceof ProcessingNode);\n        tag.putBoolean(NBT_ROOT, root);\n        tag.put(NBT_PATTERN, SerializationUtil.writePatternToNbt(pattern));\n        tag = requirements.writeToNbt(tag);\n\n        return tag;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/node/NodeList.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport net.minecraft.core.NonNullList;\nimport net.minecraft.world.item.ItemStack;\n\nimport java.util.*;\n\npublic class NodeList {\n    private final Map<ICraftingPattern, Node> nodes = new LinkedHashMap<>();\n    private final List<Node> nodesToRemove = new ArrayList<>();\n\n    public void removeMarkedForRemoval() {\n        for (Node node : nodesToRemove) {\n            nodes.remove(node.getPattern());\n        }\n        nodesToRemove.clear();\n    }\n\n    public Collection<Node> all() {\n        return nodes.values();\n    }\n\n    public void unlockAll(INetwork network) {\n        for (Node node : nodes.values()) {\n            if (node instanceof ProcessingNode) {\n                network.getCraftingManager().getAllContainers(node.getPattern()).forEach(ICraftingPatternContainer::unlock);\n            }\n        }\n    }\n\n    public boolean isEmpty() {\n        return nodes.isEmpty();\n    }\n\n    public void remove(Node node) {\n        nodesToRemove.add(node);\n    }\n\n    public Node createOrAddToExistingNode(ICraftingPattern pattern, boolean root, NonNullList<ItemStack> recipe, int qty) {\n        Node node = nodes.computeIfAbsent(pattern, key -> createNode(key, root, recipe));\n        node.addQuantity(qty);\n\n        return node;\n    }\n\n    private Node createNode(ICraftingPattern pattern, boolean root, NonNullList<ItemStack> recipe) {\n        return pattern.isProcessing() ? new ProcessingNode(pattern, root) : new CraftingNode(pattern, root, recipe);\n    }\n\n    public void put(ICraftingPattern pattern, Node node) {\n        nodes.put(pattern, node);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/node/NodeListener.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node;\n\npublic interface NodeListener {\n    void onAllDone(Node node);\n\n    void onSingleDone(Node node);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/node/NodeRequirements.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node;\n\nimport com.google.common.primitives.Ints;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.api.util.StackListEntry;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.SerializationUtil;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.nbt.Tag;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\nimport javax.annotation.Nullable;\nimport java.util.*;\n\npublic class NodeRequirements {\n    private static final String NBT_ITEMS_TO_USE = \"ItemsToUse\";\n    private static final String NBT_FLUIDS_TO_USE = \"FluidsToUse\";\n\n    private static final String NBT_ITEMS_NEEDED_PER_CRAFT = \"ItemsNeededPerCraft\";\n    private static final String NBT_FLUIDS_NEEDED_PER_CRAFT = \"FluidsNeededPerCraft\";\n\n    private final Map<Integer, IStackList<ItemStack>> itemRequirements = new LinkedHashMap<>();\n    private final Map<Integer, Integer> itemsNeededPerCraft = new LinkedHashMap<>();\n\n    private final Map<Integer, IStackList<FluidStack>> fluidRequirements = new LinkedHashMap<>();\n    private final Map<Integer, Integer> fluidsNeededPerCraft = new LinkedHashMap<>();\n\n    @Nullable\n    private List<ItemStack> cachedSimulatedItemRequirementSet = null;\n    @Nullable\n    private List<FluidStack> cachedSimulatedFluidRequirementSet = null;\n\n    public void addItemRequirement(int ingredientNumber, ItemStack stack, int size, int perCraft) {\n        if (!itemsNeededPerCraft.containsKey(ingredientNumber)) {\n            itemsNeededPerCraft.put(ingredientNumber, perCraft);\n        }\n\n        IStackList<ItemStack> list = itemRequirements.computeIfAbsent(ingredientNumber, key -> API.instance().createItemStackList());\n        list.add(stack, size);\n        cachedSimulatedItemRequirementSet = null;\n    }\n\n    public void addFluidRequirement(int ingredientNumber, FluidStack stack, int size, int perCraft) {\n        if (!fluidsNeededPerCraft.containsKey(ingredientNumber)) {\n            fluidsNeededPerCraft.put(ingredientNumber, perCraft);\n        }\n\n        IStackList<FluidStack> list = fluidRequirements.computeIfAbsent(ingredientNumber, key -> API.instance().createFluidStackList());\n        list.add(stack, size);\n        cachedSimulatedFluidRequirementSet = null;\n    }\n\n    public List<ItemStack> getSingleItemRequirementSet(boolean simulate) {\n        List<ItemStack> cached = cachedSimulatedItemRequirementSet;\n        if (simulate && cached != null) {\n            return cached;\n        }\n\n        List<ItemStack> toReturn = new ArrayList<>();\n\n        for (int i = 0; i < itemRequirements.size(); i++) {\n            int needed = itemsNeededPerCraft.get(i);\n\n            if (!itemRequirements.get(i).isEmpty()) {\n                Iterator<StackListEntry<ItemStack>> it = itemRequirements.get(i).getStacks().iterator();\n\n                while (needed > 0 && it.hasNext()) {\n                    ItemStack toUse = it.next().getStack();\n\n                    if (needed < toUse.getCount()) {\n                        if (!simulate) {\n                            itemRequirements.get(i).remove(toUse, needed);\n                        }\n\n                        toReturn.add(ItemHandlerHelper.copyStackWithSize(toUse, needed));\n\n                        needed = 0;\n                    } else {\n                        if (!simulate) {\n                            it.remove();\n                        }\n\n                        toReturn.add(toUse);\n\n                        needed -= toUse.getCount();\n                    }\n                }\n            } else {\n                return null;\n            }\n        }\n\n        cachedSimulatedItemRequirementSet = simulate ? toReturn : null;\n\n        return toReturn;\n    }\n\n    public List<FluidStack> getSingleFluidRequirementSet(boolean simulate) {\n        List<FluidStack> cached = cachedSimulatedFluidRequirementSet;\n        if (simulate && cached != null) {\n            return cached;\n        }\n\n        List<FluidStack> toReturn = new ArrayList<>();\n\n        for (int i = 0; i < fluidRequirements.size(); i++) {\n            int needed = fluidsNeededPerCraft.get(i);\n\n            if (!fluidRequirements.get(i).isEmpty()) {\n                Iterator<StackListEntry<FluidStack>> it = fluidRequirements.get(i).getStacks().iterator();\n\n                while (needed > 0 && it.hasNext()) {\n                    FluidStack toUse = it.next().getStack();\n\n                    if (needed < toUse.getAmount()) {\n                        if (!simulate) {\n                            fluidRequirements.get(i).remove(toUse, needed);\n                        }\n\n                        FluidStack stack = toUse.copy();\n                        stack.setAmount(needed);\n                        toReturn.add(stack);\n\n                        needed = 0;\n                    } else {\n                        if (!simulate) {\n                            it.remove();\n                        }\n\n                        toReturn.add(toUse);\n\n                        needed -= toUse.getAmount();\n                    }\n                }\n            } else {\n                return null;\n            }\n        }\n\n        cachedSimulatedFluidRequirementSet = simulate ? toReturn : null;\n\n        return toReturn;\n    }\n\n    public void readFromNbt(CompoundTag tag) throws CraftingTaskReadException {\n        ListTag itemRequirementsTag = tag.getList(NBT_ITEMS_TO_USE, Tag.TAG_LIST);\n        for (int i = 0; i < itemRequirementsTag.size(); i++) {\n            itemRequirements.put(i, SerializationUtil.readItemStackList(itemRequirementsTag.getList(i)));\n        }\n\n        List<Integer> itemsNeededPerCraftTag = Ints.asList(tag.getIntArray(NBT_ITEMS_NEEDED_PER_CRAFT));\n        for (int i = 0; i < itemsNeededPerCraftTag.size(); i++) {\n            itemsNeededPerCraft.put(i, itemsNeededPerCraftTag.get(i));\n        }\n\n        ListTag fluidRequirementsTag = tag.getList(NBT_FLUIDS_TO_USE, Tag.TAG_LIST);\n        for (int i = 0; i < fluidRequirementsTag.size(); i++) {\n            fluidRequirements.put(i, SerializationUtil.readFluidStackList(fluidRequirementsTag.getList(i)));\n        }\n\n        List<Integer> fluidsNeededPerCraftTag = Ints.asList(tag.getIntArray(NBT_FLUIDS_NEEDED_PER_CRAFT));\n        for (int i = 0; i < fluidsNeededPerCraftTag.size(); i++) {\n            fluidsNeededPerCraft.put(i, fluidsNeededPerCraftTag.get(i));\n        }\n    }\n\n    public CompoundTag writeToNbt(CompoundTag tag) {\n        ListTag itemRequirementsTag = new ListTag();\n        for (IStackList<ItemStack> list : itemRequirements.values()) {\n            itemRequirementsTag.add(SerializationUtil.writeItemStackList(list));\n        }\n        tag.put(NBT_ITEMS_TO_USE, itemRequirementsTag);\n\n        tag.putIntArray(NBT_ITEMS_NEEDED_PER_CRAFT, Ints.toArray(itemsNeededPerCraft.values()));\n\n        ListTag fluidRequirementsTag = new ListTag();\n        for (IStackList<FluidStack> list : fluidRequirements.values()) {\n            fluidRequirementsTag.add(SerializationUtil.writeFluidStackList(list));\n        }\n        tag.put(NBT_FLUIDS_TO_USE, fluidRequirementsTag);\n\n        tag.putIntArray(NBT_FLUIDS_NEEDED_PER_CRAFT, Ints.toArray(fluidsNeededPerCraft.values()));\n\n        return tag;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/node/ProcessingNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.api.util.StackListEntry;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.IoUtil;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.SerializationUtil;\nimport com.refinedmods.refinedstorage.apiimpl.util.FluidStackList;\nimport com.refinedmods.refinedstorage.apiimpl.util.ItemStackList;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.Tag;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport java.util.List;\n\npublic class ProcessingNode extends Node {\n    private static final String NBT_ITEMS_RECEIVED = \"ItemsReceived\";\n    private static final String NBT_FLUIDS_RECEIVED = \"FluidsReceived\";\n    private static final String NBT_SINGLE_ITEM_SET_TO_REQUIRE = \"SingleItemSetToRequire\";\n    private static final String NBT_SINGLE_FLUID_SET_TO_REQUIRE = \"SingleFluidSetToRequire\";\n    private static final String NBT_STATE = \"State\";\n\n    private final IStackList<ItemStack> singleItemSetToReceive = API.instance().createItemStackList();\n    private final IStackList<FluidStack> singleFluidSetToReceive = API.instance().createFluidStackList();\n\n    private IStackList<ItemStack> singleItemSetToRequire;\n    private IStackList<FluidStack> singleFluidSetToRequire;\n\n    private IStackList<ItemStack> itemsReceived = API.instance().createItemStackList();\n    private IStackList<FluidStack> fluidsReceived = API.instance().createFluidStackList();\n\n    private ProcessingState state = ProcessingState.READY;\n\n    private int quantityFinished;\n\n    public ProcessingNode(ICraftingPattern pattern, boolean root) {\n        super(pattern, root);\n\n        initSetsToReceive();\n    }\n\n    public ProcessingNode(INetwork network, CompoundTag tag) throws CraftingTaskReadException {\n        super(network, tag);\n\n        this.itemsReceived = SerializationUtil.readItemStackList(tag.getList(NBT_ITEMS_RECEIVED, Tag.TAG_COMPOUND));\n        this.fluidsReceived = SerializationUtil.readFluidStackList(tag.getList(NBT_FLUIDS_RECEIVED, Tag.TAG_COMPOUND));\n\n        this.singleItemSetToRequire = SerializationUtil.readItemStackList(tag.getList(NBT_SINGLE_ITEM_SET_TO_REQUIRE, Tag.TAG_COMPOUND));\n        this.singleFluidSetToRequire = SerializationUtil.readFluidStackList(tag.getList(NBT_SINGLE_FLUID_SET_TO_REQUIRE, Tag.TAG_COMPOUND));\n\n        this.state = ProcessingState.values()[tag.getInt(NBT_STATE)];\n\n        initSetsToReceive();\n    }\n\n    private void initSetsToReceive() {\n        for (ItemStack output : getPattern().getOutputs()) {\n            singleItemSetToReceive.add(output, output.getCount());\n        }\n\n        for (FluidStack output : getPattern().getFluidOutputs()) {\n            singleFluidSetToReceive.add(output, output.getAmount());\n        }\n    }\n\n    @Override\n    public void update(INetwork network, int ticks, NodeList nodes, IStorageDisk<ItemStack> internalStorage, IStorageDisk<FluidStack> internalFluidStorage, NodeListener listener) {\n        if (getQuantity() <= 0) {\n            if (totalQuantity == quantityFinished) {\n                listener.onAllDone(this);\n            }\n            return;\n        }\n\n        boolean allLocked = true;\n        boolean allMissingMachine = true;\n        boolean allRejected = true;\n\n        ProcessingState originalState = state;\n\n        for (ICraftingPatternContainer container : network.getCraftingManager().getAllContainers(getPattern())) {\n            int interval = container.getUpdateInterval();\n\n            if (interval < 0) {\n                throw new IllegalStateException(container + \" has an update interval of < 0\");\n            }\n\n            if (interval == 0 || ticks % interval == 0) {\n                for (int i = 0; i < container.getMaximumSuccessfulCraftingUpdates(); i++) {\n                    if (getQuantity() <= 0) {\n                        return;\n                    }\n\n                    if (container.isLocked()) {\n                        if (allLocked) {\n                            this.state = ProcessingState.LOCKED;\n                        }\n\n                        break;\n                    } else {\n                        allLocked = false;\n                    }\n\n                    if ((!singleItemSetToRequire.isEmpty() && !container.hasConnectedInventory()) ||\n                        (!singleFluidSetToRequire.isEmpty() && !container.hasConnectedFluidInventory())) {\n                        if (allMissingMachine) {\n                            this.state = ProcessingState.MACHINE_NONE;\n                        }\n\n                        break;\n                    } else {\n                        allMissingMachine = false;\n                    }\n\n                    boolean hasAllRequirements = false;\n\n                    var simulatedRequirements = requirements.getSingleItemRequirementSet(true);\n                    if(simulatedRequirements == null) {\n                        return;\n                    }\n\n                    List<ItemStack> extractedItems = IoUtil.extractFromInternalItemStorage(simulatedRequirements, internalStorage, Action.SIMULATE);\n                    List<FluidStack> extractedFluids = null;\n                    if (extractedItems != null) {\n                        var simulatedFluidRequirements = requirements.getSingleFluidRequirementSet(true);\n                        if(simulatedFluidRequirements == null) {\n                            return;\n                        }\n\n                        extractedFluids = IoUtil.extractFromInternalFluidStorage(simulatedFluidRequirements, internalFluidStorage, Action.SIMULATE);\n                        if (extractedFluids != null) {\n                            hasAllRequirements = true;\n                        }\n                    }\n\n                    boolean canInsertFullAmount = false;\n                    if (hasAllRequirements) {\n                        canInsertFullAmount = container.insertItemsIntoInventory(extractedItems, Action.SIMULATE);\n                        if (canInsertFullAmount) {\n                            canInsertFullAmount = container.insertFluidsIntoInventory(extractedFluids, Action.SIMULATE);\n                        }\n                    } else {\n                        break;\n                    }\n\n                    if (!canInsertFullAmount) {\n                        if (allRejected) {\n                            this.state = ProcessingState.MACHINE_DOES_NOT_ACCEPT;\n                        }\n\n                        break;\n                    } else {\n                        allRejected = false;\n                    }\n\n                    this.state = ProcessingState.READY;\n                    var actualRequirements = requirements.getSingleItemRequirementSet(false);\n                    if(actualRequirements == null) {\n                        return;\n                    }\n                    extractedItems = IoUtil.extractFromInternalItemStorage(actualRequirements, internalStorage, Action.PERFORM);\n\n                    var actualFluidRequirements = requirements.getSingleFluidRequirementSet(false);\n                    if(actualFluidRequirements == null) {\n                        return;\n                    }\n                    extractedFluids = IoUtil.extractFromInternalFluidStorage(actualFluidRequirements, internalFluidStorage, Action.PERFORM);\n\n                    container.insertItemsIntoInventory(extractedItems, Action.PERFORM);\n                    container.insertFluidsIntoInventory(extractedFluids, Action.PERFORM);\n\n                    next();\n\n                    listener.onSingleDone(this);\n\n                    container.onUsedForProcessing();\n                }\n            }\n        }\n\n        if (originalState != state) {\n            network.getCraftingManager().onTaskChanged();\n        }\n    }\n\n    public ProcessingState getState() {\n        return state;\n    }\n\n    public IStackList<ItemStack> getSingleItemSetToReceive() {\n        return singleItemSetToReceive;\n    }\n\n    public IStackList<FluidStack> getSingleFluidSetToReceive() {\n        return singleFluidSetToReceive;\n    }\n\n    public IStackList<ItemStack> getSingleItemSetToRequire() {\n        return singleItemSetToRequire;\n    }\n\n    public IStackList<FluidStack> getSingleFluidSetToRequire() {\n        return singleFluidSetToRequire;\n    }\n\n    public int getNeeded(ItemStack stack) {\n        return (singleItemSetToReceive.getCount(stack) * totalQuantity) - itemsReceived.getCount(stack);\n    }\n\n    public int getNeeded(FluidStack stack) {\n        return (singleFluidSetToReceive.getCount(stack) * totalQuantity) - fluidsReceived.getCount(stack);\n    }\n\n    public int getCurrentlyProcessing() {\n        int unprocessed = totalQuantity - quantity;\n        return unprocessed - quantityFinished;\n    }\n\n    public void markReceived(ItemStack stack, int count) {\n        itemsReceived.add(stack, count);\n        updateFinishedQuantity();\n    }\n\n    public void markReceived(FluidStack stack, int count) {\n        fluidsReceived.add(stack, count);\n        updateFinishedQuantity();\n    }\n\n    public void updateFinishedQuantity() {\n        int tempQuantityFinished = totalQuantity;\n\n        for (StackListEntry<ItemStack> toReceive : singleItemSetToReceive.getStacks()) {\n            if (itemsReceived.get(toReceive.getStack()) != null) {\n                int ratioReceived = itemsReceived.get(toReceive.getStack()).getCount() / toReceive.getStack().getCount();\n\n                if (tempQuantityFinished > ratioReceived) {\n                    tempQuantityFinished = ratioReceived;\n                }\n            } else {\n                tempQuantityFinished = 0;\n            }\n        }\n\n        for (StackListEntry<FluidStack> toReceive : singleFluidSetToReceive.getStacks()) {\n            if (fluidsReceived.get(toReceive.getStack()) != null) {\n                int ratioReceived = fluidsReceived.get(toReceive.getStack()).getAmount() / toReceive.getStack().getAmount();\n\n                if (tempQuantityFinished > ratioReceived) {\n                    tempQuantityFinished = ratioReceived;\n                }\n            } else {\n                tempQuantityFinished = 0;\n            }\n        }\n\n        this.quantityFinished = tempQuantityFinished;\n    }\n\n    @Override\n    public void onCalculationFinished() {\n        super.onCalculationFinished();\n\n        this.singleItemSetToRequire = new ItemStackList(requirements.getSingleItemRequirementSet(true));\n        this.singleFluidSetToRequire = new FluidStackList(requirements.getSingleFluidRequirementSet(true));\n    }\n\n    @Override\n    public CompoundTag writeToNbt() {\n        CompoundTag tag = super.writeToNbt();\n\n        tag.put(NBT_ITEMS_RECEIVED, SerializationUtil.writeItemStackList(itemsReceived));\n        tag.put(NBT_FLUIDS_RECEIVED, SerializationUtil.writeFluidStackList(fluidsReceived));\n\n        tag.put(NBT_SINGLE_ITEM_SET_TO_REQUIRE, SerializationUtil.writeItemStackList(singleItemSetToRequire));\n        tag.put(NBT_SINGLE_FLUID_SET_TO_REQUIRE, SerializationUtil.writeFluidStackList(singleFluidSetToRequire));\n\n        tag.putInt(NBT_STATE, state.ordinal());\n\n        return tag;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/node/ProcessingState.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node;\n\npublic enum ProcessingState {\n    READY,\n    MACHINE_NONE,\n    MACHINE_DOES_NOT_ACCEPT,\n    PROCESSED,\n    LOCKED\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/preview/CraftingPreviewElementFactory.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.preview;\n\nimport com.google.common.collect.ImmutableList;\nimport com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;\nimport com.refinedmods.refinedstorage.api.util.StackListEntry;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.FluidCraftingPreviewElement;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.ItemCraftingPreviewElement;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport java.util.ArrayList;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class CraftingPreviewElementFactory {\n    public List<ICraftingPreviewElement> getElements(CraftingPreviewInfo info) {\n        Map<Integer, ItemCraftingPreviewElement> map = new LinkedHashMap<>();\n        Map<Integer, FluidCraftingPreviewElement> mapFluids = new LinkedHashMap<>();\n\n        for (StackListEntry<ItemStack> stack : info.getMissing().getStacks()) {\n            int hash = API.instance().getItemStackHashCode(stack.getStack());\n\n            ItemCraftingPreviewElement previewStack = map.computeIfAbsent(hash, key -> new ItemCraftingPreviewElement(stack.getStack()));\n            previewStack.setMissing(true);\n            previewStack.addToCraft(stack.getStack().getCount());\n        }\n\n        for (StackListEntry<FluidStack> stack : info.getMissingFluids().getStacks()) {\n            int hash = API.instance().getFluidStackHashCode(stack.getStack());\n\n            FluidCraftingPreviewElement previewStack = mapFluids.computeIfAbsent(hash, key -> new FluidCraftingPreviewElement(stack.getStack()));\n            previewStack.setMissing(true);\n            previewStack.addToCraft(stack.getStack().getAmount());\n        }\n\n        for (ItemStack stack : ImmutableList.copyOf(info.getToCraft()).reverse()) {\n            int hash = API.instance().getItemStackHashCode(stack);\n\n            ItemCraftingPreviewElement previewStack = map.computeIfAbsent(hash, key -> new ItemCraftingPreviewElement(stack));\n            previewStack.addToCraft(stack.getCount());\n        }\n\n        for (FluidStack stack : ImmutableList.copyOf(info.getToCraftFluids()).reverse()) {\n            int hash = API.instance().getFluidStackHashCode(stack);\n\n            FluidCraftingPreviewElement previewStack = mapFluids.computeIfAbsent(hash, key -> new FluidCraftingPreviewElement(stack));\n            previewStack.addToCraft(stack.getAmount());\n        }\n\n        for (StackListEntry<ItemStack> stack : info.getToTake().getStacks()) {\n            int hash = API.instance().getItemStackHashCode(stack.getStack());\n\n            ItemCraftingPreviewElement previewStack = map.computeIfAbsent(hash, key -> new ItemCraftingPreviewElement(stack.getStack()));\n            previewStack.addAvailable(stack.getStack().getCount());\n        }\n\n        for (StackListEntry<FluidStack> stack : info.getToTakeFluids().getStacks()) {\n            int hash = API.instance().getFluidStackHashCode(stack.getStack());\n\n            FluidCraftingPreviewElement previewStack = mapFluids.computeIfAbsent(hash, key -> new FluidCraftingPreviewElement(stack.getStack()));\n            previewStack.addAvailable(stack.getStack().getAmount());\n        }\n\n        List<ICraftingPreviewElement> elements = new ArrayList<>();\n\n        elements.addAll(map.values());\n        elements.addAll(mapFluids.values());\n\n        return elements;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/preview/CraftingPreviewInfo.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.preview;\n\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class CraftingPreviewInfo {\n    private final IStackList<ItemStack> missing = API.instance().createItemStackList();\n    private final IStackList<FluidStack> missingFluids = API.instance().createFluidStackList();\n\n    private final IStackList<ItemStack> toTake = API.instance().createItemStackList();\n    private final IStackList<FluidStack> toTakeFluids = API.instance().createFluidStackList();\n\n    private final List<ItemStack> toCraft = new ArrayList<>();\n    private final List<FluidStack> toCraftFluids = new ArrayList<>();\n\n    public IStackList<ItemStack> getMissing() {\n        return missing;\n    }\n\n    public IStackList<FluidStack> getMissingFluids() {\n        return missingFluids;\n    }\n\n    public boolean hasMissing() {\n        return !missing.isEmpty() || !missingFluids.isEmpty();\n    }\n\n    public IStackList<ItemStack> getToTake() {\n        return toTake;\n    }\n\n    public IStackList<FluidStack> getToTakeFluids() {\n        return toTakeFluids;\n    }\n\n    public List<ItemStack> getToCraft() {\n        return toCraft;\n    }\n\n    public List<FluidStack> getToCraftFluids() {\n        return toCraftFluids;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/Network.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.INetworkNodeGraph;\nimport com.refinedmods.refinedstorage.api.network.INetworkNodeGraphEntry;\nimport com.refinedmods.refinedstorage.api.network.NetworkType;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler;\nimport com.refinedmods.refinedstorage.api.network.item.INetworkItemManager;\nimport com.refinedmods.refinedstorage.api.network.security.ISecurityManager;\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.IStorage;\nimport com.refinedmods.refinedstorage.api.storage.StorageType;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;\nimport com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorage;\nimport com.refinedmods.refinedstorage.api.storage.tracker.IStorageTracker;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.CraftingManager;\nimport com.refinedmods.refinedstorage.apiimpl.network.grid.handler.FluidGridHandler;\nimport com.refinedmods.refinedstorage.apiimpl.network.grid.handler.ItemGridHandler;\nimport com.refinedmods.refinedstorage.apiimpl.network.item.NetworkItemManager;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.RootNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.security.SecurityManager;\nimport com.refinedmods.refinedstorage.apiimpl.storage.cache.FluidStorageCache;\nimport com.refinedmods.refinedstorage.apiimpl.storage.cache.ItemStorageCache;\nimport com.refinedmods.refinedstorage.apiimpl.storage.tracker.FluidStorageTracker;\nimport com.refinedmods.refinedstorage.apiimpl.storage.tracker.ItemStorageTracker;\nimport com.refinedmods.refinedstorage.block.ControllerBlock;\nimport com.refinedmods.refinedstorage.energy.BaseEnergyStorage;\nimport com.refinedmods.refinedstorage.blockentity.ControllerBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IRedstoneConfigurable;\nimport com.refinedmods.refinedstorage.blockentity.config.RedstoneMode;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.Util;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.energy.IEnergyStorage;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\n\nimport javax.annotation.Nonnull;\nimport java.util.UUID;\nimport java.util.function.Predicate;\n\npublic class Network implements INetwork, IRedstoneConfigurable {\n    private static final int THROTTLE_INACTIVE_TO_ACTIVE = 20;\n    private static final int THROTTLE_ACTIVE_TO_INACTIVE = 4;\n    private static final int THROTTLE_ENERGY_TYPE_CHANGE = 20;\n\n    private static final String NBT_ENERGY = \"Energy\";\n    private static final String NBT_ITEM_STORAGE_TRACKER_ID = \"ItemStorageTrackerId\";\n    private static final String NBT_FLUID_STORAGE_TRACKER_ID = \"FluidStorageTrackerId\";\n\n    private static final Logger LOGGER = LogManager.getLogger(Network.class);\n\n    private final IItemGridHandler itemGridHandler = new ItemGridHandler(this);\n    private final IFluidGridHandler fluidGridHandler = new FluidGridHandler(this);\n    private final INetworkItemManager networkItemManager = new NetworkItemManager(this);\n    private final INetworkNodeGraph nodeGraph = new NetworkNodeGraph(this);\n    private final ICraftingManager craftingManager = new CraftingManager(this);\n    private final ISecurityManager securityManager = new SecurityManager(this);\n    private final IStorageCache<ItemStack> itemStorage = new ItemStorageCache(this);\n    private final IStorageCache<FluidStack> fluidStorage = new FluidStorageCache(this);\n    private final BaseEnergyStorage energy = new BaseEnergyStorage(RS.SERVER_CONFIG.getController().getCapacity(), RS.SERVER_CONFIG.getController().getMaxTransfer(), 0);\n    private final RootNetworkNode root;\n    private final BlockPos pos;\n    private final Level level;\n    private final NetworkType type;\n    private ItemStorageTracker itemStorageTracker;\n    private UUID itemStorageTrackerId;\n    private FluidStorageTracker fluidStorageTracker;\n    private UUID fluidStorageTrackerId;\n    private ControllerBlock.EnergyType lastEnergyType = ControllerBlock.EnergyType.OFF;\n    private int lastEnergyUsage;\n    private RedstoneMode redstoneMode = RedstoneMode.IGNORE;\n    private boolean redstonePowered = false;\n\n    private boolean amILoaded = false;\n    private boolean throttlingDisabled = true; // Will be enabled after first update\n    private boolean couldRun;\n    private int ticksSinceUpdateChanged;\n    private int ticksSinceEnergyTypeChanged;\n    private int ticks;\n    private long[] tickTimes = new long[100];\n    private int tickCounter = 0;\n\n    public Network(Level level, BlockPos pos, NetworkType type) {\n        this.pos = pos;\n        this.level = level;\n        this.type = type;\n        this.root = new RootNetworkNode(this, level, pos);\n        this.nodeGraph.addListener(() -> {\n            if (!level.isLoaded(pos)) {\n                return;\n            }\n            BlockEntity blockEntity = level.getBlockEntity(pos);\n            if (blockEntity instanceof ControllerBlockEntity) {\n                ((ControllerBlockEntity) blockEntity).getDataManager().sendParameterToWatchers(ControllerBlockEntity.NODES);\n            }\n        });\n    }\n\n    public static int getEnergyScaled(int stored, int capacity, int scale) {\n        return (int) ((float) stored / (float) capacity * (float) scale);\n    }\n\n    public static ControllerBlock.EnergyType getEnergyType(int stored, int capacity) {\n        int energy = getEnergyScaled(stored, capacity, 100);\n\n        if (energy <= 0) {\n            return ControllerBlock.EnergyType.OFF;\n        } else if (energy <= 10) {\n            return ControllerBlock.EnergyType.NEARLY_OFF;\n        } else if (energy <= 20) {\n            return ControllerBlock.EnergyType.NEARLY_ON;\n        }\n\n        return ControllerBlock.EnergyType.ON;\n    }\n\n    public RootNetworkNode getRoot() {\n        return root;\n    }\n\n    @Override\n    public BlockPos getPosition() {\n        return pos;\n    }\n\n    @Override\n    public boolean canRun() {\n        return amILoaded && energy.getEnergyStored() >= getEnergyUsage() && redstoneMode.isEnabled(redstonePowered);\n    }\n\n    public void setRedstonePowered(boolean redstonePowered) {\n        this.redstonePowered = redstonePowered;\n    }\n\n    @Override\n    public INetworkNodeGraph getNodeGraph() {\n        return nodeGraph;\n    }\n\n    @Override\n    public ISecurityManager getSecurityManager() {\n        return securityManager;\n    }\n\n    @Override\n    public ICraftingManager getCraftingManager() {\n        return craftingManager;\n    }\n\n    @Override\n    public void update() {\n        if (!level.isClientSide) {\n            long tickStart = Util.getNanos();\n\n            if (ticks == 0) {\n                redstonePowered = level.hasNeighborSignal(pos);\n            }\n\n            ++ticks;\n\n            amILoaded = level.isLoaded(pos);\n\n            updateEnergyUsage();\n\n            if (canRun()) {\n                craftingManager.update();\n\n                if (!craftingManager.getTasks().isEmpty()) {\n                    markDirty();\n                }\n            }\n\n            if (type == NetworkType.NORMAL) {\n                if (!RS.SERVER_CONFIG.getController().getUseEnergy()) {\n                    energy.setStored(this.energy.getMaxEnergyStored());\n                } else {\n                    energy.extractEnergyBypassCanExtract(getEnergyUsage(), false);\n                }\n            } else if (type == NetworkType.CREATIVE) {\n                energy.setStored(energy.getMaxEnergyStored());\n            }\n\n            boolean canRun = canRun();\n\n            if (couldRun != canRun) {\n                ++ticksSinceUpdateChanged;\n\n                if ((canRun ? (ticksSinceUpdateChanged > THROTTLE_INACTIVE_TO_ACTIVE) : (ticksSinceUpdateChanged > THROTTLE_ACTIVE_TO_INACTIVE)) || throttlingDisabled) {\n                    ticksSinceUpdateChanged = 0;\n                    couldRun = canRun;\n                    throttlingDisabled = false;\n\n                    LOGGER.debug(\"Network at position {} changed running state to {}, causing an invalidation of the node graph\", pos, couldRun);\n\n                    nodeGraph.invalidate(Action.PERFORM, level, pos);\n                    securityManager.invalidate();\n                }\n            } else {\n                ticksSinceUpdateChanged = 0;\n            }\n\n            ControllerBlock.EnergyType energyType = getEnergyType();\n\n            if (lastEnergyType != energyType) {\n                ++ticksSinceEnergyTypeChanged;\n                if (ticksSinceEnergyTypeChanged > THROTTLE_ENERGY_TYPE_CHANGE) {\n                    lastEnergyType = energyType;\n                    BlockState state = level.getBlockState(pos);\n                    if (state.getBlock() instanceof ControllerBlock) {\n                        level.setBlockAndUpdate(pos, state.setValue(ControllerBlock.ENERGY_TYPE, energyType));\n                    }\n                }\n            } else {\n                ticksSinceEnergyTypeChanged = 0;\n            }\n\n            tickTimes[tickCounter % tickTimes.length] = Util.getNanos() - tickStart;\n            tickCounter++;\n        }\n    }\n\n    @Override\n    public IItemGridHandler getItemGridHandler() {\n        return itemGridHandler;\n    }\n\n    @Override\n    public IFluidGridHandler getFluidGridHandler() {\n        return fluidGridHandler;\n    }\n\n    @Override\n    public INetworkItemManager getNetworkItemManager() {\n        return networkItemManager;\n    }\n\n    @Override\n    public void onRemoved() {\n        for (ICraftingTask task : craftingManager.getTasks()) {\n            task.onCancelled();\n        }\n\n        nodeGraph.disconnectAll();\n        API.instance().getStorageTrackerManager((ServerLevel) getLevel()).remove(itemStorageTrackerId);\n        API.instance().getStorageTrackerManager((ServerLevel) getLevel()).remove(fluidStorageTrackerId);\n    }\n\n    @Override\n    public IStorageCache<ItemStack> getItemStorageCache() {\n        return itemStorage;\n    }\n\n    @Override\n    public IStorageCache<FluidStack> getFluidStorageCache() {\n        return fluidStorage;\n    }\n\n    @Override\n    @Nonnull\n    public ItemStack insertItem(@Nonnull ItemStack stack, int size, Action action) {\n        if (stack.isEmpty()) {\n            return stack;\n        }\n\n        if (itemStorage.getStorages().isEmpty()) {\n            return ItemHandlerHelper.copyStackWithSize(stack, size);\n        }\n\n        ItemStack remainder = ItemHandlerHelper.copyStackWithSize(stack, size);\n\n        int inserted = 0;\n        int insertedExternally = 0;\n\n        for (IStorage<ItemStack> storage : this.itemStorage.getStorages()) {\n            if (storage.getAccessType() == AccessType.EXTRACT) {\n                continue;\n            }\n\n            int storedPre = storage.getStored();\n\n            remainder = storage.insert(remainder, size, action);\n\n            if (action == Action.PERFORM) {\n                inserted += storage.getCacheDelta(storedPre, size, remainder);\n            }\n\n            if (remainder.isEmpty()) {\n                // The external storage is responsible for sending changes, we don't need to anymore\n                if (storage instanceof IExternalStorage && action == Action.PERFORM) {\n                    ((IExternalStorage) storage).update(this);\n\n                    insertedExternally += size;\n                }\n\n                break;\n            } else {\n                // The external storage is responsible for sending changes, we don't need to anymore\n                if (size != remainder.getCount() && storage instanceof IExternalStorage && action == Action.PERFORM) {\n                    ((IExternalStorage) storage).update(this);\n\n                    insertedExternally += size - remainder.getCount();\n                }\n\n                size = remainder.getCount();\n            }\n        }\n\n        if (action == Action.PERFORM && inserted - insertedExternally > 0) {\n            itemStorage.add(stack, inserted - insertedExternally, false, false);\n        }\n\n        return remainder;\n    }\n\n    @Override\n    @Nonnull\n    public ItemStack extractItem(@Nonnull ItemStack stack, int size, int flags, Action action, Predicate<IStorage<ItemStack>> filter) {\n        if (stack.isEmpty()) {\n            return stack;\n        }\n\n        int requested = size;\n        int received = 0;\n\n        int extractedExternally = 0;\n\n        ItemStack newStack = ItemStack.EMPTY;\n\n        for (IStorage<ItemStack> storage : this.itemStorage.getStorages()) {\n            ItemStack took = ItemStack.EMPTY;\n\n            if (filter.test(storage) && storage.getAccessType() != AccessType.INSERT) {\n                took = storage.extract(stack, requested - received, flags, action);\n            }\n\n            if (!took.isEmpty()) {\n                // The external storage is responsible for sending changes, we don't need to anymore\n                if (storage instanceof IExternalStorage && action == Action.PERFORM) {\n                    ((IExternalStorage) storage).update(this);\n\n                    extractedExternally += took.getCount();\n                }\n\n                if (newStack.isEmpty()) {\n                    newStack = took;\n                } else {\n                    newStack.grow(took.getCount());\n                }\n\n                received += took.getCount();\n            }\n\n            if (requested == received) {\n                break;\n            }\n        }\n\n        if (newStack.getCount() - extractedExternally > 0 && action == Action.PERFORM) {\n            itemStorage.remove(newStack, newStack.getCount() - extractedExternally, false);\n        }\n\n        return newStack;\n    }\n\n    @Override\n    @Nonnull\n    public FluidStack insertFluid(@Nonnull FluidStack stack, int size, Action action) {\n        if (stack.isEmpty()) {\n            return stack;\n        }\n\n        if (fluidStorage.getStorages().isEmpty()) {\n            return StackUtils.copy(stack, size);\n        }\n\n        FluidStack remainder = StackUtils.copy(stack, size);\n\n        int inserted = 0;\n        int insertedExternally = 0;\n\n        for (IStorage<FluidStack> storage : this.fluidStorage.getStorages()) {\n            if (storage.getAccessType() == AccessType.EXTRACT) {\n                continue;\n            }\n\n            int storedPre = storage.getStored();\n\n            remainder = storage.insert(remainder, size, action);\n\n            if (action == Action.PERFORM) {\n                inserted += storage.getCacheDelta(storedPre, size, remainder);\n            }\n\n            if (remainder.isEmpty()) {\n                // The external storage is responsible for sending changes, we don't need to anymore\n                if (storage instanceof IExternalStorage && action == Action.PERFORM) {\n                    ((IExternalStorage) storage).update(this);\n\n                    insertedExternally += size;\n                }\n\n                break;\n            } else {\n                // The external storage is responsible for sending changes, we don't need to anymore\n                if (size != remainder.getAmount() && storage instanceof IExternalStorage && action == Action.PERFORM) {\n                    ((IExternalStorage) storage).update(this);\n\n                    insertedExternally += size - remainder.getAmount();\n                }\n\n                size = remainder.getAmount();\n            }\n        }\n\n        if (action == Action.PERFORM && inserted - insertedExternally > 0) {\n            fluidStorage.add(stack, inserted - insertedExternally, false, false);\n        }\n\n        return remainder;\n    }\n\n    @Override\n    @Nonnull\n    public FluidStack extractFluid(@Nonnull FluidStack stack, int size, int flags, Action action, Predicate<IStorage<FluidStack>> filter) {\n        if (stack.isEmpty()) {\n            return stack;\n        }\n\n        int requested = size;\n        int received = 0;\n\n        int extractedExternally = 0;\n\n        FluidStack newStack = FluidStack.EMPTY;\n\n        for (IStorage<FluidStack> storage : this.fluidStorage.getStorages()) {\n            FluidStack took = FluidStack.EMPTY;\n\n            if (filter.test(storage) && storage.getAccessType() != AccessType.INSERT) {\n                took = storage.extract(stack, requested - received, flags, action);\n            }\n\n            if (!took.isEmpty()) {\n                // The external storage is responsible for sending changes, we don't need to anymore\n                if (storage instanceof IExternalStorage && action == Action.PERFORM) {\n                    ((IExternalStorage) storage).update(this);\n\n                    extractedExternally += took.getAmount();\n                }\n\n                if (newStack.isEmpty()) {\n                    newStack = took;\n                } else {\n                    newStack.grow(took.getAmount());\n                }\n\n                received += took.getAmount();\n            }\n\n            if (requested == received) {\n                break;\n            }\n        }\n\n        if (newStack.getAmount() - extractedExternally > 0 && action == Action.PERFORM) {\n            fluidStorage.remove(newStack, newStack.getAmount() - extractedExternally, false);\n        }\n\n        return newStack;\n    }\n\n    @Override\n    public IStorageTracker<ItemStack> getItemStorageTracker() {\n        if (itemStorageTracker == null) {\n            if (itemStorageTrackerId == null) {\n                this.itemStorageTrackerId = UUID.randomUUID();\n            }\n\n            this.itemStorageTracker = (ItemStorageTracker) API.instance().getStorageTrackerManager((ServerLevel) level).getOrCreate(itemStorageTrackerId, StorageType.ITEM);\n        }\n\n        return itemStorageTracker;\n    }\n\n    @Override\n    public IStorageTracker<FluidStack> getFluidStorageTracker() {\n        if (fluidStorageTracker == null) {\n            if (fluidStorageTrackerId == null) {\n                this.fluidStorageTrackerId = UUID.randomUUID();\n            }\n\n            this.fluidStorageTracker = (FluidStorageTracker) API.instance().getStorageTrackerManager((ServerLevel) level).getOrCreate(fluidStorageTrackerId, StorageType.FLUID);\n        }\n\n        return fluidStorageTracker;\n    }\n\n    @Override\n    public Level getLevel() {\n        return level;\n    }\n\n    @Override\n    public INetwork readFromNbt(CompoundTag tag) {\n        if (tag.contains(NBT_ENERGY)) {\n            this.energy.setStored(tag.getInt(NBT_ENERGY));\n        }\n\n        redstoneMode = RedstoneMode.read(tag);\n\n        craftingManager.readFromNbt(tag);\n\n        if (tag.contains(NBT_ITEM_STORAGE_TRACKER_ID)) {\n            this.itemStorageTrackerId = tag.getUUID(NBT_ITEM_STORAGE_TRACKER_ID);\n        }\n\n        if (tag.contains(NBT_FLUID_STORAGE_TRACKER_ID)) {\n            this.fluidStorageTrackerId = tag.getUUID(NBT_FLUID_STORAGE_TRACKER_ID);\n        }\n\n        return this;\n    }\n\n    @Override\n    public CompoundTag writeToNbt(CompoundTag tag) {\n        tag.putInt(NBT_ENERGY, this.energy.getEnergyStored());\n\n        redstoneMode.write(tag);\n\n        craftingManager.writeToNbt(tag);\n        if (itemStorageTrackerId != null) {\n            tag.putUUID(NBT_ITEM_STORAGE_TRACKER_ID, itemStorageTrackerId);\n        }\n\n        if (fluidStorageTrackerId != null) {\n            tag.putUUID(NBT_FLUID_STORAGE_TRACKER_ID, fluidStorageTrackerId);\n        }\n\n        return tag;\n    }\n\n    @Override\n    public long[] getTickTimes() {\n        return tickTimes;\n    }\n\n    @Override\n    public void markDirty() {\n        API.instance().getNetworkManager((ServerLevel) level).markForSaving();\n    }\n\n    public ControllerBlock.EnergyType getEnergyType() {\n        if (!redstoneMode.isEnabled(redstonePowered)) {\n            return ControllerBlock.EnergyType.OFF;\n        }\n\n        return getEnergyType(this.energy.getEnergyStored(), this.energy.getMaxEnergyStored());\n    }\n\n    @Override\n    public RedstoneMode getRedstoneMode() {\n        return redstoneMode;\n    }\n\n    @Override\n    public void setRedstoneMode(RedstoneMode mode) {\n        this.redstoneMode = mode;\n\n        markDirty();\n    }\n\n    private void updateEnergyUsage() {\n        if (!redstoneMode.isEnabled(redstonePowered)) {\n            this.lastEnergyUsage = 0;\n            return;\n        }\n\n        int usage = RS.SERVER_CONFIG.getController().getBaseUsage();\n\n        for (INetworkNodeGraphEntry entry : nodeGraph.all()) {\n            if (entry.getNode().isActive()) {\n                usage += entry.getNode().getEnergyUsage();\n            }\n        }\n\n        this.lastEnergyUsage = usage;\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        return lastEnergyUsage;\n    }\n\n    @Override\n    public IEnergyStorage getEnergyStorage() {\n        return energy;\n    }\n\n    @Override\n    public NetworkType getType() {\n        return type;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkListener.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network;\n\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport net.minecraft.server.level.ServerLevel;\nimport net.neoforged.bus.api.SubscribeEvent;\nimport net.neoforged.neoforge.event.TickEvent;\n\npublic class NetworkListener {\n    @SubscribeEvent\n    public void onLevelTick(TickEvent.LevelTickEvent e) {\n        if (!e.level.isClientSide() && e.phase == TickEvent.Phase.END) {\n            e.level.getProfiler().push(\"network ticking\");\n\n            for (INetwork network : API.instance().getNetworkManager((ServerLevel) e.level).all()) {\n                network.update();\n            }\n\n            e.level.getProfiler().pop();\n\n            e.level.getProfiler().push(\"network node ticking\");\n\n            for (INetworkNode node : API.instance().getNetworkNodeManager((ServerLevel) e.level).all()) {\n                node.update();\n            }\n\n            e.level.getProfiler().pop();\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkManager.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network;\n\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.INetworkManager;\nimport com.refinedmods.refinedstorage.api.network.NetworkType;\nimport com.refinedmods.refinedstorage.apiimpl.util.RSSavedData;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.nbt.Tag;\nimport net.minecraft.world.level.Level;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\n\nimport javax.annotation.Nullable;\nimport java.util.Collection;\nimport java.util.concurrent.ConcurrentHashMap;\n\npublic class NetworkManager extends RSSavedData implements INetworkManager {\n    public static final String NAME = \"refinedstorage_networks\";\n\n    private static final String NBT_NETWORKS = \"Networks\";\n    private static final String NBT_TYPE = \"Type\";\n    private static final String NBT_DATA = \"Data\";\n    private static final String NBT_POS = \"Pos\";\n\n    private final Level level;\n\n    private final Logger logger = LogManager.getLogger(getClass());\n\n    private final ConcurrentHashMap<BlockPos, INetwork> networks = new ConcurrentHashMap<>();\n\n    public NetworkManager(Level level) {\n        this.level = level;\n    }\n\n    @Override\n    public void load(CompoundTag tag) {\n        if (tag.contains(NBT_NETWORKS)) {\n            ListTag networksTag = tag.getList(NBT_NETWORKS, Tag.TAG_COMPOUND);\n\n            this.networks.clear();\n\n            for (int i = 0; i < networksTag.size(); ++i) {\n                CompoundTag networkTag = networksTag.getCompound(i);\n\n                CompoundTag data = networkTag.getCompound(NBT_DATA);\n                BlockPos pos = BlockPos.of(networkTag.getLong(NBT_POS));\n                int type = networkTag.getInt(NBT_TYPE);\n\n                INetwork network = new Network(level, pos, NetworkType.values()[type]);\n\n                try {\n                    network = network.readFromNbt(data);\n                } catch (Throwable t) {\n                    logger.error(\"Error while reading network\", t);\n                }\n\n                this.networks.put(pos, network);\n            }\n        }\n    }\n\n    @Override\n    public CompoundTag save(CompoundTag tag) {\n        ListTag list = new ListTag();\n\n        for (INetwork network : all()) {\n            try {\n                CompoundTag networkTag = new CompoundTag();\n\n                networkTag.putLong(NBT_POS, network.getPosition().asLong());\n                networkTag.put(NBT_DATA, network.writeToNbt(new CompoundTag()));\n                networkTag.putInt(NBT_TYPE, network.getType().ordinal());\n\n                list.add(networkTag);\n            } catch (Throwable t) {\n                logger.error(\"Error while saving network\", t);\n            }\n        }\n\n        tag.put(NBT_NETWORKS, list);\n\n        return tag;\n    }\n\n    @Nullable\n    @Override\n    public INetwork getNetwork(BlockPos pos) {\n        return networks.get(pos);\n    }\n\n    @Override\n    public void removeNetwork(BlockPos pos) {\n        if (pos == null) {\n            throw new IllegalArgumentException(\"Position cannot be null\");\n        }\n\n        networks.remove(pos);\n    }\n\n    @Override\n    public void setNetwork(BlockPos pos, INetwork network) {\n        if (pos == null) {\n            throw new IllegalArgumentException(\"Position cannot be null\");\n        }\n\n        if (network == null) {\n            throw new IllegalArgumentException(\"Network cannot be null\");\n        }\n\n        networks.put(pos, network);\n    }\n\n    @Override\n    public Collection<INetwork> all() {\n        return networks.values();\n    }\n\n    @Override\n    public void markForSaving() {\n        setDirty();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkNodeGraph.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network;\n\nimport com.google.common.collect.Sets;\nimport com.refinedmods.refinedstorage.api.network.*;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.Block;\nimport net.minecraft.world.level.block.entity.BlockEntity;\n\nimport javax.annotation.Nullable;\nimport java.util.*;\nimport java.util.function.Consumer;\n\npublic class NetworkNodeGraph implements INetworkNodeGraph {\n    private final INetwork network;\n    private final List<INetworkNodeGraphListener> listeners = new LinkedList<>();\n    private final Set<Consumer<INetwork>> actions = new HashSet<>();\n    private Set<INetworkNodeGraphEntry> entries = Sets.newConcurrentHashSet();\n    private boolean invalidating = false;\n\n    public NetworkNodeGraph(INetwork network) {\n        this.network = network;\n    }\n\n    @Override\n    public void invalidate(Action action, Level level, BlockPos origin) {\n        this.invalidating = true;\n\n        Operator operator = new Operator(action);\n\n        INetworkNode originNode = NetworkUtils.getNodeFromBlockEntity(level.getBlockEntity(origin));\n        if (originNode instanceof INetworkNodeVisitor) {\n            ((INetworkNodeVisitor) originNode).visit(operator);\n        }\n\n        Visitor currentVisitor;\n        while ((currentVisitor = operator.toCheck.poll()) != null) {\n            currentVisitor.visit(operator);\n        }\n\n        this.entries = operator.foundNodes;\n\n        if (action == Action.PERFORM) {\n            for (INetworkNodeGraphEntry entry : operator.newEntries) {\n                entry.getNode().onConnected(network);\n            }\n\n            for (INetworkNodeGraphEntry entry : operator.previousEntries) {\n                entry.getNode().onDisconnected(network);\n            }\n\n            actions.forEach(h -> h.accept(network));\n            actions.clear();\n\n            if (!operator.newEntries.isEmpty() || !operator.previousEntries.isEmpty()) {\n                listeners.forEach(INetworkNodeGraphListener::onChanged);\n            }\n        }\n\n        this.invalidating = false;\n    }\n\n    @Override\n    public void runActionWhenPossible(Consumer<INetwork> handler) {\n        if (invalidating) {\n            actions.add(handler);\n        } else {\n            handler.accept(network);\n        }\n    }\n\n    @Override\n    public Collection<INetworkNodeGraphEntry> all() {\n        return entries;\n    }\n\n    @Override\n    public void addListener(INetworkNodeGraphListener listener) {\n        listeners.add(listener);\n    }\n\n    @Override\n    public void disconnectAll() {\n        entries.forEach(entry -> entry.getNode().onDisconnected(network));\n        entries.clear();\n\n        listeners.forEach(INetworkNodeGraphListener::onChanged);\n    }\n\n    protected Level getLevel() {\n        return network.getLevel();\n    }\n\n    private static class Visitor implements INetworkNodeVisitor {\n        private final INetworkNode node;\n        private final Level level;\n        private final BlockPos pos;\n        private final Direction side;\n        private final BlockEntity blockEntity;\n\n        Visitor(INetworkNode node, Level level, BlockPos pos, Direction side, BlockEntity blockEntity) {\n            this.node = node;\n            this.level = level;\n            this.pos = pos;\n            this.side = side;\n            this.blockEntity = blockEntity;\n        }\n\n        @Override\n        public void visit(com.refinedmods.refinedstorage.api.network.INetworkNodeVisitor.Operator operator) {\n            if (node instanceof INetworkNodeVisitor) {\n                ((INetworkNodeVisitor) node).visit(operator);\n            } else {\n                for (Direction checkSide : Direction.values()) {\n                    if (checkSide != side) { // Avoid going backward\n                        INetworkNode nodeOnSide = NetworkUtils.getNodeFromBlockEntity(blockEntity);\n                        if (nodeOnSide == node) {\n                            BlockPos relativePos = pos.relative(checkSide);\n                            if (level.isLoaded(relativePos)) {\n                                operator.apply(level, relativePos, checkSide.getOpposite());\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    private class Operator implements INetworkNodeVisitor.Operator {\n        private final Set<INetworkNodeGraphEntry> foundNodes = Sets.newConcurrentHashSet(); // All scanned entries\n\n        private final Set<INetworkNodeGraphEntry> newEntries = Sets.newConcurrentHashSet(); // All scanned new entries, that didn't appear in the list before\n        private final Set<INetworkNodeGraphEntry> previousEntries = Sets.newConcurrentHashSet(entries); // All unscanned entries (entries that were in the previous list, but not in the new list)\n\n        private final Queue<Visitor> toCheck = new ArrayDeque<>();\n\n        private final Action action;\n\n        public Operator(Action action) {\n            this.action = action;\n        }\n\n        @Override\n        public void apply(Level level, BlockPos pos, @Nullable Direction side) {\n            BlockEntity blockEntity = level.getBlockEntity(pos);\n\n            INetworkNode otherNode = NetworkUtils.getNodeFromBlockEntity(blockEntity);\n            if (otherNode != null) {\n                NetworkNodeGraphEntry otherNodeItem = new NetworkNodeGraphEntry(otherNode);\n\n                if (otherNode.getNetwork() != null && !otherNode.getNetwork().equals(network)) {\n                    if (action == Action.PERFORM) {\n                        dropConflictingBlock(level, pos);\n                    }\n\n                    return;\n                }\n\n                if (foundNodes.add(otherNodeItem)) {\n                    if (!entries.contains(otherNodeItem)) {\n                        // We can't let the node connect immediately\n                        // We can only let the node connect AFTER the nodes list has changed in the graph\n                        // This is so that storage nodes can refresh the item/fluid cache, and the item/fluid cache will notice it then (otherwise not)\n                        newEntries.add(otherNodeItem);\n                    }\n\n                    previousEntries.remove(otherNodeItem);\n\n                    toCheck.add(new Visitor(otherNode, level, pos, side, blockEntity));\n                }\n            }\n        }\n\n        private void dropConflictingBlock(Level level, BlockPos pos) {\n            if (!network.getPosition().equals(pos)) {\n                Block.dropResources(level.getBlockState(pos), level, pos, level.getBlockEntity(pos));\n                level.removeBlock(pos, false);\n            }\n        }\n\n        @Override\n        public Action getAction() {\n            return action;\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkNodeGraphEntry.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network;\n\nimport com.refinedmods.refinedstorage.api.network.INetworkNodeGraphEntry;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\n\npublic class NetworkNodeGraphEntry implements INetworkNodeGraphEntry {\n    private final INetworkNode node;\n\n    public NetworkNodeGraphEntry(INetworkNode node) {\n        this.node = node;\n    }\n\n    @Override\n    public INetworkNode getNode() {\n        return node;\n    }\n\n    @Override\n    public boolean equals(Object other) {\n        if (!(other instanceof NetworkNodeGraphEntry)) {\n            return false;\n        }\n        if (this == other) {\n            return true;\n        }\n\n        NetworkNodeGraphEntry otherItem = (NetworkNodeGraphEntry) other;\n\n        if (node.getLevel().dimension() != otherItem.node.getLevel().dimension()) {\n            return false;\n        }\n\n        return node.getPos().equals(otherItem.node.getPos());\n    }\n\n    @Override\n    public int hashCode() {\n        int result = node.getPos().hashCode();\n        result = 31 * result + node.getLevel().dimension().hashCode();\n        return result;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkNodeListener.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network;\n\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport com.refinedmods.refinedstorage.util.PlayerUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.level.LevelAccessor;\nimport net.neoforged.bus.api.SubscribeEvent;\nimport net.neoforged.neoforge.event.level.BlockEvent;\n\npublic class NetworkNodeListener {\n    @SubscribeEvent\n    public void onBlockPlace(BlockEvent.EntityPlaceEvent e) {\n        if (!e.getLevel().isClientSide() && e.getEntity() instanceof Player) {\n            Player player = (Player) e.getEntity();\n\n            INetworkNode placed = NetworkUtils.getNodeFromBlockEntity(e.getLevel().getBlockEntity(e.getPos()));\n\n            if (placed != null) {\n                for (Direction facing : Direction.values()) {\n                    INetworkNode node = NetworkUtils.getNodeFromBlockEntity(e.getLevel().getBlockEntity(e.getBlockSnapshot().getPos().relative(facing)));\n\n                    if (node != null && node.getNetwork() != null && !node.getNetwork().getSecurityManager().hasPermission(Permission.BUILD, player)) {\n                        LevelUtils.sendNoPermissionMessage(player);\n\n                        e.setCanceled(true);\n\n                        //Fixes desync as we do not cancel the event clientside\n                        PlayerUtils.updateHeldItems((ServerPlayer) player);\n\n                        return;\n                    }\n                }\n\n                discoverNode(e.getLevel(), e.getPos());\n\n                placed.setOwner(player.getGameProfile().getId());\n            }\n        }\n    }\n\n    private void discoverNode(LevelAccessor world, BlockPos pos) {\n        for (Direction facing : Direction.values()) {\n            INetworkNode node = NetworkUtils.getNodeFromBlockEntity(world.getBlockEntity(pos.relative(facing)));\n\n            if (node != null && node.getNetwork() != null) {\n                node.getNetwork().getNodeGraph().invalidate(Action.PERFORM, node.getNetwork().getLevel(), node.getNetwork().getPosition());\n\n                return;\n            }\n        }\n    }\n\n    @SubscribeEvent\n    public void onBlockBreak(BlockEvent.BreakEvent e) {\n        if (!e.getLevel().isClientSide()) {\n            INetworkNode node = NetworkUtils.getNodeFromBlockEntity(e.getLevel().getBlockEntity(e.getPos()));\n\n            if (node != null && node.getNetwork() != null && !node.getNetwork().getSecurityManager().hasPermission(Permission.BUILD, e.getPlayer())) {\n                LevelUtils.sendNoPermissionMessage(e.getPlayer());\n\n                e.setCanceled(true);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkNodeManager.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network;\n\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNodeFactory;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNodeManager;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.util.RSSavedData;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.nbt.Tag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\n\nimport javax.annotation.Nullable;\nimport java.util.Collection;\nimport java.util.concurrent.ConcurrentHashMap;\n\npublic class NetworkNodeManager extends RSSavedData implements INetworkNodeManager {\n    public static final String NAME = \"refinedstorage_nodes\";\n\n    private static final String NBT_NODES = \"Nodes\";\n    private static final String NBT_NODE_ID = \"Id\";\n    private static final String NBT_NODE_DATA = \"Data\";\n    private static final String NBT_NODE_POS = \"Pos\";\n\n    private final Level level;\n\n    private final Logger logger = LogManager.getLogger(getClass());\n\n    private final ConcurrentHashMap<BlockPos, INetworkNode> nodes = new ConcurrentHashMap<>();\n\n    public NetworkNodeManager(Level level) {\n        this.level = level;\n    }\n\n    @Override\n    public void load(CompoundTag tag) {\n        if (tag.contains(NBT_NODES)) {\n            ListTag nodesTag = tag.getList(NBT_NODES, Tag.TAG_COMPOUND);\n\n            this.nodes.clear();\n\n            for (int i = 0; i < nodesTag.size(); ++i) {\n                CompoundTag nodeTag = nodesTag.getCompound(i);\n\n                ResourceLocation id = new ResourceLocation(nodeTag.getString(NBT_NODE_ID));\n                CompoundTag data = nodeTag.getCompound(NBT_NODE_DATA);\n                BlockPos pos = BlockPos.of(nodeTag.getLong(NBT_NODE_POS));\n\n                INetworkNodeFactory factory = API.instance().getNetworkNodeRegistry().get(id);\n\n                if (factory != null) {\n                    INetworkNode node = null;\n\n                    try {\n                        node = factory.create(data, level, pos);\n                    } catch (Throwable t) {\n                        logger.error(\"Could not read network node\", t);\n                    }\n\n                    if (node != null) {\n                        this.nodes.put(pos, node);\n                    }\n                } else {\n                    logger.warn(\"Factory for {} not found in network node registry\", id);\n                }\n            }\n        }\n    }\n\n    @Override\n    public CompoundTag save(CompoundTag tag) {\n        ListTag list = new ListTag();\n\n        for (INetworkNode node : all()) {\n            try {\n                CompoundTag nodeTag = new CompoundTag();\n\n                nodeTag.putString(NBT_NODE_ID, node.getId().toString());\n                nodeTag.putLong(NBT_NODE_POS, node.getPos().asLong());\n                nodeTag.put(NBT_NODE_DATA, node.write(new CompoundTag()));\n\n                list.add(nodeTag);\n            } catch (Throwable t) {\n                logger.error(\"Error while saving network node\", t);\n            }\n        }\n\n        tag.put(NBT_NODES, list);\n\n        return tag;\n    }\n\n    @Nullable\n    @Override\n    public INetworkNode getNode(BlockPos pos) {\n        return nodes.get(pos);\n    }\n\n    @Override\n    public void removeNode(BlockPos pos) {\n        if (pos == null) {\n            throw new IllegalArgumentException(\"Position cannot be null\");\n        }\n\n        nodes.remove(pos);\n    }\n\n    @Override\n    public void setNode(BlockPos pos, INetworkNode node) {\n        if (pos == null) {\n            throw new IllegalArgumentException(\"Position cannot be null\");\n        }\n\n        if (node == null) {\n            throw new IllegalArgumentException(\"Node cannot be null\");\n        }\n\n        nodes.put(pos, node);\n    }\n\n    @Override\n    public Collection<INetworkNode> all() {\n        return nodes.values();\n    }\n\n    @Override\n    public void markForSaving() {\n        setDirty();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkNodeRegistry.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network;\n\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNodeFactory;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNodeRegistry;\nimport net.minecraft.resources.ResourceLocation;\n\nimport javax.annotation.Nullable;\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class NetworkNodeRegistry implements INetworkNodeRegistry {\n    private final Map<ResourceLocation, INetworkNodeFactory> factories = new HashMap<>();\n\n    @Override\n    public void add(ResourceLocation id, INetworkNodeFactory factory) {\n        factories.put(id, factory);\n    }\n\n    @Override\n    @Nullable\n    public INetworkNodeFactory get(ResourceLocation id) {\n        return factories.get(id);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/CraftingGridBehavior.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.grid;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternProvider;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.grid.GridType;\nimport com.refinedmods.refinedstorage.api.network.grid.ICraftingGridBehavior;\nimport com.refinedmods.refinedstorage.api.network.grid.INetworkAwareGrid;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode;\nimport com.refinedmods.refinedstorage.item.PatternItem;\nimport net.minecraft.core.NonNullList;\nimport net.minecraft.world.Containers;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.CraftingContainer;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.crafting.CraftingRecipe;\nimport net.neoforged.neoforge.common.CommonHooks;\nimport net.neoforged.neoforge.event.EventHooks;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\nimport net.neoforged.neoforge.items.wrapper.PlayerMainInvWrapper;\nimport javax.annotation.Nullable;\nimport java.util.*;\nimport java.util.concurrent.atomic.AtomicReference;\n\npublic class CraftingGridBehavior implements ICraftingGridBehavior {\n    @Override\n    public void onCrafted(INetworkAwareGrid grid, CraftingRecipe recipe, Player player, @Nullable IStackList<ItemStack> availableItems, @Nullable IStackList<ItemStack> usedItems) {\n        NonNullList<ItemStack> remainder = recipe.getRemainingItems(grid.getCraftingMatrix());\n\n        INetwork network = grid.getNetwork();\n\n        CraftingContainer matrix = grid.getCraftingMatrix();\n\n        for (int i = 0; i < grid.getCraftingMatrix().getContainerSize(); ++i) {\n            ItemStack slot = matrix.getItem(i);\n\n            // Do we have a remainder?\n            if (i < remainder.size() && !remainder.get(i).isEmpty()) {\n                // If there is no space for the remainder, dump it in the player inventory.\n                if (!slot.isEmpty() && slot.getCount() > 1) {\n                    if (!player.getInventory().add(remainder.get(i).copy())) { // If there is no space in the player inventory, try to dump it in the network.\n                        ItemStack remainderStack = network == null ? remainder.get(i).copy() : network.insertItem(remainder.get(i).copy(), remainder.get(i).getCount(), Action.PERFORM);\n\n                        // If there is no space in the network, just dump it in the world.\n                        if (!remainderStack.isEmpty()) {\n                            Containers.dropItemStack(player.getCommandSenderWorld(), player.getX(), player.getY(), player.getZ(), remainderStack);\n                        }\n                    }\n\n                    matrix.removeItem(i, 1);\n                } else {\n                    matrix.setItem(i, remainder.get(i).copy());\n                }\n            } else if (!slot.isEmpty()) { // We don't have a remainder, but the slot is not empty.\n                if (slot.getCount() == 1 && network != null && grid.isGridActive()) { // Attempt to refill the slot with the same item from the network, only if we have a network and only if it's the last item.\n                    ItemStack refill;\n                    if (availableItems == null) { // for regular crafting\n                        refill = network.extractItem(slot, 1, Action.PERFORM);\n                    } else { // for shift crafting\n                        if (availableItems.get(slot) != null) {\n                            refill = availableItems.remove(slot, 1).getStack().copy();\n                            refill.setCount(1);\n                            usedItems.add(refill);\n                        } else {\n                            refill = ItemStack.EMPTY;\n                        }\n                    }\n\n                    matrix.setItem(i, refill);\n\n                    if (!refill.isEmpty()) {\n                        network.getItemStorageTracker().changed(player, refill.copy());\n                    }\n                } else { // We don't have a network, or, the slot still has more than 1 items in it. Just decrement then.\n                    matrix.removeItem(i, 1);\n                }\n            }\n        }\n\n        grid.onCraftingMatrixChanged();\n    }\n\n    @Override\n    public void onCraftedShift(INetworkAwareGrid grid, Player player) {\n        CraftingContainer matrix = grid.getCraftingMatrix();\n        INetwork network = grid.getNetwork();\n        List<ItemStack> craftedItemsList = new ArrayList<>();\n        ItemStack crafted = grid.getCraftingResult().getItem(0);\n\n        int maxCrafted = crafted.getMaxStackSize();\n\n        int amountCrafted = 0;\n        boolean useNetwork = network != null && grid.isGridActive();\n\n        IStackList<ItemStack> availableItems = API.instance().createItemStackList();\n        if (useNetwork) {\n            // We need a modifiable list of the items in storage that are relevant for this craft.\n            // For performance reason we extract these into an extra list\n            filterDuplicateStacks(network, matrix, availableItems);\n        }\n\n        //A second list to remember which items have been extracted\n        IStackList<ItemStack> usedItems = API.instance().createItemStackList();\n\n        CommonHooks.setCraftingPlayer(player);\n        // Do while the item is still craftable (aka is the result slot still the same as the original item?) and we don't exceed the max stack size.\n        do {\n            grid.onCrafted(player, availableItems, usedItems);\n\n            craftedItemsList.add(crafted.copy());\n\n            amountCrafted += crafted.getCount();\n        } while (API.instance().getComparer().isEqual(crafted, grid.getCraftingResult().getItem(0)) && amountCrafted < maxCrafted && amountCrafted + crafted.getCount() <= maxCrafted);\n\n        if (useNetwork) {\n            usedItems.getStacks().forEach(stack -> network.extractItem(stack.getStack(), stack.getStack().getCount(), Action.PERFORM));\n        }\n\n        for (ItemStack craftedItem : craftedItemsList) {\n            ItemStack remainder = ItemHandlerHelper.insertItem(\n                    new PlayerMainInvWrapper(player.getInventory()),\n                    craftedItem.copy(),\n                    false\n            );\n\n            if (!remainder.isEmpty() && useNetwork) {\n                remainder = network.insertItem(remainder, remainder.getCount(), Action.PERFORM);\n            }\n\n            if (!remainder.isEmpty()) {\n                Containers.dropItemStack(player.getCommandSenderWorld(), player.getX(), player.getY(), player.getZ(), remainder);\n            }\n        }\n\n        // @Volatile: This is some logic copied from ResultSlot#checkTakeAchievements. We call this manually for shift clicking because\n        // otherwise it's not being called.\n        // For regular crafting, this is already called in ResultCraftingGridSlot#onTake -> checkTakeAchievements(stack)\n        crafted.onCraftedBy(player.level(), player, amountCrafted);\n        EventHooks.firePlayerCraftingEvent(player, ItemHandlerHelper.copyStackWithSize(crafted, amountCrafted), grid.getCraftingMatrix());\n        CommonHooks.setCraftingPlayer(null);\n    }\n\n    private void filterDuplicateStacks(INetwork network, CraftingContainer matrix, IStackList<ItemStack> availableItems) {\n        for (int i = 0; i < matrix.getContainerSize(); ++i) {\n            ItemStack stack = network.getItemStorageCache().getList().get(matrix.getItem(i));\n\n            //Don't add the same item twice into the list. Items may appear twice in a recipe but not in storage.\n            if (stack != null && availableItems.get(stack) == null) {\n                availableItems.add(stack);\n            }\n        }\n    }\n\n    @Override\n    public void onRecipeTransfer(INetworkAwareGrid grid, Player player, ItemStack[][] recipe) {\n        INetwork network = grid.getNetwork();\n\n        if (network != null && grid.getGridType() == GridType.CRAFTING && !network.getSecurityManager().hasPermission(Permission.EXTRACT, player)) {\n            return;\n        }\n\n        // First try to empty the crafting matrix\n        for (int i = 0; i < grid.getCraftingMatrix().getContainerSize(); ++i) {\n            ItemStack slot = grid.getCraftingMatrix().getItem(i);\n\n            if (!slot.isEmpty()) {\n                // Only if we are a crafting grid. Pattern grids can just be emptied.\n                if (grid.getGridType() == GridType.CRAFTING) {\n                    // If we are connected, try to insert into network. If it fails, stop.\n                    if (network != null && grid.isGridActive()) {\n                        if (!network.insertItem(slot, slot.getCount(), Action.SIMULATE).isEmpty()) {\n                            return;\n                        } else {\n                            network.insertItem(slot, slot.getCount(), Action.PERFORM);\n\n                            network.getItemStorageTracker().changed(player, slot.copy());\n                        }\n                    } else {\n                        // If we aren't connected, try to insert into player inventory. If it fails, stop.\n                        if (!player.getInventory().add(slot.copy())) {\n                            return;\n                        }\n                    }\n                }\n\n                grid.getCraftingMatrix().setItem(i, ItemStack.EMPTY);\n            }\n        }\n\n        AtomicReference<Map<Item, ItemStack>> playerItems = new AtomicReference<>();\n        // Now let's fill the matrix\n        for (int i = 0; i < grid.getCraftingMatrix().getContainerSize(); ++i) {\n            if (recipe[i] != null) {\n                ItemStack[] possibilities = recipe[i];\n\n                if (network != null && grid.isGridActive() && network.getItemStorageCache() != null) {\n\n                    // sort by the number of items in storage, craftables and inventory\n                    Arrays.sort(possibilities, compareByItemStackCounts(player, network, playerItems));\n                }\n\n                // If we are a crafting grid\n                if (grid.getGridType() == GridType.CRAFTING) {\n                    boolean found = false;\n\n                    // If we are connected, first try to get the possibilities from the network\n                    if (network != null && grid.isGridActive()) {\n                        for (ItemStack possibility : possibilities) {\n                            ItemStack took = network.extractItem(possibility, possibility.getCount(), IComparer.COMPARE_NBT, Action.PERFORM);\n\n                            if (!took.isEmpty()) {\n                                grid.getCraftingMatrix().setItem(i, took);\n\n                                network.getItemStorageTracker().changed(player, took.copy());\n\n                                found = true;\n\n                                break;\n                            }\n                        }\n                    }\n\n                    // If we haven't found anything in the network (or we are disconnected), go look in the player inventory\n                    if (!found) {\n                        for (ItemStack possibility : possibilities) {\n                            for (int j = 0; j < player.getInventory().getContainerSize(); ++j) {\n                                if (API.instance().getComparer().isEqual(possibility, player.getInventory().getItem(j), IComparer.COMPARE_NBT)) {\n                                    grid.getCraftingMatrix().setItem(i, ItemHandlerHelper.copyStackWithSize(player.getInventory().getItem(j), 1));\n\n                                    player.getInventory().removeItem(j, 1);\n\n                                    found = true;\n\n                                    break;\n                                }\n                            }\n\n                            if (found) {\n                                break;\n                            }\n                        }\n                    }\n                } else if (grid.getGridType() == GridType.PATTERN) {\n                    // If we are a pattern grid we can just set the slot\n                    grid.getCraftingMatrix().setItem(i, possibilities.length == 0 ? ItemStack.EMPTY : possibilities[0]);\n                }\n            }\n        }\n\n        if (grid.getGridType() == GridType.PATTERN) {\n            ((GridNetworkNode) grid).setProcessingPattern(false);\n            ((GridNetworkNode) grid).markDirty();\n        }\n    }\n\n    private Comparator<ItemStack> compareByItemStackCounts(Player player, INetwork network, AtomicReference<Map<Item, ItemStack>> playerItems) {\n        return Comparator.comparingInt((ItemStack itemStack) -> {\n\n            ItemStack stack = network.getItemStorageCache().getList().get(itemStack);\n            if (stack != null) {\n                return stack.getCount();\n            }\n\n            if (network.getCraftingManager().getPattern(itemStack) != null) {\n                return 1;\n            }\n\n            if (playerItems.get() == null) {\n                playerItems.set(makePlayerInventoryMap(player, network));\n            }\n\n            ItemStack onPlayer = playerItems.get().get(itemStack.getItem());\n            if (onPlayer != null) {\n                return onPlayer.getCount();\n            }\n            return 0;\n        }).reversed();\n    }\n\n    private Map<Item, ItemStack> makePlayerInventoryMap(Player player, INetwork network) {\n        Map<Item, ItemStack> playerItems = new HashMap<>();\n        for (int j = 0; j < player.getInventory().getContainerSize(); j++) {\n            ItemStack inventoryStack = player.getInventory().getItem(j);\n\n            if (inventoryStack.getItem() instanceof ICraftingPatternProvider) {\n                ICraftingPattern pattern = PatternItem.fromCache(network.getLevel(), inventoryStack);\n                if (pattern.isValid()) {\n                    for (ItemStack stack : pattern.getOutputs()) {\n                        if (!stack.isEmpty()) {\n                            playerItems.put(stack.getItem(), stack);\n                        }\n                    }\n                }\n            } else {\n                playerItems.put(inventoryStack.getItem(), inventoryStack);\n            }\n        }\n\n        return playerItems;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/GridManager.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.grid;\n\nimport com.refinedmods.refinedstorage.api.network.grid.GridFactoryType;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.api.network.grid.IGridFactory;\nimport com.refinedmods.refinedstorage.api.network.grid.IGridManager;\nimport com.refinedmods.refinedstorage.container.factory.GridMenuProvider;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport org.apache.commons.lang3.tuple.Pair;\n\nimport javax.annotation.Nullable;\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class GridManager implements IGridManager {\n    private final Map<ResourceLocation, IGridFactory> factories = new HashMap<>();\n\n    @Override\n    public void add(ResourceLocation id, IGridFactory factory) {\n        factories.put(id, factory);\n    }\n\n    @Override\n    public void openGrid(ResourceLocation id, ServerPlayer player, BlockPos pos) {\n        openGrid(id, player, null, pos, new PlayerSlot(-1));\n    }\n\n    @Override\n    public void openGrid(ResourceLocation id, ServerPlayer player, ItemStack stack, PlayerSlot slot) {\n        openGrid(id, player, stack, null, slot);\n    }\n\n    private void openGrid(ResourceLocation id, ServerPlayer player, @Nullable ItemStack stack, @Nullable BlockPos pos, PlayerSlot slot) {\n        Pair<IGrid, BlockEntity> grid = createGrid(id, player, stack, pos, slot);\n        if (grid == null) {\n            return;\n        }\n\n        player.openMenu(new GridMenuProvider(grid.getLeft(), grid.getRight()), buf -> {\n            buf.writeResourceLocation(id);\n\n            buf.writeBoolean(pos != null);\n            if (pos != null) {\n                buf.writeBlockPos(pos);\n            }\n\n            buf.writeBoolean(stack != null);\n            if (stack != null) {\n                buf.writeItem(stack);\n            }\n\n            slot.writePlayerSlot(buf);\n        });\n    }\n\n    @Override\n    @Nullable\n    public Pair<IGrid, BlockEntity> createGrid(ResourceLocation id, Player player, @Nullable ItemStack stack, @Nullable BlockPos pos, PlayerSlot slot) {\n        IGridFactory factory = factories.get(id);\n\n        if (factory == null) {\n            return null;\n        }\n\n        IGrid grid = null;\n        BlockEntity blockEntity = factory.getRelevantBlockEntity(player.level(), pos);\n\n        if (factory.getType() == GridFactoryType.STACK) {\n            grid = factory.createFromStack(player, stack, slot);\n        } else if (factory.getType() == GridFactoryType.BLOCK) {\n            grid = factory.createFromBlock(player, pos);\n        }\n\n        if (grid == null) {\n            return null;\n        }\n\n        return Pair.of(grid, blockEntity);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/GridTab.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.grid;\n\nimport com.mojang.blaze3d.platform.Lighting;\nimport com.refinedmods.refinedstorage.api.network.grid.IGridTab;\nimport com.refinedmods.refinedstorage.api.render.IElementDrawer;\nimport com.refinedmods.refinedstorage.api.util.IFilter;\nimport net.minecraft.client.gui.Font;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.network.chat.MutableComponent;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.List;\n\npublic class GridTab implements IGridTab {\n    private final List<IFilter> filters;\n    @Nullable\n    private final MutableComponent name;\n    @Nonnull\n    private final ItemStack icon;\n    @Nullable\n    private final FluidStack fluidIcon;\n\n    public GridTab(List<IFilter> filters, String name, @Nonnull ItemStack icon, @Nullable FluidStack fluidIcon) {\n        this.filters = filters;\n        this.name = name.trim().isEmpty() ? null : Component.literal(name);\n        this.icon = icon;\n        this.fluidIcon = fluidIcon;\n    }\n\n    @Override\n    public List<IFilter> getFilters() {\n        return filters;\n    }\n\n    @Override\n    public void drawTooltip(Font font, GuiGraphics graphics, int x, int y) {\n        if (name != null) {\n            graphics.renderTooltip(font, name, x, y);\n        }\n    }\n\n    @Override\n    public void drawIcon(GuiGraphics graphics, int x, int y, IElementDrawer<ItemStack> itemDrawer, IElementDrawer<FluidStack> fluidDrawer) {\n        if (!icon.isEmpty()) {\n            Lighting.setupFor3DItems();\n            itemDrawer.draw(graphics, x, y, icon);\n        } else {\n            fluidDrawer.draw(graphics, x, y, fluidIcon);\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/factory/GridBlockGridFactory.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.grid.factory;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.GridFactoryType;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.api.network.grid.IGridFactory;\nimport com.refinedmods.refinedstorage.blockentity.grid.GridBlockEntity;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\n\nimport javax.annotation.Nullable;\n\npublic class GridBlockGridFactory implements IGridFactory {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"grid\");\n\n    @Override\n    @Nullable\n    public IGrid createFromStack(Player player, ItemStack stack, PlayerSlot slot) {\n        return null;\n    }\n\n    @Override\n    @Nullable\n    public IGrid createFromBlock(Player player, BlockPos pos) {\n        BlockEntity blockEntity = getRelevantBlockEntity(player.getCommandSenderWorld(), pos);\n\n        if (blockEntity instanceof GridBlockEntity) {\n            return ((GridBlockEntity) blockEntity).getNode();\n        }\n\n        return null;\n    }\n\n    @Nullable\n    @Override\n    public BlockEntity getRelevantBlockEntity(Level level, BlockPos pos) {\n        return level.getBlockEntity(pos);\n    }\n\n    @Override\n    public GridFactoryType getType() {\n        return GridFactoryType.BLOCK;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/factory/PortableGridBlockGridFactory.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.grid.factory;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.GridFactoryType;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.api.network.grid.IGridFactory;\nimport com.refinedmods.refinedstorage.blockentity.grid.portable.PortableGridBlockEntity;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\n\nimport javax.annotation.Nullable;\n\npublic class PortableGridBlockGridFactory implements IGridFactory {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"portable_grid_block\");\n\n    @Override\n    @Nullable\n    public IGrid createFromStack(Player player, ItemStack stack, PlayerSlot slot) {\n        return null;\n    }\n\n    @Override\n    @Nullable\n    public IGrid createFromBlock(Player player, BlockPos pos) {\n        BlockEntity blockEntity = getRelevantBlockEntity(player.level(), pos);\n\n        if (blockEntity instanceof PortableGridBlockEntity) {\n            return (PortableGridBlockEntity) blockEntity;\n        }\n\n        return null;\n    }\n\n    @Nullable\n    @Override\n    public BlockEntity getRelevantBlockEntity(Level level, BlockPos pos) {\n        return level.getBlockEntity(pos);\n    }\n\n    @Override\n    public GridFactoryType getType() {\n        return GridFactoryType.BLOCK;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/factory/PortableGridGridFactory.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.grid.factory;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.GridFactoryType;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.api.network.grid.IGridFactory;\nimport com.refinedmods.refinedstorage.blockentity.grid.portable.PortableGrid;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\n\nimport javax.annotation.Nullable;\n\npublic class PortableGridGridFactory implements IGridFactory {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"portable_grid_item\");\n\n    @Nullable\n    @Override\n    public IGrid createFromStack(Player player, ItemStack stack, PlayerSlot slot) {\n        PortableGrid portableGrid = new PortableGrid(player, stack, slot);\n\n        portableGrid.onOpen();\n\n        return portableGrid;\n    }\n\n    @Nullable\n    @Override\n    public IGrid createFromBlock(Player player, BlockPos pos) {\n        return null;\n    }\n\n    @Nullable\n    @Override\n    public BlockEntity getRelevantBlockEntity(Level level, BlockPos pos) {\n        return null;\n    }\n\n    @Override\n    public GridFactoryType getType() {\n        return GridFactoryType.STACK;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/factory/WirelessFluidGridGridFactory.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.grid.factory;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.GridFactoryType;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.api.network.grid.IGridFactory;\nimport com.refinedmods.refinedstorage.blockentity.grid.WirelessFluidGrid;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\n\nimport javax.annotation.Nullable;\n\npublic class WirelessFluidGridGridFactory implements IGridFactory {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"wireless_fluid_grid\");\n\n    @Nullable\n    @Override\n    public IGrid createFromStack(Player player, ItemStack stack, PlayerSlot slot) {\n        return new WirelessFluidGrid(stack, player.getServer(), slot);\n    }\n\n    @Nullable\n    @Override\n    public IGrid createFromBlock(Player player, BlockPos pos) {\n        return null;\n    }\n\n    @Nullable\n    @Override\n    public BlockEntity getRelevantBlockEntity(Level level, BlockPos pos) {\n        return null;\n    }\n\n    @Override\n    public GridFactoryType getType() {\n        return GridFactoryType.STACK;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/factory/WirelessGridGridFactory.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.grid.factory;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.GridFactoryType;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.api.network.grid.IGridFactory;\nimport com.refinedmods.refinedstorage.blockentity.grid.WirelessGrid;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\n\nimport javax.annotation.Nullable;\n\npublic class WirelessGridGridFactory implements IGridFactory {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"wireless_grid\");\n\n    @Nullable\n    @Override\n    public IGrid createFromStack(Player player, ItemStack stack, PlayerSlot slot) {\n        return new WirelessGrid(stack, player.getServer(), slot);\n    }\n\n    @Nullable\n    @Override\n    public IGrid createFromBlock(Player player, BlockPos pos) {\n        return null;\n    }\n\n    @Nullable\n    @Override\n    public BlockEntity getRelevantBlockEntity(Level level, BlockPos pos) {\n        return null;\n    }\n\n    @Override\n    public GridFactoryType getType() {\n        return GridFactoryType.STACK;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/handler/FluidGridHandler.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.grid.handler;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.CalculationResultType;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICalculationResult;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.ErrorCraftingPreviewElement;\nimport com.refinedmods.refinedstorage.network.grid.GridCraftingPreviewResponseMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridCraftingStartResponseMessage;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.Containers;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.capabilities.Capabilities;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.fluids.FluidType;\nimport net.neoforged.neoforge.fluids.capability.IFluidHandler;\nimport net.neoforged.neoforge.fluids.capability.IFluidHandlerItem;\nimport org.apache.commons.lang3.tuple.Pair;\n\nimport javax.annotation.Nonnull;\nimport java.util.Collections;\nimport java.util.UUID;\n\npublic class FluidGridHandler implements IFluidGridHandler {\n    private final INetwork network;\n\n    public FluidGridHandler(INetwork network) {\n        this.network = network;\n    }\n\n    @Override\n    public void onExtract(ServerPlayer player, UUID id, boolean shift) {\n        FluidStack stack = network.getFluidStorageCache().getList().get(id);\n\n        if (stack == null || stack.getAmount() < FluidType.BUCKET_VOLUME || !network.getSecurityManager().hasPermission(Permission.EXTRACT, player) || !network.canRun()) {\n            return;\n        }\n\n        NetworkUtils.extractBucketFromPlayerInventoryOrNetwork(player, network, bucket -> {\n            IFluidHandlerItem fluidHandler = bucket.getCapability(Capabilities.FluidHandler.ITEM);\n            if (fluidHandler != null) {\n                network.getFluidStorageTracker().changed(player, stack.copy());\n\n                FluidStack extracted = network.extractFluid(stack, FluidType.BUCKET_VOLUME, Action.PERFORM);\n\n                fluidHandler.fill(extracted, IFluidHandler.FluidAction.EXECUTE);\n\n                if (shift) {\n                    if (!player.getInventory().add(fluidHandler.getContainer().copy())) {\n                        Containers.dropItemStack(player.getCommandSenderWorld(), player.getX(), player.getY(), player.getZ(), fluidHandler.getContainer());\n                    }\n                } else {\n                    player.containerMenu.setCarried(fluidHandler.getContainer());\n                }\n\n                network.getNetworkItemManager().drainEnergy(player, RS.SERVER_CONFIG.getWirelessFluidGrid().getExtractUsage());\n            }\n        });\n    }\n\n    @Override\n    @Nonnull\n    public ItemStack onInsert(ServerPlayer player, ItemStack container) {\n        if (!network.getSecurityManager().hasPermission(Permission.INSERT, player) || !network.canRun()) {\n            return container;\n        }\n\n        Pair<ItemStack, FluidStack> result = StackUtils.getFluid(container, true);\n\n        if (!result.getValue().isEmpty() && network.insertFluid(result.getValue(), result.getValue().getAmount(), Action.SIMULATE).isEmpty()) {\n            network.getFluidStorageTracker().changed(player, result.getValue().copy());\n\n            result = StackUtils.getFluid(container, false);\n\n            network.insertFluid(result.getValue(), result.getValue().getAmount(), Action.PERFORM);\n\n            network.getNetworkItemManager().drainEnergy(player, RS.SERVER_CONFIG.getWirelessFluidGrid().getInsertUsage());\n\n            return result.getLeft();\n        }\n\n        return container;\n    }\n\n    @Override\n    public void onInsertHeldContainer(ServerPlayer player) {\n        player.containerMenu.setCarried(onInsert(player, player.containerMenu.getCarried()));\n    }\n\n    @Override\n    public void onCraftingPreviewRequested(ServerPlayer player, UUID id, int quantity, boolean noPreview) {\n        if (!network.getSecurityManager().hasPermission(Permission.AUTOCRAFTING, player)) {\n            return;\n        }\n\n        FluidStack stack = network.getFluidStorageCache().getCraftablesList().get(id);\n\n        if (stack != null) {\n            ICalculationResult result = network.getCraftingManager().create(stack, quantity);\n            if (result == null) {\n                return;\n            }\n\n            if (!result.isOk() && result.getType() != CalculationResultType.MISSING) {\n                RS.NETWORK_HANDLER.sendTo(\n                    player,\n                    new GridCraftingPreviewResponseMessage(\n                        Collections.singletonList(new ErrorCraftingPreviewElement(result.getType(), result.getRecursedPattern() == null ? ItemStack.EMPTY : result.getRecursedPattern().getStack())),\n                        id,\n                        quantity,\n                        true\n                    )\n                );\n            } else if (result.isOk() && noPreview) {\n                network.getCraftingManager().start(result.getTask());\n\n                RS.NETWORK_HANDLER.sendTo(player, new GridCraftingStartResponseMessage());\n            } else {\n                RS.NETWORK_HANDLER.sendTo(\n                    player,\n                    new GridCraftingPreviewResponseMessage(\n                        result.getPreviewElements(),\n                        id,\n                        quantity,\n                        true\n                    )\n                );\n            }\n        }\n    }\n\n    @Override\n    public void onCraftingRequested(ServerPlayer player, UUID id, int quantity) {\n        if (quantity <= 0 || !network.getSecurityManager().hasPermission(Permission.AUTOCRAFTING, player)) {\n            return;\n        }\n\n        FluidStack stack = network.getFluidStorageCache().getCraftablesList().get(id);\n\n        if (stack != null) {\n            ICalculationResult result = network.getCraftingManager().create(stack, quantity);\n            if (result.isOk()) {\n                network.getCraftingManager().start(result.getTask());\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/handler/ItemGridHandler.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.grid.handler;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.CalculationResultType;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICalculationResult;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.api.util.StackListEntry;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.ErrorCraftingPreviewElement;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport com.refinedmods.refinedstorage.network.grid.GridCraftingPreviewResponseMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridCraftingStartResponseMessage;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.capabilities.Capabilities;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.Collections;\nimport java.util.Optional;\nimport java.util.UUID;\n\npublic class ItemGridHandler implements IItemGridHandler {\n    private final INetwork network;\n\n    public ItemGridHandler(INetwork network) {\n        this.network = network;\n    }\n\n    public static void onInventoryScroll(IItemGridHandler gridHandler, ServerPlayer player, int slot, boolean shift, boolean up, @Nullable INetwork network) {\n        if (player == null || !(player.containerMenu instanceof GridContainerMenu)) {\n            return;\n        }\n\n        if (network != null && ((up && !network.getSecurityManager().hasPermission(Permission.INSERT, player)) || (!up && !network.getSecurityManager().hasPermission(Permission.EXTRACT, player)))) {\n            return;\n        }\n\n        int flags = EXTRACT_SINGLE;\n        ItemStack stackInSlot = player.getInventory().getItem(slot);\n        ItemStack stackOnCursor = player.containerMenu.getCarried();\n\n        if (shift) { // shift\n            flags |= EXTRACT_SHIFT;\n\n            if (!stackInSlot.isEmpty()) {\n                if (up) { // scroll up\n                    player.getInventory().setItem(slot, gridHandler.onInsert(player, stackInSlot, true));\n                } else { // scroll down\n                    gridHandler.onExtract(player, stackInSlot, slot, flags);\n                }\n            }\n        } else { //ctrl\n            if (up) { // scroll up\n                if (!stackOnCursor.isEmpty()) {\n                    gridHandler.onInsert(player, stackOnCursor, true);\n                }\n            } else { //scroll down\n                if (stackOnCursor.isEmpty()) {\n                    gridHandler.onExtract(player, stackInSlot, -1, flags);\n                } else {\n                    gridHandler.onExtract(player, stackOnCursor, -1, flags);\n                }\n            }\n        }\n    }\n\n    public static void onGridScroll(IItemGridHandler gridHandler, ServerPlayer player, @Nullable UUID id, boolean shift, boolean up, @Nullable INetwork network) {\n        if (player == null || !(player.containerMenu instanceof GridContainerMenu)) {\n            return;\n        }\n\n        if (network != null && ((up && !network.getSecurityManager().hasPermission(Permission.INSERT, player)) || (!up && !network.getSecurityManager().hasPermission(Permission.EXTRACT, player)))) {\n            return;\n        }\n\n        IGrid grid = ((GridContainerMenu) player.containerMenu).getGrid();\n\n        int flags = EXTRACT_SINGLE;\n\n        if (shift && id != null) {\n            flags |= EXTRACT_SHIFT;\n            if (up) { //scroll up, insert hovering stack pulled from Inventory\n                IStorageCache<ItemStack> cache = grid.getStorageCache();\n                if (cache == null || cache.getList().get(id) == null) {\n                    return;\n                }\n\n                for (int i = 0; i < player.getInventory().items.size(); i++) {\n                    if (API.instance().getComparer().isEqual(player.getInventory().getItem(i), cache.getList().get(id), IComparer.COMPARE_NBT)) {\n                        gridHandler.onInsert(player, player.getInventory().getItem(i), true);\n                        break;\n                    }\n                }\n\n            } else { //scroll down, extract hovering item\n                gridHandler.onExtract(player, id, -1, flags);\n            }\n        } else { //ctrl\n            if (!up && id != null) { //scroll down, extract hovering item\n                gridHandler.onExtract(player, id, -1, flags);\n\n            } else if (up && !player.containerMenu.getCarried().isEmpty()) { // insert stack from cursor\n                gridHandler.onInsert(player, player.containerMenu.getCarried(), true);\n            }\n        }\n    }\n\n    @Override\n    public void onExtract(ServerPlayer player, ItemStack stack, int preferredSlot, int flags) {\n        StackListEntry<ItemStack> stackEntry = network.getItemStorageCache().getList().getEntry(stack, IComparer.COMPARE_NBT);\n        if (stackEntry != null) {\n            onExtract(player, stackEntry.getId(), preferredSlot, flags);\n        }\n    }\n\n    @Override\n    public void onExtract(ServerPlayer player, UUID id, int preferredSlot, int flags) {\n        ItemStack item = network.getItemStorageCache().getList().get(id);\n\n        if (item == null || !network.getSecurityManager().hasPermission(Permission.EXTRACT, player) || !network.canRun()) {\n            return;\n        }\n\n        int itemSize = item.getCount();\n        // We copy here because some mods change the NBT tag of an item after getting the stack limit\n        int maxItemSize = item.getItem().getMaxStackSize(item.copy());\n\n        boolean single = (flags & EXTRACT_SINGLE) == EXTRACT_SINGLE;\n\n        ItemStack held = player.containerMenu.getCarried();\n\n        if (single) {\n            if (!held.isEmpty() && (!API.instance().getComparer().isEqualNoQuantity(item, held) || held.getCount() + 1 > held.getMaxStackSize())) {\n                return;\n            }\n        } else if (!player.containerMenu.getCarried().isEmpty()) {\n            return;\n        }\n\n        int size = 64;\n\n        if ((flags & EXTRACT_HALF) == EXTRACT_HALF && itemSize > 1) {\n            size = itemSize / 2;\n\n            // Rationale for this check:\n            // If we have 32 buckets, and we want to extract half, we expect/need to get 8 (max stack size 16 / 2).\n            // Without this check, we would get 16 (total stack size 32 / 2).\n            // Max item size also can't be 1. Otherwise, if we want to extract half of 8 lava buckets, we would get size 0 (1 / 2).\n            if (size > maxItemSize / 2 && maxItemSize != 1) {\n                size = maxItemSize / 2;\n            }\n        } else if (single) {\n            size = 1;\n        } else if ((flags & EXTRACT_SHIFT) == EXTRACT_SHIFT) {\n            // NO OP, the quantity already set (64) is needed for shift\n        }\n\n        size = Math.min(size, maxItemSize);\n\n        // Do this before actually extracting, since external storage sends updates as soon as a change happens (so before the storage tracker used to track)\n        network.getItemStorageTracker().changed(player, item.copy());\n\n        ItemStack took = network.extractItem(item, size, Action.SIMULATE);\n\n        if (!took.isEmpty()) {\n            if ((flags & EXTRACT_SHIFT) == EXTRACT_SHIFT) {\n                IItemHandler playerInventory = player.getCapability(Capabilities.ItemHandler.ENTITY);\n                if (playerInventory != null) {\n                    if (preferredSlot != -1) {\n                        ItemStack remainder = playerInventory.insertItem(preferredSlot, took, true);\n                        if (remainder.getCount() != took.getCount()) {\n                            ItemStack inserted = network.extractItem(item, size - remainder.getCount(), Action.PERFORM);\n                            playerInventory.insertItem(preferredSlot, inserted, false);\n                            took.setCount(remainder.getCount());\n                        }\n                    }\n\n                    if (!took.isEmpty() && ItemHandlerHelper.insertItemStacked(playerInventory, took, true).isEmpty()) {\n                        took = network.extractItem(item, size, Action.PERFORM);\n\n                        ItemHandlerHelper.insertItemStacked(playerInventory, took, false);\n                    }\n                }\n            } else {\n                took = network.extractItem(item, size, Action.PERFORM);\n\n                if (!took.isEmpty()) {\n                    if (single && !held.isEmpty()) {\n                        held.grow(1);\n                    } else {\n                        player.containerMenu.setCarried(took);\n                    }\n                }\n            }\n\n            network.getNetworkItemManager().drainEnergy(player, RS.SERVER_CONFIG.getWirelessGrid().getExtractUsage());\n        }\n    }\n\n    @Override\n    @Nonnull\n    public ItemStack onInsert(ServerPlayer player, ItemStack stack, boolean single) {\n        if (!network.getSecurityManager().hasPermission(Permission.INSERT, player) || !network.canRun()) {\n            return stack;\n        }\n\n        network.getItemStorageTracker().changed(player, stack.copy());\n\n        ItemStack remainder;\n        if (single) {\n            if (network.insertItem(stack, 1, Action.SIMULATE).isEmpty()) {\n                network.insertItem(stack, 1, Action.PERFORM);\n                stack.shrink(1);\n            }\n            remainder = stack;\n        } else {\n            remainder = network.insertItem(stack, stack.getCount(), Action.PERFORM);\n        }\n\n        network.getNetworkItemManager().drainEnergy(player, RS.SERVER_CONFIG.getWirelessGrid().getInsertUsage());\n\n        return remainder;\n    }\n\n    @Override\n    public void onInsertHeldItem(ServerPlayer player, boolean single) {\n        if (player.containerMenu.getCarried().isEmpty() || !network.getSecurityManager().hasPermission(Permission.INSERT, player) || !network.canRun()) {\n            return;\n        }\n\n        ItemStack stack = player.containerMenu.getCarried();\n        int size = single ? 1 : stack.getCount();\n\n        network.getItemStorageTracker().changed(player, stack.copy());\n\n        if (single) {\n            if (network.insertItem(stack, size, Action.SIMULATE).isEmpty()) {\n                network.insertItem(stack, size, Action.PERFORM);\n\n                stack.shrink(size);\n            }\n        } else {\n            player.containerMenu.setCarried(network.insertItem(stack, size, Action.PERFORM));\n        }\n\n        network.getNetworkItemManager().drainEnergy(player, RS.SERVER_CONFIG.getWirelessGrid().getInsertUsage());\n    }\n\n    @Override\n    public void onCraftingPreviewRequested(ServerPlayer player, UUID id, int quantity, boolean noPreview) {\n        if (!network.getSecurityManager().hasPermission(Permission.AUTOCRAFTING, player)) {\n            return;\n        }\n\n        ItemStack stack = network.getItemStorageCache().getCraftablesList().get(id);\n\n        if (stack != null) {\n            ICalculationResult result = network.getCraftingManager().create(stack, quantity);\n\n            if (!result.isOk() && result.getType() != CalculationResultType.MISSING) {\n                RS.NETWORK_HANDLER.sendTo(\n                    player,\n                    new GridCraftingPreviewResponseMessage(\n                        Collections.singletonList(new ErrorCraftingPreviewElement(result.getType(), result.getRecursedPattern() == null ? ItemStack.EMPTY : result.getRecursedPattern().getStack())),\n                        id,\n                        quantity,\n                        false\n                    )\n                );\n            } else if (result.isOk() && noPreview) {\n                network.getCraftingManager().start(result.getTask());\n\n                RS.NETWORK_HANDLER.sendTo(player, new GridCraftingStartResponseMessage());\n            } else {\n                RS.NETWORK_HANDLER.sendTo(\n                    player,\n                    new GridCraftingPreviewResponseMessage(\n                        result.getPreviewElements(),\n                        id,\n                        quantity,\n                        false\n                    )\n                );\n            }\n        }\n    }\n\n    @Override\n    public void onCraftingRequested(ServerPlayer player, UUID id, int quantity) {\n        if (quantity <= 0 || !network.getSecurityManager().hasPermission(Permission.AUTOCRAFTING, player)) {\n            return;\n        }\n\n        ItemStack stack = network.getItemStorageCache().getCraftablesList().get(id);\n\n        if (stack != null) {\n            ICalculationResult result = network.getCraftingManager().create(stack, quantity);\n            if (result.isOk()) {\n                network.getCraftingManager().start(result.getTask());\n            }\n        }\n    }\n\n    @Override\n    public void onCraftingCancelRequested(ServerPlayer player, @Nullable UUID id) {\n        if (!network.getSecurityManager().hasPermission(Permission.AUTOCRAFTING, player)) {\n            return;\n        }\n\n        network.getCraftingManager().cancel(id);\n\n        network.getNetworkItemManager().drainEnergy(player, id == null ? RS.SERVER_CONFIG.getWirelessCraftingMonitor().getCancelAllUsage() : RS.SERVER_CONFIG.getWirelessCraftingMonitor().getCancelUsage());\n    }\n\n    @Override\n    public void onInventoryScroll(ServerPlayer player, int slot, boolean shift, boolean up) {\n        onInventoryScroll(this, player, slot, shift, up, network);\n    }\n\n    @Override\n    public void onGridScroll(ServerPlayer player, @Nullable UUID id, boolean shift, boolean up) {\n        onGridScroll(this, player, id, shift, up, network);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/handler/PortableFluidGridHandler.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.grid.handler;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.blockentity.grid.portable.IPortableGrid;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.Containers;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.capabilities.Capabilities;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.fluids.FluidType;\nimport net.neoforged.neoforge.fluids.capability.IFluidHandler;\nimport net.neoforged.neoforge.fluids.capability.IFluidHandlerItem;\nimport org.apache.commons.lang3.tuple.Pair;\n\nimport javax.annotation.Nonnull;\nimport java.util.UUID;\n\npublic class PortableFluidGridHandler implements IFluidGridHandler {\n    private final IPortableGrid portableGrid;\n\n    public PortableFluidGridHandler(IPortableGrid portableGrid) {\n        this.portableGrid = portableGrid;\n    }\n\n    @Override\n    public void onExtract(ServerPlayer player, UUID id, boolean shift) {\n        if (!portableGrid.isGridActive()) {\n            return;\n        }\n\n        FluidStack stack = portableGrid.getFluidCache().getList().get(id);\n\n        if (stack == null || stack.getAmount() < FluidType.BUCKET_VOLUME) {\n            return;\n        }\n\n        ItemStack bucket = ItemStack.EMPTY;\n\n        for (int i = 0; i < player.getInventory().getContainerSize(); ++i) {\n            ItemStack slot = player.getInventory().getItem(i);\n\n            if (API.instance().getComparer().isEqualNoQuantity(StackUtils.EMPTY_BUCKET, slot)) {\n                bucket = StackUtils.EMPTY_BUCKET.copy();\n\n                player.getInventory().removeItem(i, 1);\n\n                break;\n            }\n        }\n\n        if (!bucket.isEmpty()) {\n            IFluidHandlerItem fluidHandler = bucket.getCapability(Capabilities.FluidHandler.ITEM);\n            if (fluidHandler != null) {\n                portableGrid.getFluidStorageTracker().changed(player, stack.copy());\n\n                fluidHandler.fill(portableGrid.getFluidStorage().extract(stack, FluidType.BUCKET_VOLUME, IComparer.COMPARE_NBT, Action.PERFORM), IFluidHandler.FluidAction.EXECUTE);\n\n                if (shift) {\n                    if (!player.getInventory().add(fluidHandler.getContainer().copy())) {\n                        Containers.dropItemStack(player.getCommandSenderWorld(), player.getX(), player.getY(), player.getZ(), fluidHandler.getContainer());\n                    }\n                } else {\n                    player.containerMenu.setCarried(fluidHandler.getContainer());\n                }\n\n                portableGrid.drainEnergy(RS.SERVER_CONFIG.getPortableGrid().getExtractUsage());\n            }\n        }\n    }\n\n    @Override\n    @Nonnull\n    public ItemStack onInsert(ServerPlayer player, ItemStack container) {\n        if (!portableGrid.isGridActive()) {\n            return container;\n        }\n\n        Pair<ItemStack, FluidStack> result = StackUtils.getFluid(container, true);\n\n        if (!result.getValue().isEmpty() && portableGrid.getFluidStorage().insert(result.getValue(), result.getValue().getAmount(), Action.SIMULATE).isEmpty()) {\n            portableGrid.getFluidStorageTracker().changed(player, result.getValue().copy());\n\n            result = StackUtils.getFluid(container, false);\n\n            portableGrid.getFluidStorage().insert(result.getValue(), result.getValue().getAmount(), Action.PERFORM);\n\n            portableGrid.drainEnergy(RS.SERVER_CONFIG.getPortableGrid().getInsertUsage());\n\n            return result.getLeft();\n        }\n\n        return container;\n    }\n\n    @Override\n    public void onInsertHeldContainer(ServerPlayer player) {\n        player.containerMenu.setCarried(onInsert(player, player.containerMenu.getCarried()));\n    }\n\n    @Override\n    public void onCraftingPreviewRequested(ServerPlayer player, UUID id, int quantity, boolean noPreview) {\n        // NO OP\n    }\n\n    @Override\n    public void onCraftingRequested(ServerPlayer player, UUID id, int quantity) {\n        // NO OP\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/handler/PortableItemGridHandler.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.grid.handler;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.blockentity.grid.portable.IPortableGrid;\nimport net.minecraft.core.Direction;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.capabilities.Capabilities;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.UUID;\n\npublic class PortableItemGridHandler implements IItemGridHandler {\n    private final IPortableGrid portableGrid;\n    private final IGrid grid;\n\n    public PortableItemGridHandler(IPortableGrid portableGrid, IGrid grid) {\n        this.portableGrid = portableGrid;\n        this.grid = grid;\n    }\n\n    @Override\n    public void onExtract(ServerPlayer player, ItemStack stack, int preferredSlot, int flags) {\n        if (portableGrid.getStorage() == null || !grid.isGridActive()) {\n            return;\n        }\n\n        if (portableGrid.getItemCache().getList().getEntry(stack, IComparer.COMPARE_NBT) != null) {\n            onExtract(player, portableGrid.getItemCache().getList().getEntry(stack, IComparer.COMPARE_NBT).getId(), preferredSlot, flags);\n        }\n    }\n\n    @Override\n    public void onExtract(ServerPlayer player, UUID id, int preferredSlot, int flags) {\n        if (portableGrid.getStorage() == null || !grid.isGridActive()) {\n            return;\n        }\n\n        ItemStack item = portableGrid.getItemCache().getList().get(id);\n\n        if (item == null) {\n            return;\n        }\n\n        int itemSize = item.getCount();\n        // We copy here because some mods change the NBT tag of an item after getting the stack limit\n        int maxItemSize = item.getItem().getMaxStackSize(item.copy());\n\n        boolean single = (flags & EXTRACT_SINGLE) == EXTRACT_SINGLE;\n\n        ItemStack held = player.containerMenu.getCarried();\n\n        if (single) {\n            if (!held.isEmpty() && (!API.instance().getComparer().isEqualNoQuantity(item, held) || held.getCount() + 1 > held.getMaxStackSize())) {\n                return;\n            }\n        } else if (!player.containerMenu.getCarried().isEmpty()) {\n            return;\n        }\n\n        int size = 64;\n\n        if ((flags & EXTRACT_HALF) == EXTRACT_HALF && itemSize > 1) {\n            size = itemSize / 2;\n\n            // Rationale for this check:\n            // If we have 32 buckets, and we want to extract half, we expect/need to get 8 (max stack size 16 / 2).\n            // Without this check, we would get 16 (total stack size 32 / 2).\n            // Max item size also can't be 1. Otherwise, if we want to extract half of 8 lava buckets, we would get size 0 (1 / 2).\n            if (size > maxItemSize / 2 && maxItemSize != 1) {\n                size = maxItemSize / 2;\n            }\n        } else if (single) {\n            size = 1;\n        } else if ((flags & EXTRACT_SHIFT) == EXTRACT_SHIFT) {\n            // NO OP, the quantity already set (64) is needed for shift\n        }\n\n        size = Math.min(size, maxItemSize);\n\n        // Do this before actually extracting, since portable grid sends updates as soon as a change happens (so before the storage tracker used to track)\n        portableGrid.getItemStorageTracker().changed(player, item.copy());\n\n        ItemStack took = portableGrid.getItemStorage().extract(item, size, IComparer.COMPARE_NBT, Action.SIMULATE);\n\n        if (!took.isEmpty()) {\n            if ((flags & EXTRACT_SHIFT) == EXTRACT_SHIFT) {\n                IItemHandler playerInventory = player.getCapability(Capabilities.ItemHandler.ENTITY);\n                if (playerInventory != null) {\n                    if (preferredSlot != -1) {\n                        ItemStack remainder = playerInventory.insertItem(preferredSlot, took, true);\n                        if (remainder.getCount() != took.getCount()) {\n                            ItemStack inserted = portableGrid.getItemStorage().extract(item, size - remainder.getCount(), IComparer.COMPARE_NBT, Action.PERFORM);\n                            playerInventory.insertItem(preferredSlot, inserted, false);\n                            took.setCount(remainder.getCount());\n                        }\n                    }\n\n                    if (!took.isEmpty() && ItemHandlerHelper.insertItemStacked(playerInventory, took, true).isEmpty()) {\n                        took = portableGrid.getItemStorage().extract(item, size, IComparer.COMPARE_NBT, Action.PERFORM);\n\n                        ItemHandlerHelper.insertItemStacked(playerInventory, took, false);\n                    }\n                }\n            } else {\n                took = portableGrid.getItemStorage().extract(item, size, IComparer.COMPARE_NBT, Action.PERFORM);\n\n                if (single && !held.isEmpty()) {\n                    held.grow(1);\n                } else {\n                    player.containerMenu.setCarried(took);\n                }\n            }\n\n            portableGrid.drainEnergy(RS.SERVER_CONFIG.getPortableGrid().getExtractUsage());\n        }\n    }\n\n    @Override\n    @Nonnull\n    public ItemStack onInsert(ServerPlayer player, ItemStack stack, boolean single) {\n        if (portableGrid.getStorage() == null || !grid.isGridActive()) {\n            return stack;\n        }\n\n        portableGrid.getItemStorageTracker().changed(player, stack.copy());\n        ItemStack remainder;\n        if (single) {\n            if (portableGrid.getItemStorage().insert(stack, 1, Action.SIMULATE).isEmpty()) {\n                portableGrid.getItemStorage().insert(stack, 1, Action.PERFORM);\n                stack.shrink(1);\n            }\n            remainder = stack;\n        } else {\n            remainder = portableGrid.getItemStorage().insert(stack, stack.getCount(), Action.PERFORM);\n        }\n\n        portableGrid.drainEnergy(RS.SERVER_CONFIG.getPortableGrid().getInsertUsage());\n\n        return remainder;\n    }\n\n    @Override\n    public void onInsertHeldItem(ServerPlayer player, boolean single) {\n        if (player.containerMenu.getCarried().isEmpty() || portableGrid.getStorage() == null || !grid.isGridActive()) {\n            return;\n        }\n\n        ItemStack stack = player.containerMenu.getCarried();\n        int size = single ? 1 : stack.getCount();\n\n        portableGrid.getItemStorageTracker().changed(player, stack.copy());\n\n        if (single) {\n            if (portableGrid.getItemStorage().insert(stack, size, Action.SIMULATE).isEmpty()) {\n                portableGrid.getItemStorage().insert(stack, size, Action.PERFORM);\n\n                stack.shrink(size);\n            }\n        } else {\n            player.containerMenu.setCarried(portableGrid.getItemStorage().insert(stack, size, Action.PERFORM));\n        }\n\n        portableGrid.drainEnergy(RS.SERVER_CONFIG.getPortableGrid().getInsertUsage());\n    }\n\n    @Override\n    public void onCraftingPreviewRequested(ServerPlayer player, UUID id, int quantity, boolean noPreview) {\n        // NO OP\n    }\n\n    @Override\n    public void onCraftingRequested(ServerPlayer player, UUID id, int quantity) {\n        // NO OP\n    }\n\n    @Override\n    public void onCraftingCancelRequested(ServerPlayer player, @Nullable UUID id) {\n        // NO OP\n    }\n\n    @Override\n    public void onInventoryScroll(ServerPlayer player, int slot, boolean shift, boolean up) {\n        ItemGridHandler.onInventoryScroll(this, player, slot, shift, up, null);\n    }\n\n    @Override\n    public void onGridScroll(ServerPlayer player, @Nullable UUID id, boolean shift, boolean up) {\n        ItemGridHandler.onGridScroll(this, player, id, shift, up, null);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/item/NetworkItemManager.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.item;\n\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.INetworkNodeGraphEntry;\nimport com.refinedmods.refinedstorage.api.network.IWirelessTransmitter;\nimport com.refinedmods.refinedstorage.api.network.item.INetworkItem;\nimport com.refinedmods.refinedstorage.api.network.item.INetworkItemManager;\nimport com.refinedmods.refinedstorage.api.network.item.INetworkItemProvider;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.phys.Vec3;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\npublic class NetworkItemManager implements INetworkItemManager {\n    private final INetwork network;\n    private final Map<Player, INetworkItem> items = new ConcurrentHashMap<>();\n\n    public NetworkItemManager(INetwork network) {\n        this.network = network;\n    }\n\n    @Override\n    public void open(Player player, ItemStack stack, PlayerSlot slot) {\n        boolean inRange = false;\n\n        for (INetworkNodeGraphEntry entry : network.getNodeGraph().all()) {\n            INetworkNode node = entry.getNode();\n\n            if (node instanceof IWirelessTransmitter &&\n                network.canRun() &&\n                node.isActive() &&\n                ((IWirelessTransmitter) node).getDimension() == player.getCommandSenderWorld().dimension()) {\n                IWirelessTransmitter transmitter = (IWirelessTransmitter) node;\n\n                Vec3 pos = player.position();\n\n                double distance = Math.sqrt(Math.pow(transmitter.getOrigin().getX() - pos.x(), 2) + Math.pow(transmitter.getOrigin().getY() - pos.y(), 2) + Math.pow(transmitter.getOrigin().getZ() - pos.z(), 2));\n\n                if (distance < transmitter.getRange()) {\n                    inRange = true;\n\n                    break;\n                }\n            }\n        }\n\n        if (!inRange) {\n            player.sendSystemMessage(Component.translatable(\"misc.refinedstorage.network_item.out_of_range\"));\n\n            return;\n        }\n\n        INetworkItem item = ((INetworkItemProvider) stack.getItem()).provide(this, player, stack, slot);\n\n        if (item.onOpen(network)) {\n            items.put(player, item);\n        }\n    }\n\n    @Override\n    public void close(Player player) {\n        items.remove(player);\n    }\n\n    @Override\n    public INetworkItem getItem(Player player) {\n        return items.get(player);\n    }\n\n    @Override\n    public void drainEnergy(Player player, int energy) {\n        INetworkItem item = getItem(player);\n\n        if (item != null) {\n            item.drainEnergy(energy);\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/item/WirelessCraftingMonitorNetworkItem.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.item;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.item.INetworkItem;\nimport com.refinedmods.refinedstorage.api.network.item.INetworkItemManager;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.blockentity.craftingmonitor.WirelessCraftingMonitor;\nimport com.refinedmods.refinedstorage.container.factory.CraftingMonitorMenuProvider;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport com.refinedmods.refinedstorage.item.WirelessCraftingMonitorItem;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.capabilities.Capabilities;\nimport net.neoforged.neoforge.energy.IEnergyStorage;\n\npublic class WirelessCraftingMonitorNetworkItem implements INetworkItem {\n    private final INetworkItemManager handler;\n    private final Player player;\n    private final ItemStack stack;\n    private final PlayerSlot slot;\n\n    public WirelessCraftingMonitorNetworkItem(INetworkItemManager handler, Player player, ItemStack stack, PlayerSlot slot) {\n        this.handler = handler;\n        this.player = player;\n        this.stack = stack;\n        this.slot = slot;\n    }\n\n    @Override\n    public Player getPlayer() {\n        return player;\n    }\n\n    @Override\n    public boolean onOpen(INetwork network) {\n        IEnergyStorage energy = stack.getCapability(Capabilities.EnergyStorage.ITEM);\n\n        if (RS.SERVER_CONFIG.getWirelessCraftingMonitor().getUseEnergy() &&\n            ((WirelessCraftingMonitorItem) stack.getItem()).getType() != WirelessCraftingMonitorItem.Type.CREATIVE &&\n            energy != null &&\n            energy.getEnergyStored() <= RS.SERVER_CONFIG.getWirelessCraftingMonitor().getOpenUsage()) {\n            sendOutOfEnergyMessage();\n\n            return false;\n        }\n\n        if (!network.getSecurityManager().hasPermission(Permission.MODIFY, player) ||\n            !network.getSecurityManager().hasPermission(Permission.AUTOCRAFTING, player)) {\n            LevelUtils.sendNoPermissionMessage(player);\n\n            return false;\n        }\n\n        WirelessCraftingMonitor wirelessCraftingMonitor = new WirelessCraftingMonitor(stack, player.getServer(), slot);\n\n        player.openMenu(\n            new CraftingMonitorMenuProvider(RSContainerMenus.WIRELESS_CRAFTING_MONITOR.get(), wirelessCraftingMonitor, null),\n            slot::writePlayerSlot\n        );\n\n        drainEnergy(RS.SERVER_CONFIG.getWirelessCraftingMonitor().getOpenUsage());\n\n        return true;\n    }\n\n    @Override\n    public void drainEnergy(int energy) {\n        if (RS.SERVER_CONFIG.getWirelessCraftingMonitor().getUseEnergy() && ((WirelessCraftingMonitorItem) stack.getItem()).getType() != WirelessCraftingMonitorItem.Type.CREATIVE) {\n            IEnergyStorage energyStorage = stack.getCapability(Capabilities.EnergyStorage.ITEM);\n            if (energyStorage != null) {\n                energyStorage.extractEnergy(energy, false);\n\n                if (energyStorage.getEnergyStored() <= 0) {\n                    handler.close(player);\n\n                    player.closeContainer();\n\n                    sendOutOfEnergyMessage();\n                }\n            }\n        }\n    }\n\n    private void sendOutOfEnergyMessage() {\n        player.sendSystemMessage(Component.translatable(\"misc.refinedstorage.network_item.out_of_energy\", Component.translatable(stack.getItem().getDescriptionId())));\n    }\n}"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/item/WirelessFluidGridNetworkItem.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.item;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.item.INetworkItem;\nimport com.refinedmods.refinedstorage.api.network.item.INetworkItemManager;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.grid.factory.WirelessFluidGridGridFactory;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport com.refinedmods.refinedstorage.item.WirelessFluidGridItem;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.capabilities.Capabilities;\nimport net.neoforged.neoforge.energy.IEnergyStorage;\n\npublic class WirelessFluidGridNetworkItem implements INetworkItem {\n    private final INetworkItemManager handler;\n    private final Player player;\n    private final ItemStack stack;\n    private final PlayerSlot slot;\n\n    public WirelessFluidGridNetworkItem(INetworkItemManager handler, Player player, ItemStack stack, PlayerSlot slot) {\n        this.handler = handler;\n        this.player = player;\n        this.stack = stack;\n        this.slot = slot;\n    }\n\n    @Override\n    public Player getPlayer() {\n        return player;\n    }\n\n    @Override\n    public boolean onOpen(INetwork network) {\n        IEnergyStorage energy = stack.getCapability(Capabilities.EnergyStorage.ITEM);\n\n        if (RS.SERVER_CONFIG.getWirelessFluidGrid().getUseEnergy() &&\n            ((WirelessFluidGridItem) stack.getItem()).getType() != WirelessFluidGridItem.Type.CREATIVE &&\n            energy != null &&\n            energy.getEnergyStored() <= RS.SERVER_CONFIG.getWirelessFluidGrid().getOpenUsage()) {\n            sendOutOfEnergyMessage();\n\n            return false;\n        }\n\n        if (!network.getSecurityManager().hasPermission(Permission.MODIFY, player)) {\n            LevelUtils.sendNoPermissionMessage(player);\n\n            return false;\n        }\n\n        API.instance().getGridManager().openGrid(WirelessFluidGridGridFactory.ID, (ServerPlayer) player, stack, slot);\n\n        drainEnergy(RS.SERVER_CONFIG.getWirelessFluidGrid().getOpenUsage());\n\n        return true;\n    }\n\n    @Override\n    public void drainEnergy(int energy) {\n        if (RS.SERVER_CONFIG.getWirelessFluidGrid().getUseEnergy() && ((WirelessFluidGridItem) stack.getItem()).getType() != WirelessFluidGridItem.Type.CREATIVE) {\n            IEnergyStorage energyStorage = stack.getCapability(Capabilities.EnergyStorage.ITEM);\n            if (energyStorage != null) {\n                energyStorage.extractEnergy(energy, false);\n\n                if (energyStorage.getEnergyStored() <= 0) {\n                    handler.close(player);\n\n                    player.closeContainer();\n\n                    sendOutOfEnergyMessage();\n                }\n            }\n        }\n    }\n\n    private void sendOutOfEnergyMessage() {\n        player.sendSystemMessage(Component.translatable(\"misc.refinedstorage.network_item.out_of_energy\", Component.translatable(stack.getItem().getDescriptionId())));\n    }\n}"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/item/WirelessGridNetworkItem.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.item;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.item.INetworkItem;\nimport com.refinedmods.refinedstorage.api.network.item.INetworkItemManager;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.grid.factory.WirelessGridGridFactory;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport com.refinedmods.refinedstorage.item.WirelessGridItem;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.capabilities.Capabilities;\nimport net.neoforged.neoforge.energy.IEnergyStorage;\n\npublic class WirelessGridNetworkItem implements INetworkItem {\n    private final INetworkItemManager handler;\n    private final Player player;\n    private final ItemStack stack;\n    private final PlayerSlot slot;\n\n    public WirelessGridNetworkItem(INetworkItemManager handler, Player player, ItemStack stack, PlayerSlot slot) {\n        this.handler = handler;\n        this.player = player;\n        this.stack = stack;\n        this.slot = slot;\n    }\n\n    @Override\n    public Player getPlayer() {\n        return player;\n    }\n\n    @Override\n    public boolean onOpen(INetwork network) {\n        IEnergyStorage energy = stack.getCapability(Capabilities.EnergyStorage.ITEM);\n\n        if (RS.SERVER_CONFIG.getWirelessGrid().getUseEnergy() &&\n            ((WirelessGridItem) stack.getItem()).getType() != WirelessGridItem.Type.CREATIVE &&\n            energy != null &&\n            energy.getEnergyStored() <= RS.SERVER_CONFIG.getWirelessGrid().getOpenUsage()) {\n            sendOutOfEnergyMessage();\n\n            return false;\n        }\n\n        if (!network.getSecurityManager().hasPermission(Permission.MODIFY, player)) {\n            LevelUtils.sendNoPermissionMessage(player);\n\n            return false;\n        }\n\n        API.instance().getGridManager().openGrid(WirelessGridGridFactory.ID, (ServerPlayer) player, stack, slot);\n\n        drainEnergy(RS.SERVER_CONFIG.getWirelessGrid().getOpenUsage());\n\n        return true;\n    }\n\n    @Override\n    public void drainEnergy(int energy) {\n        if (RS.SERVER_CONFIG.getWirelessGrid().getUseEnergy() && ((WirelessGridItem) stack.getItem()).getType() != WirelessGridItem.Type.CREATIVE) {\n            IEnergyStorage energyStorage = stack.getCapability(Capabilities.EnergyStorage.ITEM);\n            if (energyStorage != null) {\n                energyStorage.extractEnergy(energy, false);\n\n                if (energyStorage.getEnergyStored() <= 0) {\n                    handler.close(player);\n\n                    player.closeContainer();\n\n                    sendOutOfEnergyMessage();\n                }\n            }\n        }\n    }\n\n    private void sendOutOfEnergyMessage() {\n        player.sendSystemMessage(Component.translatable(\"misc.refinedstorage.network_item.out_of_energy\", Component.translatable(stack.getItem().getDescriptionId())));\n    }\n}"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/CableNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.node.ICoverable;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverType;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\n\npublic class CableNetworkNode extends NetworkNode implements ICoverable {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"cable\");\n\n    private final CoverManager coverManager;\n\n    public CableNetworkNode(Level level, BlockPos pos) {\n        super(level, pos);\n        this.coverManager = new CoverManager(this);\n    }\n\n    @Override\n    public boolean canConduct(Direction direction) {\n        return !coverManager.hasCover(direction) || coverManager.getCover(direction).getType() == CoverType.HOLLOW;\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        return RS.SERVER_CONFIG.getCable().getUsage();\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    @Override\n    public CoverManager getCoverManager() {\n        return coverManager;\n    }\n\n    @Override\n    public void read(CompoundTag tag) {\n        if (tag.contains(CoverManager.NBT_COVER_MANAGER)) {\n            this.coverManager.readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER));\n        }\n        super.read(tag);\n    }\n\n    @Override\n    public CompoundTag write(CompoundTag tag) {\n        tag.put(CoverManager.NBT_COVER_MANAGER, this.coverManager.writeToNbt());\n        return super.write(tag);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/ConnectivityStateChangeCause.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\npublic enum ConnectivityStateChangeCause {\n    GRAPH_CHANGE,\n    REDSTONE_MODE_OR_NETWORK_ENERGY_CHANGE\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/ConstructorNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.node.ICoverable;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;\nimport com.refinedmods.refinedstorage.blockentity.ConstructorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IComparable;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.UpgradeItemHandler;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener;\nimport com.refinedmods.refinedstorage.item.UpgradeItem;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.core.dispenser.DefaultDispenseItemBehavior;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.entity.projectile.FireworkRocketEntity;\nimport net.minecraft.world.item.BlockItem;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.Items;\nimport net.minecraft.world.item.context.BlockPlaceContext;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.phys.BlockHitResult;\nimport net.minecraft.world.phys.Vec3;\nimport net.neoforged.neoforge.common.CommonHooks;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.fluids.FluidType;\nimport net.neoforged.neoforge.fluids.FluidUtil;\nimport net.neoforged.neoforge.fluids.capability.IFluidHandler;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\npublic class ConstructorNetworkNode extends NetworkNode implements IComparable, IType, ICoverable {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"constructor\");\n\n    private static final String NBT_COMPARE = \"Compare\";\n    private static final String NBT_TYPE = \"Type\";\n    private static final String NBT_DROP = \"Drop\";\n    private static final String NBT_FLUID_FILTERS = \"FluidFilters\";\n\n    private static final int BASE_SPEED = 20;\n\n    private final BaseItemHandler itemFilters = new BaseItemHandler(1).addListener(new NetworkNodeInventoryListener(this));\n    private final FluidInventory fluidFilters = new FluidInventory(1)\n        .addListener(new NetworkNodeFluidInventoryListener(this));\n\n    private final UpgradeItemHandler upgrades = (UpgradeItemHandler) new UpgradeItemHandler(4, UpgradeItem.Type.SPEED, UpgradeItem.Type.CRAFTING, UpgradeItem.Type.STACK)\n        .addListener(new NetworkNodeInventoryListener(this));\n    private final CoverManager coverManager;\n    private int compare = IComparer.COMPARE_NBT;\n    private int type = IType.ITEMS;\n    private boolean drop = false;\n\n    public ConstructorNetworkNode(Level level, BlockPos pos) {\n        super(level, pos);\n        this.coverManager = new CoverManager(this);\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        return RS.SERVER_CONFIG.getConstructor().getUsage() + upgrades.getEnergyUsage();\n    }\n\n    @Override\n    public void update() {\n        super.update();\n\n        if (canUpdate() && ticks % upgrades.getSpeed(BASE_SPEED, 4) == 0 && level.isLoaded(pos)) {\n            if (type == IType.ITEMS && !itemFilters.getStackInSlot(0).isEmpty()) {\n                ItemStack stack = itemFilters.getStackInSlot(0);\n\n                if (drop) {\n                    extractAndDropItem(stack);\n                } else if (stack.getItem() == Items.FIREWORK_ROCKET) {\n                    extractAndSpawnFireworks(stack);\n                } else if (stack.getItem() instanceof BlockItem) {\n                    extractAndPlaceBlock(stack);\n                }\n            } else if (type == IType.FLUIDS && !fluidFilters.getFluid(0).isEmpty()) {\n                extractAndPlaceFluid(fluidFilters.getFluid(0));\n            }\n        }\n    }\n\n    private void extractAndPlaceFluid(FluidStack stack) {\n        BlockPos front = pos.relative(getDirection());\n\n        if (network.extractFluid(stack, FluidType.BUCKET_VOLUME, compare, Action.SIMULATE).getAmount() < FluidType.BUCKET_VOLUME) {\n            if (upgrades.hasUpgrade(UpgradeItem.Type.CRAFTING)) {\n                network.getCraftingManager().request(this, stack, FluidType.BUCKET_VOLUME);\n            }\n        } else if (!level.getBlockState(front).getFluidState().isSource()) {\n            FluidUtil.tryPlaceFluid(LevelUtils.getFakePlayer((ServerLevel) level, getOwner()), level, InteractionHand.MAIN_HAND, front, new NetworkFluidHandler(StackUtils.copy(stack, FluidType.BUCKET_VOLUME)), stack);\n        }\n    }\n\n    private void extractAndPlaceBlock(ItemStack stack) {\n        ItemStack took = network.extractItem(stack, 1, compare, Action.SIMULATE);\n        if (!took.isEmpty()) {\n            // We have to copy took as the forge hook clears the item.\n            final ItemStack tookCopy = took.copy();\n            BlockPlaceContext ctx = new ConstructorBlockItemUseContext(\n                level,\n                LevelUtils.getFakePlayer((ServerLevel) level, getOwner()),\n                InteractionHand.MAIN_HAND,\n                took,\n                new BlockHitResult(Vec3.ZERO, getDirection(), pos, false)\n            );\n\n            InteractionResult result = CommonHooks.onPlaceItemIntoWorld(ctx);\n            if (result.consumesAction()) {\n                network.extractItem(tookCopy, 1, Action.PERFORM);\n            }\n        } else if (upgrades.hasUpgrade(UpgradeItem.Type.CRAFTING)) {\n            ItemStack craft = itemFilters.getStackInSlot(0);\n\n            network.getCraftingManager().request(this, craft, 1);\n        }\n    }\n\n    private void extractAndDropItem(ItemStack stack) {\n        int dropCount = Math.min(upgrades.getStackInteractCount(), stack.getMaxStackSize());\n        ItemStack took = network.extractItem(stack, dropCount, compare, Action.PERFORM);\n\n        if (!took.isEmpty()) {\n            DefaultDispenseItemBehavior.spawnItem(level, took, 6, getDirection(), new Vec3(getDispensePositionX(), getDispensePositionY(), getDispensePositionZ()));\n        } else if (upgrades.hasUpgrade(UpgradeItem.Type.CRAFTING)) {\n            network.getCraftingManager().request(this, stack, 1);\n        }\n    }\n\n    private void extractAndSpawnFireworks(ItemStack stack) {\n        ItemStack took = network.extractItem(stack, 1, compare, Action.PERFORM);\n\n        if (!took.isEmpty()) {\n            level.addFreshEntity(new FireworkRocketEntity(level, getDispensePositionX(), getDispensePositionY(), getDispensePositionZ(), took));\n        }\n    }\n\n    private double getDispensePositionX() {\n        return (double) pos.getX() + 0.5D + 0.8D * (double) getDirection().getStepX();\n    }\n\n    private double getDispensePositionY() {\n        return (double) pos.getY() + (getDirection() == Direction.DOWN ? 0.45D : 0.5D) + 0.8D * (double) getDirection().getStepY();\n    }\n\n    private double getDispensePositionZ() {\n        return (double) pos.getZ() + 0.5D + 0.8D * (double) getDirection().getStepZ();\n    }\n\n    @Override\n    public int getCompare() {\n        return compare;\n    }\n\n    @Override\n    public void setCompare(int compare) {\n        this.compare = compare;\n\n        markDirty();\n    }\n\n    @Override\n    public void read(CompoundTag tag) {\n        super.read(tag);\n\n        if (tag.contains(CoverManager.NBT_COVER_MANAGER)) {\n            this.coverManager.readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER));\n        }\n\n        StackUtils.readItems(upgrades, 1, tag);\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    @Override\n    public CompoundTag write(CompoundTag tag) {\n        super.write(tag);\n\n        tag.put(CoverManager.NBT_COVER_MANAGER, this.coverManager.writeToNbt());\n\n        StackUtils.writeItems(upgrades, 1, tag);\n\n        return tag;\n    }\n\n    @Override\n    public CompoundTag writeConfiguration(CompoundTag tag) {\n        super.writeConfiguration(tag);\n\n        tag.putInt(NBT_COMPARE, compare);\n        tag.putInt(NBT_TYPE, type);\n        tag.putBoolean(NBT_DROP, drop);\n\n        StackUtils.writeItems(itemFilters, 0, tag);\n\n        tag.put(NBT_FLUID_FILTERS, fluidFilters.writeToNbt());\n\n        return tag;\n    }\n\n    @Override\n    public void readConfiguration(CompoundTag tag) {\n        super.readConfiguration(tag);\n\n        if (tag.contains(NBT_COMPARE)) {\n            compare = tag.getInt(NBT_COMPARE);\n        }\n\n        if (tag.contains(NBT_TYPE)) {\n            type = tag.getInt(NBT_TYPE);\n        }\n\n        if (tag.contains(NBT_DROP)) {\n            drop = tag.getBoolean(NBT_DROP);\n        }\n\n        StackUtils.readItems(itemFilters, 0, tag);\n\n        if (tag.contains(NBT_FLUID_FILTERS)) {\n            fluidFilters.readFromNbt(tag.getCompound(NBT_FLUID_FILTERS));\n        }\n    }\n\n    public boolean isDrop() {\n        return drop;\n    }\n\n    public void setDrop(boolean drop) {\n        this.drop = drop;\n    }\n\n    public IItemHandler getUpgrades() {\n        return upgrades;\n    }\n\n    @Override\n    public IItemHandler getDrops() {\n        return getUpgrades();\n    }\n\n    @Override\n    public int getType() {\n        return level.isClientSide ? ConstructorBlockEntity.TYPE.getValue() : type;\n    }\n\n    @Override\n    public void setType(int type) {\n        this.type = type;\n\n        markDirty();\n    }\n\n    @Override\n    public IItemHandlerModifiable getItemFilters() {\n        return itemFilters;\n    }\n\n    @Override\n    public FluidInventory getFluidFilters() {\n        return fluidFilters;\n    }\n\n    @Override\n    public CoverManager getCoverManager() {\n        return coverManager;\n    }\n\n    private static class ConstructorBlockItemUseContext extends BlockPlaceContext {\n        public ConstructorBlockItemUseContext(Level level, @Nullable Player player, InteractionHand hand, ItemStack stack, BlockHitResult rayTraceResult) {\n            super(level, player, hand, stack, rayTraceResult);\n        }\n    }\n\n    private class NetworkFluidHandler implements IFluidHandler {\n        private final FluidStack resource;\n\n        public NetworkFluidHandler(FluidStack resource) {\n            this.resource = resource;\n        }\n\n        @Override\n        public int getTanks() {\n            throw new UnsupportedOperationException();\n        }\n\n        @Nonnull\n        @Override\n        public FluidStack getFluidInTank(int tank) {\n            throw new UnsupportedOperationException();\n        }\n\n        @Override\n        public int getTankCapacity(int tank) {\n            throw new UnsupportedOperationException();\n        }\n\n        @Override\n        public boolean isFluidValid(int tank, @Nonnull FluidStack stack) {\n            throw new UnsupportedOperationException();\n        }\n\n        @Override\n        public int fill(FluidStack resource, FluidAction action) {\n            throw new UnsupportedOperationException();\n        }\n\n        @Nonnull\n        @Override\n        public FluidStack drain(FluidStack resource, FluidAction action) {\n            return network.extractFluid(resource, resource.getAmount(), compare, action == FluidAction.SIMULATE ? Action.SIMULATE : Action.PERFORM);\n        }\n\n        @Nonnull\n        @Override\n        public FluidStack drain(int maxDrain, FluidAction action) {\n            return network.extractFluid(resource, resource.getAmount(), compare, action == FluidAction.SIMULATE ? Action.SIMULATE : Action.PERFORM);\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/CrafterManagerNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.block.CrafterManagerBlock;\nimport com.refinedmods.refinedstorage.block.NetworkNodeBlock;\nimport com.refinedmods.refinedstorage.blockentity.CrafterManagerBlockEntity;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\n\npublic class CrafterManagerNetworkNode extends NetworkNode {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"crafter_manager\");\n\n    private static final String NBT_SIZE = \"Size\";\n    private static final String NBT_SEARCH_BOX_MODE = \"SearchBoxMode\";\n\n    private int size = IGrid.SIZE_STRETCH;\n    private int searchBoxMode = IGrid.SEARCH_BOX_MODE_NORMAL;\n\n    public CrafterManagerNetworkNode(Level level, BlockPos pos) {\n        super(level, pos);\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        return RS.SERVER_CONFIG.getCrafterManager().getUsage();\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    public int getSize() {\n        return level.isClientSide ? CrafterManagerBlockEntity.SIZE.getValue() : size;\n    }\n\n    public void setSize(int size) {\n        this.size = size;\n    }\n\n    @Override\n    public CompoundTag writeConfiguration(CompoundTag tag) {\n        super.writeConfiguration(tag);\n\n        tag.putInt(NBT_SIZE, size);\n        tag.putInt(NBT_SEARCH_BOX_MODE, searchBoxMode);\n\n        return tag;\n    }\n\n    @Override\n    public void readConfiguration(CompoundTag tag) {\n        super.readConfiguration(tag);\n\n        if (tag.contains(NBT_SIZE)) {\n            size = tag.getInt(NBT_SIZE);\n        }\n\n        if (tag.contains(NBT_SEARCH_BOX_MODE)) {\n            searchBoxMode = tag.getInt(NBT_SEARCH_BOX_MODE);\n        }\n    }\n\n    public int getSearchBoxMode() {\n        return level.isClientSide ? CrafterManagerBlockEntity.SEARCH_BOX_MODE.getValue() : searchBoxMode;\n    }\n\n    public void setSearchBoxMode(int searchBoxMode) {\n        this.searchBoxMode = searchBoxMode;\n    }\n\n    public boolean isActiveOnClient() {\n        BlockState state = level.getBlockState(pos);\n\n        if (state.getBlock() instanceof CrafterManagerBlock) {\n            return state.getValue(NetworkNodeBlock.CONNECTED);\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/CrafterNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternProvider;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.UpgradeItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.validator.PatternItemValidator;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener;\nimport com.refinedmods.refinedstorage.item.UpgradeItem;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.Nameable;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.neoforged.neoforge.fluids.capability.IFluidHandler;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport net.neoforged.neoforge.items.wrapper.CombinedInvWrapper;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.UUID;\n\npublic class CrafterNetworkNode extends NetworkNode implements ICraftingPatternContainer {\n\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"crafter\");\n    private static final Component DEFAULT_NAME = Component.translatable(\"gui.refinedstorage.crafter\");\n    private static final String NBT_DISPLAY_NAME = \"DisplayName\";\n    private static final String NBT_UUID = \"CrafterUuid\";\n    private static final String NBT_MODE = \"Mode\";\n    private static final String NBT_LOCKED = \"Locked\";\n    private static final String NBT_WAS_POWERED = \"WasPowered\";\n    private final List<ICraftingPattern> patterns = new ArrayList<>();\n    private final UpgradeItemHandler upgrades = (UpgradeItemHandler) new UpgradeItemHandler(4, UpgradeItem.Type.SPEED)\n        .addListener(new NetworkNodeInventoryListener(this));\n    // Used to prevent infinite recursion on getRootContainer() when there's e.g. two crafters facing each other.\n    private boolean visited = false;\n    private final BaseItemHandler patternsInventory = new BaseItemHandler(9) {\n        @Override\n        public int getSlotLimit(int slot) {\n            return 1;\n        }\n\n        @Nonnull\n        @Override\n        public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) {\n            if (!stacks.get(slot).isEmpty()) {\n                return stack;\n            }\n\n            return super.insertItem(slot, stack, simulate);\n        }\n    }\n        .addValidator(new PatternItemValidator(level))\n        .addListener(new NetworkNodeInventoryListener(this))\n        .addListener((handler, slot, reading) -> {\n            if (!reading) {\n                if (!level.isClientSide) {\n                    invalidate();\n                }\n\n                if (network != null) {\n                    network.getCraftingManager().invalidate();\n                }\n            }\n        });\n    private CrafterMode mode = CrafterMode.IGNORE;\n    private boolean locked = false;\n    private boolean wasPowered;\n    @Nullable\n    private Component displayName;\n    @Nullable\n    private UUID uuid = null;\n\n    public CrafterNetworkNode(Level level, BlockPos pos) {\n        super(level, pos);\n    }\n\n    private void invalidate() {\n        patterns.clear();\n\n        for (int i = 0; i < patternsInventory.getSlots(); ++i) {\n            ItemStack patternStack = patternsInventory.getStackInSlot(i);\n\n            if (!patternStack.isEmpty()) {\n                ICraftingPattern pattern = ((ICraftingPatternProvider) patternStack.getItem()).create(level, patternStack, this);\n\n                if (pattern.isValid()) {\n                    patterns.add(pattern);\n                }\n            }\n        }\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        return RS.SERVER_CONFIG.getCrafter().getUsage() + upgrades.getEnergyUsage() + (RS.SERVER_CONFIG.getCrafter().getPatternUsage() * patterns.size());\n    }\n\n    @Override\n    public void update() {\n        super.update();\n\n        if (ticks == 1) {\n            invalidate();\n        }\n\n        if (mode == CrafterMode.PULSE_INSERTS_NEXT_SET && level.isLoaded(pos)) {\n            if (level.hasNeighborSignal(pos)) {\n                this.wasPowered = true;\n\n                markDirty();\n            } else if (wasPowered) {\n                this.wasPowered = false;\n                this.locked = false;\n\n                markDirty();\n            }\n        }\n    }\n\n    @Override\n    protected void onConnectedStateChange(INetwork network, boolean state, ConnectivityStateChangeCause cause) {\n        super.onConnectedStateChange(network, state, cause);\n\n        network.getCraftingManager().invalidate();\n    }\n\n    @Override\n    public void onDisconnected(INetwork network) {\n        super.onDisconnected(network);\n\n        network.getCraftingManager().getTasks().stream()\n            .filter(task -> task.getPattern().getContainer().getPosition().equals(pos))\n            .forEach(task -> network.getCraftingManager().cancel(task.getId()));\n    }\n\n    @Override\n    public void onDirectionChanged(Direction direction) {\n        super.onDirectionChanged(direction);\n\n        if (network != null) {\n            network.getCraftingManager().invalidate();\n        }\n\n        level.invalidateCapabilities(pos);\n    }\n\n    @Override\n    public void read(CompoundTag tag) {\n        super.read(tag);\n\n        StackUtils.readItems(patternsInventory, 0, tag);\n\n        invalidate();\n\n        StackUtils.readItems(upgrades, 1, tag);\n\n        if (tag.contains(NBT_DISPLAY_NAME)) {\n            displayName = Component.Serializer.fromJson(tag.getString(NBT_DISPLAY_NAME));\n        }\n\n        if (tag.hasUUID(NBT_UUID)) {\n            uuid = tag.getUUID(NBT_UUID);\n        }\n\n        if (tag.contains(NBT_MODE)) {\n            mode = CrafterMode.getById(tag.getInt(NBT_MODE));\n        }\n\n        if (tag.contains(NBT_LOCKED)) {\n            locked = tag.getBoolean(NBT_LOCKED);\n        }\n\n        if (tag.contains(NBT_WAS_POWERED)) {\n            wasPowered = tag.getBoolean(NBT_WAS_POWERED);\n        }\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    @Override\n    public CompoundTag write(CompoundTag tag) {\n        super.write(tag);\n\n        StackUtils.writeItems(patternsInventory, 0, tag);\n        StackUtils.writeItems(upgrades, 1, tag);\n\n        if (displayName != null) {\n            tag.putString(NBT_DISPLAY_NAME, Component.Serializer.toJson(displayName));\n        }\n\n        if (uuid != null) {\n            tag.putUUID(NBT_UUID, uuid);\n        }\n\n        tag.putInt(NBT_MODE, mode.ordinal());\n        tag.putBoolean(NBT_LOCKED, locked);\n        tag.putBoolean(NBT_WAS_POWERED, wasPowered);\n\n        return tag;\n    }\n\n    @Override\n    public int getUpdateInterval() {\n        switch (upgrades.getUpgradeCount(UpgradeItem.Type.SPEED)) {\n            case 0:\n                return 10;\n            case 1:\n                return 8;\n            case 2:\n                return 6;\n            case 3:\n                return 4;\n            case 4:\n                return 2;\n            default:\n                return 0;\n        }\n    }\n\n    @Override\n    public int getMaximumSuccessfulCraftingUpdates() {\n        switch (upgrades.getUpgradeCount(UpgradeItem.Type.SPEED)) {\n            case 0:\n                return 1;\n            case 1:\n                return 2;\n            case 2:\n                return 3;\n            case 3:\n                return 4;\n            case 4:\n                return 5;\n            default:\n                return 1;\n        }\n    }\n\n    @Override\n    @Nullable\n    public IItemHandler getConnectedInventory() {\n        ICraftingPatternContainer proxy = getRootContainer();\n        if (proxy == null) {\n            return null;\n        }\n        return LevelUtils.getItemHandler(level, proxy.getPosition().relative(proxy.getDirection()), proxy.getDirection().getOpposite());\n    }\n\n    @Nullable\n    @Override\n    public IFluidHandler getConnectedFluidInventory() {\n        ICraftingPatternContainer proxy = getRootContainer();\n        if (proxy == null) {\n            return null;\n        }\n        return LevelUtils.getFluidHandler(level, proxy.getPosition().relative(proxy.getDirection()), proxy.getDirection().getOpposite());\n    }\n\n    @Override\n    @Nullable\n    public BlockEntity getConnectedBlockEntity() {\n        ICraftingPatternContainer proxy = getRootContainer();\n        if (proxy == null) {\n            return null;\n        }\n\n        return proxy.getFacingBlockEntity();\n    }\n\n    @Override\n    public List<ICraftingPattern> getPatterns() {\n        return patterns;\n    }\n\n    @Override\n    @Nullable\n    public IItemHandlerModifiable getPatternInventory() {\n        return patternsInventory;\n    }\n\n    @Override\n    @Nullable\n    public Component getCustomName() {\n        return displayName;\n    }\n\n    @Override\n    public Component getName() {\n        ICraftingPatternContainer root = getRootContainer();\n        if (root != null) {\n            Component displayNameOfRoot = root.getCustomName();\n            if (displayNameOfRoot != null) {\n                return displayNameOfRoot;\n            }\n        }\n\n        BlockEntity facing = getConnectedBlockEntity();\n\n        if (facing instanceof Nameable && ((Nameable) facing).getName() != null) {\n            return ((Nameable) facing).getName();\n        }\n\n        if (facing != null) {\n            return Component.translatable(level.getBlockState(facing.getBlockPos()).getBlock().getDescriptionId());\n        }\n\n        return DEFAULT_NAME;\n    }\n\n    @Nullable\n    public Component getDisplayName() {\n        return displayName;\n    }\n\n    public void setDisplayName(Component displayName) {\n        this.displayName = displayName;\n    }\n\n    @Override\n    public BlockPos getPosition() {\n        return pos;\n    }\n\n    public CrafterMode getMode() {\n        return mode;\n    }\n\n    public void setMode(CrafterMode mode) {\n        this.mode = mode;\n        this.wasPowered = false;\n        this.locked = false;\n\n        this.markDirty();\n    }\n\n    public IItemHandler getUpgrades() {\n        return upgrades;\n    }\n\n    @Override\n    public IItemHandler getDrops() {\n        return new CombinedInvWrapper(patternsInventory, upgrades);\n    }\n\n    @Override\n    @Nullable\n    public ICraftingPatternContainer getRootContainer() {\n        if (visited) {\n            return null;\n        }\n\n        INetworkNode facing = API.instance().getNetworkNodeManager((ServerLevel) level).getNode(pos.relative(getDirection()));\n        if (!(facing instanceof ICraftingPatternContainer) || facing.getNetwork() != network) {\n            return this;\n        }\n\n        visited = true;\n        ICraftingPatternContainer facingContainer = ((ICraftingPatternContainer) facing).getRootContainer();\n        visited = false;\n\n        return facingContainer;\n    }\n\n    public Optional<ICraftingPatternContainer> getRootContainerNotSelf() {\n        ICraftingPatternContainer root = getRootContainer();\n\n        if (root != null && root != this) {\n            return Optional.of(root);\n        }\n\n        return Optional.empty();\n    }\n\n    @Override\n    public UUID getUuid() {\n        if (this.uuid == null) {\n            this.uuid = UUID.randomUUID();\n\n            markDirty();\n        }\n\n        return uuid;\n    }\n\n    @Override\n    public boolean isLocked() {\n        Optional<ICraftingPatternContainer> root = getRootContainerNotSelf();\n        if (root.isPresent()) {\n            return root.get().isLocked();\n        }\n\n        switch (mode) {\n            case IGNORE:\n                return false;\n            case SIGNAL_LOCKS_AUTOCRAFTING:\n                return level.hasNeighborSignal(pos);\n            case SIGNAL_UNLOCKS_AUTOCRAFTING:\n                return !level.hasNeighborSignal(pos);\n            case PULSE_INSERTS_NEXT_SET:\n                return locked;\n            default:\n                return false;\n        }\n    }\n\n    @Override\n    public void unlock() {\n        locked = false;\n    }\n\n    @Override\n    public void onUsedForProcessing() {\n        Optional<ICraftingPatternContainer> root = getRootContainerNotSelf();\n        if (root.isPresent()) {\n            root.get().onUsedForProcessing();\n\n            return;\n        }\n\n        if (mode == CrafterMode.PULSE_INSERTS_NEXT_SET) {\n            this.locked = true;\n\n            markDirty();\n        }\n    }\n\n    public enum CrafterMode {\n        IGNORE,\n        SIGNAL_UNLOCKS_AUTOCRAFTING,\n        SIGNAL_LOCKS_AUTOCRAFTING,\n        PULSE_INSERTS_NEXT_SET;\n\n        public static CrafterMode getById(int id) {\n            if (id >= 0 && id < values().length) {\n                return values()[id];\n            }\n\n            return IGNORE;\n        }\n    }\n\n\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/CraftingMonitorNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask;\nimport com.refinedmods.refinedstorage.block.CraftingMonitorBlock;\nimport com.refinedmods.refinedstorage.block.NetworkNodeBlock;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.craftingmonitor.CraftingMonitorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.craftingmonitor.ICraftingMonitor;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\n\nimport javax.annotation.Nullable;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Optional;\nimport java.util.UUID;\n\npublic class CraftingMonitorNetworkNode extends NetworkNode implements ICraftingMonitor {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"crafting_monitor\");\n\n    private static final String NBT_TAB_SELECTED = \"TabSelected\";\n    private static final String NBT_TAB_PAGE = \"TabPage\";\n\n    private Optional<UUID> tabSelected = Optional.empty();\n    private int tabPage;\n\n    public CraftingMonitorNetworkNode(Level level, BlockPos pos) {\n        super(level, pos);\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        return RS.SERVER_CONFIG.getCraftingMonitor().getUsage();\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    @Override\n    public Component getTitle() {\n        return Component.translatable(\"gui.refinedstorage.crafting_monitor\");\n    }\n\n    @Override\n    public void onCancelled(ServerPlayer player, @Nullable UUID id) {\n        if (network != null) {\n            network.getItemGridHandler().onCraftingCancelRequested(player, id);\n        }\n    }\n\n    @Override\n    public BlockEntitySynchronizationParameter<Integer, ?> getRedstoneModeParameter() {\n        return NetworkNodeBlockEntity.REDSTONE_MODE;\n    }\n\n    @Override\n    public Collection<ICraftingTask> getTasks() {\n        return network != null ? network.getCraftingManager().getTasks() : Collections.emptyList();\n    }\n\n    @Nullable\n    @Override\n    public ICraftingManager getCraftingManager() {\n        return network != null ? network.getCraftingManager() : null;\n    }\n\n    @Override\n    public boolean isActiveOnClient() {\n        BlockState state = level.getBlockState(pos);\n\n        if (state.getBlock() instanceof CraftingMonitorBlock) {\n            return state.getValue(NetworkNodeBlock.CONNECTED);\n        }\n\n        return false;\n    }\n\n    @Override\n    public CompoundTag write(CompoundTag tag) {\n        super.write(tag);\n\n        tag.putInt(NBT_TAB_PAGE, tabPage);\n\n        tabSelected.ifPresent(uuid -> tag.putUUID(NBT_TAB_SELECTED, uuid));\n\n        return tag;\n    }\n\n    @Override\n    public void read(CompoundTag tag) {\n        super.read(tag);\n\n        if (tag.contains(NBT_TAB_PAGE)) {\n            tabPage = tag.getInt(NBT_TAB_PAGE);\n        }\n\n        if (tag.hasUUID(NBT_TAB_SELECTED)) {\n            tabSelected = Optional.of(tag.getUUID(NBT_TAB_SELECTED));\n        }\n    }\n\n    @Override\n    public void onClosed(Player player) {\n        // NO OP\n    }\n\n    @Override\n    public Optional<UUID> getTabSelected() {\n        return level.isClientSide ? CraftingMonitorBlockEntity.TAB_SELECTED.getValue() : tabSelected;\n    }\n\n    public void setTabSelected(Optional<UUID> tabSelected) {\n        this.tabSelected = tabSelected;\n    }\n\n    @Override\n    public int getTabPage() {\n        return level.isClientSide ? CraftingMonitorBlockEntity.TAB_PAGE.getValue() : tabPage;\n    }\n\n    public void setTabPage(int tabPage) {\n        this.tabPage = tabPage;\n    }\n\n    @Override\n    public void onTabSelectionChanged(Optional<UUID> tab) {\n        BlockEntitySynchronizationManager.setParameter(CraftingMonitorBlockEntity.TAB_SELECTED, tab);\n    }\n\n    @Override\n    public void onTabPageChanged(int page) {\n        if (page >= 0) {\n            BlockEntitySynchronizationManager.setParameter(CraftingMonitorBlockEntity.TAB_PAGE, page);\n        }\n    }\n\n    @Override\n    public int getSlotId() {\n        return -1;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/DestructorNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.node.ICoverable;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;\nimport com.refinedmods.refinedstorage.blockentity.DestructorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IComparable;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.UpgradeItemHandler;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener;\nimport com.refinedmods.refinedstorage.item.UpgradeItem;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.Containers;\nimport net.minecraft.world.entity.Entity;\nimport net.minecraft.world.entity.item.ItemEntity;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.Items;\nimport net.minecraft.world.item.enchantment.Enchantments;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.Block;\nimport net.minecraft.world.level.block.Blocks;\nimport net.minecraft.world.level.block.LiquidBlock;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.level.material.Fluid;\nimport net.minecraft.world.phys.AABB;\nimport net.minecraft.world.phys.BlockHitResult;\nimport net.minecraft.world.phys.Vec3;\nimport net.neoforged.neoforge.common.NeoForge;\nimport net.neoforged.neoforge.event.level.BlockEvent;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.fluids.FluidType;\nimport net.neoforged.neoforge.fluids.IFluidBlock;\nimport net.neoforged.neoforge.fluids.capability.IFluidHandler;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport java.util.List;\n\npublic class DestructorNetworkNode extends NetworkNode implements IComparable, IWhitelistBlacklist, IType, ICoverable {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"destructor\");\n\n    private static final String NBT_COMPARE = \"Compare\";\n    private static final String NBT_MODE = \"Mode\";\n    private static final String NBT_TYPE = \"Type\";\n    private static final String NBT_PICKUP = \"Pickup\";\n    private static final String NBT_FLUID_FILTERS = \"FluidFilters\";\n\n    private static final int BASE_SPEED = 20;\n\n    private final BaseItemHandler itemFilters = new BaseItemHandler(9).addListener(new NetworkNodeInventoryListener(this));\n    private final FluidInventory fluidFilters = new FluidInventory(9).addListener(new NetworkNodeFluidInventoryListener(this));\n    private final CoverManager coverManager;\n    private int compare = IComparer.COMPARE_NBT;\n    private final UpgradeItemHandler upgrades = (UpgradeItemHandler) new UpgradeItemHandler(4, UpgradeItem.Type.SPEED, UpgradeItem.Type.SILK_TOUCH, UpgradeItem.Type.FORTUNE_1, UpgradeItem.Type.FORTUNE_2, UpgradeItem.Type.FORTUNE_3)\n        .addListener(new NetworkNodeInventoryListener(this))\n        .addListener((handler, slot, reading) -> tool = createTool());\n    private int mode = IWhitelistBlacklist.BLACKLIST;\n    private int type = IType.ITEMS;\n    private boolean pickupItem = false;\n\n    public DestructorNetworkNode(Level level, BlockPos pos) {\n        super(level, pos);\n        this.coverManager = new CoverManager(this);\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        return RS.SERVER_CONFIG.getDestructor().getUsage() + upgrades.getEnergyUsage();\n    }\n\n    @Override\n    public void update() {\n        super.update();\n\n        if (canUpdate() && ticks % upgrades.getSpeed(BASE_SPEED, 4) == 0 && level.isLoaded(pos)) {\n            if (type == IType.ITEMS) {\n                if (pickupItem) {\n                    pickupItems();\n                } else {\n                    breakBlock();\n                }\n            } else if (type == IType.FLUIDS) {\n                breakFluid();\n            }\n        }\n    }\n\n    private ItemStack tool = createTool();\n\n    private void pickupItems() {\n        BlockPos front = pos.relative(getDirection());\n        if (!level.isLoaded(front)) {\n            return;\n        }\n\n        List<ItemEntity> droppedItems = level.getEntitiesOfClass(ItemEntity.class, new AABB(front));\n\n        for (ItemEntity entity : droppedItems) {\n\n            if (entity.isRemoved()) {\n                continue;\n            }\n\n            ItemStack droppedItem = entity.getItem();\n\n            if (IWhitelistBlacklist.acceptsItem(itemFilters, mode, compare, droppedItem) &&\n                network.insertItem(droppedItem, droppedItem.getCount(), Action.SIMULATE).isEmpty()) {\n                network.insertItemTracked(droppedItem.copy(), droppedItem.getCount());\n\n                entity.remove(Entity.RemovalReason.DISCARDED);\n\n                break;\n            }\n        }\n    }\n\n    private void breakBlock() {\n        BlockPos front = pos.relative(getDirection());\n        if (!level.isLoaded(front)) {\n            return;\n        }\n        BlockState frontBlockState = level.getBlockState(front);\n        Block frontBlock = frontBlockState.getBlock();\n        ItemStack frontStack = frontBlock.getCloneItemStack(\n            frontBlockState,\n            new BlockHitResult(Vec3.ZERO, getDirection().getOpposite(), front, false),\n            level,\n            front,\n            LevelUtils.getFakePlayer((ServerLevel) level, getOwner())\n        );\n\n        if (!frontStack.isEmpty() &&\n            IWhitelistBlacklist.acceptsItem(itemFilters, mode, compare, frontStack) &&\n            frontBlockState.getDestroySpeed(level, front) != -1.0) {\n            List<ItemStack> drops = Block.getDrops(\n                frontBlockState,\n                (ServerLevel) level,\n                front,\n                level.getBlockEntity(front),\n                LevelUtils.getFakePlayer((ServerLevel) level, getOwner()),\n                tool\n            );\n\n            for (ItemStack drop : drops) {\n                if (!network.insertItem(drop, drop.getCount(), Action.SIMULATE).isEmpty()) {\n                    return;\n                }\n            }\n\n            BlockEvent.BreakEvent e = new BlockEvent.BreakEvent(level, front, frontBlockState, LevelUtils.getFakePlayer((ServerLevel) level, getOwner()));\n\n            if (!NeoForge.EVENT_BUS.post(e).isCanceled()) {\n                frontBlock.playerWillDestroy(level, front, frontBlockState, LevelUtils.getFakePlayer((ServerLevel) level, getOwner()));\n\n                level.removeBlock(front, false);\n\n                for (ItemStack drop : drops) {\n                    // We check if the controller isn't null here because when a destructor faces a node and removes it\n                    // it will essentially remove this block itself from the network without knowing\n                    if (network == null) {\n                        Containers.dropItemStack(level, front.getX(), front.getY(), front.getZ(), drop);\n                    } else {\n                        network.insertItemTracked(drop, drop.getCount());\n                    }\n                }\n            }\n        }\n    }\n\n    private void breakFluid() {\n        BlockPos front = pos.relative(getDirection());\n        if (!level.isLoaded(front)) {\n            return;\n        }\n\n        BlockState frontBlockState = level.getBlockState(front);\n        Block frontBlock = frontBlockState.getBlock();\n\n        if (frontBlock instanceof LiquidBlock) {\n            // @Volatile: Logic from FlowingFluidBlock#pickupFluid\n            if (frontBlockState.getValue(LiquidBlock.LEVEL) == 0) {\n                Fluid fluid = ((LiquidBlock) frontBlock).getFluid();\n\n                FluidStack stack = new FluidStack(fluid, FluidType.BUCKET_VOLUME);\n\n                if (IWhitelistBlacklist.acceptsFluid(fluidFilters, mode, compare, stack) &&\n                    network.insertFluid(stack, stack.getAmount(), Action.SIMULATE).isEmpty()) {\n                    network.insertFluidTracked(stack, stack.getAmount());\n\n                    level.setBlock(front, Blocks.AIR.defaultBlockState(), 11);\n                }\n            }\n        } else if (frontBlock instanceof IFluidBlock) {\n            IFluidBlock fluidBlock = (IFluidBlock) frontBlock;\n\n            if (fluidBlock.canDrain(level, front)) {\n                FluidStack simulatedDrain = fluidBlock.drain(level, front, IFluidHandler.FluidAction.SIMULATE);\n\n                if (IWhitelistBlacklist.acceptsFluid(fluidFilters, mode, compare, simulatedDrain) &&\n                    network.insertFluid(simulatedDrain, simulatedDrain.getAmount(), Action.SIMULATE).isEmpty()) {\n                    FluidStack drained = fluidBlock.drain(level, front, IFluidHandler.FluidAction.EXECUTE);\n\n                    network.insertFluidTracked(drained, drained.getAmount());\n                }\n            }\n        }\n    }\n\n    private ItemStack createTool() {\n        ItemStack newTool = new ItemStack(Items.DIAMOND_PICKAXE);\n\n        if (upgrades.hasUpgrade(UpgradeItem.Type.SILK_TOUCH)) {\n            newTool.enchant(Enchantments.SILK_TOUCH, 1);\n        } else if (upgrades.hasUpgrade(UpgradeItem.Type.FORTUNE_3)) {\n            newTool.enchant(Enchantments.BLOCK_FORTUNE, 3);\n        } else if (upgrades.hasUpgrade(UpgradeItem.Type.FORTUNE_2)) {\n            newTool.enchant(Enchantments.BLOCK_FORTUNE, 2);\n        } else if (upgrades.hasUpgrade(UpgradeItem.Type.FORTUNE_1)) {\n            newTool.enchant(Enchantments.BLOCK_FORTUNE, 1);\n        }\n\n        return newTool;\n    }\n\n    @Override\n    public int getCompare() {\n        return compare;\n    }\n\n    @Override\n    public void setCompare(int compare) {\n        this.compare = compare;\n\n        markDirty();\n    }\n\n    @Override\n    public int getWhitelistBlacklistMode() {\n        return mode;\n    }\n\n    @Override\n    public void setWhitelistBlacklistMode(int mode) {\n        this.mode = mode;\n\n        markDirty();\n    }\n\n    @Override\n    public void read(CompoundTag tag) {\n        super.read(tag);\n\n        if (tag.contains(CoverManager.NBT_COVER_MANAGER)) {\n            this.coverManager.readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER));\n        }\n\n        StackUtils.readItems(upgrades, 1, tag);\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    @Override\n    public CompoundTag write(CompoundTag tag) {\n        super.write(tag);\n\n        tag.put(CoverManager.NBT_COVER_MANAGER, this.coverManager.writeToNbt());\n\n        StackUtils.writeItems(upgrades, 1, tag);\n\n        return tag;\n    }\n\n    @Override\n    public CompoundTag writeConfiguration(CompoundTag tag) {\n        super.writeConfiguration(tag);\n\n        tag.putInt(NBT_COMPARE, compare);\n        tag.putInt(NBT_MODE, mode);\n        tag.putInt(NBT_TYPE, type);\n        tag.putBoolean(NBT_PICKUP, pickupItem);\n\n        StackUtils.writeItems(itemFilters, 0, tag);\n\n        tag.put(NBT_FLUID_FILTERS, fluidFilters.writeToNbt());\n\n        return tag;\n    }\n\n    @Override\n    public void readConfiguration(CompoundTag tag) {\n        super.readConfiguration(tag);\n\n        if (tag.contains(NBT_COMPARE)) {\n            compare = tag.getInt(NBT_COMPARE);\n        }\n\n        if (tag.contains(NBT_MODE)) {\n            mode = tag.getInt(NBT_MODE);\n        }\n\n        if (tag.contains(NBT_TYPE)) {\n            type = tag.getInt(NBT_TYPE);\n        }\n\n        if (tag.contains(NBT_PICKUP)) {\n            pickupItem = tag.getBoolean(NBT_PICKUP);\n        }\n\n        StackUtils.readItems(itemFilters, 0, tag);\n\n        if (tag.contains(NBT_FLUID_FILTERS)) {\n            fluidFilters.readFromNbt(tag.getCompound(NBT_FLUID_FILTERS));\n        }\n    }\n\n    public IItemHandler getUpgrades() {\n        return upgrades;\n    }\n\n    @Override\n    public IItemHandler getDrops() {\n        return getUpgrades();\n    }\n\n    @Override\n    public int getType() {\n        return level.isClientSide ? DestructorBlockEntity.TYPE.getValue() : type;\n    }\n\n    @Override\n    public void setType(int type) {\n        this.type = type;\n\n        markDirty();\n    }\n\n    @Override\n    public IItemHandlerModifiable getItemFilters() {\n        return itemFilters;\n    }\n\n    @Override\n    public FluidInventory getFluidFilters() {\n        return fluidFilters;\n    }\n\n    public boolean isPickupItem() {\n        return pickupItem;\n    }\n\n    public void setPickupItem(boolean pickupItem) {\n        this.pickupItem = pickupItem;\n    }\n\n    @Override\n    public CoverManager getCoverManager() {\n        return coverManager;\n    }\n\n\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/DetectorNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.block.DetectorBlock;\nimport com.refinedmods.refinedstorage.blockentity.DetectorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IComparable;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.blockentity.config.RedstoneMode;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport javax.annotation.Nullable;\n\npublic class DetectorNetworkNode extends NetworkNode implements IComparable, IType {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"detector\");\n    public static final int MODE_UNDER = 0;\n    public static final int MODE_EQUAL = 1;\n    public static final int MODE_ABOVE = 2;\n    private static final int SPEED = 5;\n    private static final String NBT_COMPARE = \"Compare\";\n    private static final String NBT_MODE = \"Mode\";\n    private static final String NBT_AMOUNT = \"Amount\";\n    private static final String NBT_TYPE = \"Type\";\n    private static final String NBT_FLUID_FILTERS = \"FluidFilters\";\n\n    private final BaseItemHandler itemFilters = new BaseItemHandler(1).addListener(new NetworkNodeInventoryListener(this));\n    private final FluidInventory fluidFilters = new FluidInventory(1).addListener(new NetworkNodeFluidInventoryListener(this));\n\n    private int compare = IComparer.COMPARE_NBT;\n    private int type = IType.ITEMS;\n    private int mode = MODE_EQUAL;\n    private int amount = 0;\n\n    private boolean powered = false;\n    private boolean wasPowered;\n\n    public DetectorNetworkNode(Level level, BlockPos pos) {\n        super(level, pos);\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        return RS.SERVER_CONFIG.getDetector().getUsage();\n    }\n\n    @Override\n    public void update() {\n        super.update();\n\n        if (powered != wasPowered && level.isLoaded(pos)) {\n            wasPowered = powered;\n\n            level.setBlockAndUpdate(pos, level.getBlockState(pos).setValue(DetectorBlock.POWERED, powered));\n            level.updateNeighborsAt(pos, level.getBlockState(pos).getBlock());\n        }\n\n        if (canUpdate() && ticks % SPEED == 0) {\n            if (type == IType.ITEMS) {\n                ItemStack slot = itemFilters.getStackInSlot(0);\n\n                if (!slot.isEmpty()) {\n                    ItemStack stack = network.getItemStorageCache().getList().get(slot, compare);\n\n                    powered = isPowered(stack == null ? null : stack.getCount());\n                } else {\n                    powered = isPowered(network.getItemStorageCache().getList().getStacks().stream().map(e -> e.getStack().getCount()).mapToInt(Number::intValue).sum());\n                }\n            } else if (type == IType.FLUIDS) {\n                FluidStack slot = fluidFilters.getFluid(0);\n\n                if (!slot.isEmpty()) {\n                    FluidStack stack = network.getFluidStorageCache().getList().get(slot, compare);\n\n                    powered = isPowered(stack == null ? null : stack.getAmount());\n                } else {\n                    powered = isPowered(network.getFluidStorageCache().getList().getStacks().stream().map(e -> e.getStack().getAmount()).mapToInt(Number::intValue).sum());\n                }\n            }\n        }\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    @Override\n    public void onConnectedStateChange(INetwork network, boolean state, ConnectivityStateChangeCause cause) {\n        super.onConnectedStateChange(network, state, cause);\n\n        if (!state) {\n            powered = false;\n        }\n    }\n\n    public boolean isPowered() {\n        return powered;\n    }\n\n    public void setPowered(boolean powered) {\n        this.powered = powered;\n    }\n\n    private boolean isPowered(@Nullable Integer size) {\n        if (size != null) {\n            switch (mode) {\n                case MODE_UNDER:\n                    return size < amount;\n                case MODE_EQUAL:\n                    return size == amount;\n                case MODE_ABOVE:\n                    return size > amount;\n                default:\n                    return false;\n            }\n        } else {\n            if (mode == MODE_UNDER && amount != 0) {\n                return true;\n            }\n\n            return mode == MODE_EQUAL && amount == 0;\n        }\n    }\n\n    @Override\n    public int getCompare() {\n        return compare;\n    }\n\n    @Override\n    public void setCompare(int compare) {\n        this.compare = compare;\n\n        markDirty();\n    }\n\n    public int getMode() {\n        return mode;\n    }\n\n    public void setMode(int mode) {\n        this.mode = mode;\n    }\n\n    public int getAmount() {\n        return amount;\n    }\n\n    public void setAmount(int amount) {\n        this.amount = amount;\n    }\n\n    @Override\n    public CompoundTag writeConfiguration(CompoundTag tag) {\n        super.writeConfiguration(tag);\n\n        tag.putInt(NBT_COMPARE, compare);\n        tag.putInt(NBT_MODE, mode);\n        tag.putInt(NBT_AMOUNT, amount);\n        tag.putInt(NBT_TYPE, type);\n\n        StackUtils.writeItems(itemFilters, 0, tag);\n\n        tag.put(NBT_FLUID_FILTERS, fluidFilters.writeToNbt());\n\n        return tag;\n    }\n\n    @Override\n    public void readConfiguration(CompoundTag tag) {\n        super.readConfiguration(tag);\n\n        if (tag.contains(NBT_COMPARE)) {\n            compare = tag.getInt(NBT_COMPARE);\n        }\n\n        if (tag.contains(NBT_MODE)) {\n            mode = tag.getInt(NBT_MODE);\n        }\n\n        if (tag.contains(NBT_AMOUNT)) {\n            amount = tag.getInt(NBT_AMOUNT);\n        }\n\n        if (tag.contains(NBT_TYPE)) {\n            type = tag.getInt(NBT_TYPE);\n        }\n\n        StackUtils.readItems(itemFilters, 0, tag);\n\n        if (tag.contains(NBT_FLUID_FILTERS)) {\n            fluidFilters.readFromNbt(tag.getCompound(NBT_FLUID_FILTERS));\n        }\n    }\n\n    @Override\n    public void setRedstoneMode(RedstoneMode mode) {\n        // NO OP\n    }\n\n    @Override\n    public int getType() {\n        return level.isClientSide ? DetectorBlockEntity.TYPE.getValue() : type;\n    }\n\n    @Override\n    public void setType(int type) {\n        this.type = type;\n\n        markDirty();\n    }\n\n    @Override\n    public IItemHandlerModifiable getItemFilters() {\n        return itemFilters;\n    }\n\n    @Override\n    public FluidInventory getFluidFilters() {\n        return fluidFilters;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/DiskState.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\npublic enum DiskState {\n    NONE,\n    NORMAL,\n    DISCONNECTED,\n    NEAR_CAPACITY,\n    FULL;\n\n    public static final int DISK_NEAR_CAPACITY_THRESHOLD = 75;\n\n    public static DiskState get(int stored, int capacity) {\n        if (stored == capacity) {\n            return FULL;\n        } else if ((int) ((float) stored / (float) capacity * 100F) >= DISK_NEAR_CAPACITY_THRESHOLD) {\n            return NEAR_CAPACITY;\n        } else {\n            return NORMAL;\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/ExporterNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.node.ICoverable;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;\nimport com.refinedmods.refinedstorage.blockentity.ExporterBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IComparable;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.UpgradeItemHandler;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener;\nimport com.refinedmods.refinedstorage.item.UpgradeItem;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.fluids.FluidType;\nimport net.neoforged.neoforge.fluids.capability.IFluidHandler;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\n\npublic class ExporterNetworkNode extends NetworkNode implements IComparable, IType, ICoverable {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"exporter\");\n\n    private static final String NBT_COMPARE = \"Compare\";\n    private static final String NBT_TYPE = \"Type\";\n    private static final String NBT_FLUID_FILTERS = \"FluidFilters\";\n\n    private final BaseItemHandler itemFilters = new BaseItemHandler(9).addListener(new NetworkNodeInventoryListener(this));\n    private final FluidInventory fluidFilters = new FluidInventory(9).addListener(new NetworkNodeFluidInventoryListener(this));\n    private final CoverManager coverManager;\n    private int compare = IComparer.COMPARE_NBT;\n    private final UpgradeItemHandler upgrades = (UpgradeItemHandler) new UpgradeItemHandler(4, UpgradeItem.Type.SPEED, UpgradeItem.Type.CRAFTING, UpgradeItem.Type.STACK, UpgradeItem.Type.REGULATOR)\n        .addListener(new NetworkNodeInventoryListener(this))\n        .addListener((handler, slot, reading) -> {\n            if (!reading && !getUpgrades().hasUpgrade(UpgradeItem.Type.REGULATOR)) {\n                boolean changed = false;\n\n                for (int i = 0; i < itemFilters.getSlots(); ++i) {\n                    ItemStack filteredItem = itemFilters.getStackInSlot(i);\n\n                    if (filteredItem.getCount() > 1) {\n                        filteredItem.setCount(1);\n                        changed = true;\n                    }\n                }\n\n                for (int i = 0; i < fluidFilters.getSlots(); ++i) {\n                    FluidStack filteredFluid = fluidFilters.getFluid(i);\n\n                    if (!filteredFluid.isEmpty() && filteredFluid.getAmount() != FluidType.BUCKET_VOLUME) {\n                        filteredFluid.setAmount(FluidType.BUCKET_VOLUME);\n                        changed = true;\n                    }\n                }\n\n                if (changed) {\n                    markDirty();\n                }\n            }\n        });\n    private int type = IType.ITEMS;\n    private int filterSlot;\n\n    public ExporterNetworkNode(Level level, BlockPos pos) {\n        super(level, pos);\n        this.coverManager = new CoverManager(this);\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        return RS.SERVER_CONFIG.getExporter().getUsage() + upgrades.getEnergyUsage();\n    }\n\n    @Override\n    public void update() {\n        super.update();\n\n        if (canUpdate() && ticks % upgrades.getSpeed() == 0 && level.isLoaded(pos)) {\n            if (type == IType.ITEMS) {\n                IItemHandler handler = LevelUtils.getItemHandler(\n                    level,\n                    pos.relative(getDirection()),\n                    getDirection().getOpposite()\n                );\n\n                if (handler != null) {\n                    while (filterSlot + 1 < itemFilters.getSlots() && itemFilters.getStackInSlot(filterSlot).isEmpty()) {\n                        filterSlot++;\n                    }\n\n                    // We jump out of the loop above if we reach the maximum slot. If the maximum slot is empty,\n                    // we waste a tick with doing nothing because it's empty. Hence this check. If we are at the last slot\n                    // and it's empty, go back to slot 0.\n                    // We also handle if we exceeded the maximum slot in general.\n                    if ((filterSlot == itemFilters.getSlots() - 1 && itemFilters.getStackInSlot(filterSlot).isEmpty()) || (filterSlot >= itemFilters.getSlots())) {\n                        filterSlot = 0;\n                    }\n\n                    ItemStack slot = itemFilters.getStackInSlot(filterSlot);\n\n                    if (!slot.isEmpty()) {\n                        int stackSize = upgrades.getStackInteractCount();\n\n                        if (upgrades.hasUpgrade(UpgradeItem.Type.REGULATOR)) {\n                            int found = 0;\n\n                            for (int i = 0; i < handler.getSlots(); i++) {\n                                ItemStack stackInConnectedHandler = handler.getStackInSlot(i);\n\n                                if (API.instance().getComparer().isEqual(slot, stackInConnectedHandler, compare)) {\n                                    found += stackInConnectedHandler.getCount();\n                                }\n                            }\n\n                            int needed = 0;\n\n                            for (int i = 0; i < itemFilters.getSlots(); ++i) {\n                                if (API.instance().getComparer().isEqualNoQuantity(slot, itemFilters.getStackInSlot(i))) {\n                                    needed += itemFilters.getStackInSlot(i).getCount();\n                                }\n                            }\n\n                            stackSize = Math.min(stackSize, needed - found);\n                        }\n\n                        if (stackSize > 0) {\n                            ItemStack took = network.extractItem(slot, Math.min(slot.getMaxStackSize(), stackSize), compare, Action.SIMULATE);\n\n                            if (took.isEmpty()) {\n                                if (upgrades.hasUpgrade(UpgradeItem.Type.CRAFTING)) {\n                                    network.getCraftingManager().request(new SlottedCraftingRequest(this, filterSlot), slot, stackSize);\n                                }\n                            } else {\n                                ItemStack remainder = ItemHandlerHelper.insertItem(handler, took, true);\n\n                                int correctedStackSize = took.getCount() - remainder.getCount();\n\n                                if (correctedStackSize > 0) {\n                                    took = network.extractItem(slot, correctedStackSize, compare, Action.PERFORM);\n\n                                    ItemHandlerHelper.insertItem(handler, took, false);\n                                }\n                            }\n                        }\n                    }\n\n                    filterSlot++;\n                }\n            } else if (type == IType.FLUIDS) {\n                FluidStack[] fluids = fluidFilters.getFluids();\n\n                while (filterSlot + 1 < fluids.length && fluids[filterSlot] == null) {\n                    filterSlot++;\n                }\n\n                // We jump out of the loop above if we reach the maximum slot. If the maximum slot is empty,\n                // we waste a tick with doing nothing because it's empty. Hence this check. If we are at the last slot\n                // and it's empty, go back to slot 0.\n                // We also handle if we exceeded the maximum slot in general.\n                if ((filterSlot == fluids.length - 1 && fluids[filterSlot] == null) || (filterSlot >= fluids.length)) {\n                    filterSlot = 0;\n                }\n\n                IFluidHandler handler = LevelUtils.getFluidHandler(\n                    level,\n                    pos.relative(getDirection()),\n                    getDirection().getOpposite()\n                );\n\n                if (handler != null) {\n                    FluidStack stack = fluids[filterSlot];\n\n                    if (stack != null) {\n                        int toExtract = FluidType.BUCKET_VOLUME * upgrades.getStackInteractCount();\n\n                        FluidStack stackInStorage = network.getFluidStorageCache().getList().get(stack, compare);\n\n                        if (stackInStorage != null) {\n                            toExtract = Math.min(toExtract, stackInStorage.getAmount());\n\n                            if (upgrades.hasUpgrade(UpgradeItem.Type.REGULATOR)) {\n                                int found = 0;\n\n                                for (int i = 0; i < handler.getTanks(); i++) {\n                                    FluidStack stackInConnectedHandler = handler.getFluidInTank(i);\n\n                                    if (API.instance().getComparer().isEqual(stack, stackInConnectedHandler, compare)) {\n                                        found += stackInConnectedHandler.getAmount();\n                                    }\n                                }\n\n                                int needed = 0;\n\n                                for (int i = 0; i < fluidFilters.getSlots(); ++i) {\n                                    if (API.instance().getComparer().isEqual(stack, fluidFilters.getFluid(i), IComparer.COMPARE_NBT)) {\n                                        needed += fluidFilters.getFluid(i).getAmount();\n                                    }\n                                }\n\n                                toExtract = Math.min(toExtract, needed - found);\n                            }\n\n                            if (toExtract > 0) {\n                                FluidStack took = network.extractFluid(stack, toExtract, compare, Action.SIMULATE);\n\n                                int filled = handler.fill(took, IFluidHandler.FluidAction.SIMULATE);\n\n                                if (filled > 0) {\n                                    took = network.extractFluid(stack, filled, compare, Action.PERFORM);\n\n                                    handler.fill(took, IFluidHandler.FluidAction.EXECUTE);\n                                }\n                            }\n                        } else if (upgrades.hasUpgrade(UpgradeItem.Type.CRAFTING)) {\n                            network.getCraftingManager().request(this, stack, toExtract);\n                        }\n                    }\n\n                    filterSlot++;\n                }\n            }\n        }\n    }\n\n    @Override\n    public int getCompare() {\n        return compare;\n    }\n\n    @Override\n    public void setCompare(int compare) {\n        this.compare = compare;\n\n        markDirty();\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    @Override\n    public CompoundTag write(CompoundTag tag) {\n        super.write(tag);\n\n        tag.put(CoverManager.NBT_COVER_MANAGER, this.coverManager.writeToNbt());\n\n        StackUtils.writeItems(upgrades, 1, tag);\n        return tag;\n    }\n\n    @Override\n    public CompoundTag writeConfiguration(CompoundTag tag) {\n        super.writeConfiguration(tag);\n\n        tag.putInt(NBT_COMPARE, compare);\n        tag.putInt(NBT_TYPE, type);\n\n        StackUtils.writeItems(itemFilters, 0, tag);\n\n        tag.put(NBT_FLUID_FILTERS, fluidFilters.writeToNbt());\n\n        return tag;\n    }\n\n    @Override\n    public void read(CompoundTag tag) {\n        super.read(tag);\n\n        if (tag.contains(CoverManager.NBT_COVER_MANAGER)) {\n            this.coverManager.readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER));\n        }\n\n        StackUtils.readItems(upgrades, 1, tag);\n    }\n\n    @Override\n    public void readConfiguration(CompoundTag tag) {\n        super.readConfiguration(tag);\n\n        if (tag.contains(NBT_COMPARE)) {\n            compare = tag.getInt(NBT_COMPARE);\n        }\n\n        if (tag.contains(NBT_TYPE)) {\n            type = tag.getInt(NBT_TYPE);\n        }\n\n        StackUtils.readItems(itemFilters, 0, tag);\n\n        if (tag.contains(NBT_FLUID_FILTERS)) {\n            fluidFilters.readFromNbt(tag.getCompound(NBT_FLUID_FILTERS));\n        }\n    }\n\n    public UpgradeItemHandler getUpgrades() {\n        return upgrades;\n    }\n\n    @Override\n    public IItemHandler getDrops() {\n        return getUpgrades();\n    }\n\n    @Override\n    public int getType() {\n        return level.isClientSide ? ExporterBlockEntity.TYPE.getValue() : type;\n    }\n\n    @Override\n    public void setType(int type) {\n        this.type = type;\n\n        markDirty();\n    }\n\n    @Override\n    public IItemHandlerModifiable getItemFilters() {\n        return itemFilters;\n    }\n\n    @Override\n    public FluidInventory getFluidFilters() {\n        return fluidFilters;\n    }\n\n    @Override\n    public CoverManager getCoverManager() {\n        return coverManager;\n    }\n\n\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/ExternalStorageNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.node.ICoverable;\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.IStorage;\nimport com.refinedmods.refinedstorage.api.storage.IStorageProvider;\nimport com.refinedmods.refinedstorage.api.storage.StorageType;\nimport com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause;\nimport com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorage;\nimport com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorageContext;\nimport com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorageProvider;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;\nimport com.refinedmods.refinedstorage.apiimpl.storage.cache.FluidStorageCache;\nimport com.refinedmods.refinedstorage.apiimpl.storage.cache.ItemStorageCache;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener;\nimport com.refinedmods.refinedstorage.blockentity.ExternalStorageBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.*;\nimport com.refinedmods.refinedstorage.util.AccessTypeUtils;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.chat.Component;\n\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\n\nimport java.util.List;\nimport java.util.concurrent.CopyOnWriteArrayList;\n\npublic class ExternalStorageNetworkNode extends NetworkNode implements IStorageProvider, IStorageScreen, IComparable, IWhitelistBlacklist, IPrioritizable, IType, IAccessType, IExternalStorageContext, ICoverable {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"external_storage\");\n\n    private static final Logger LOGGER = LogManager.getLogger(ExternalStorageNetworkNode.class);\n\n    private static final String NBT_PRIORITY = \"Priority\";\n    private static final String NBT_COMPARE = \"Compare\";\n    private static final String NBT_MODE = \"Mode\";\n    private static final String NBT_TYPE = \"Type\";\n    private static final String NBT_FLUID_FILTERS = \"FluidFilters\";\n\n    private final BaseItemHandler itemFilters = new BaseItemHandler(9).addListener(new NetworkNodeInventoryListener(this));\n    private final FluidInventory fluidFilters = new FluidInventory(9).addListener(new NetworkNodeFluidInventoryListener(this));\n    private final List<IExternalStorage<ItemStack>> itemStorages = new CopyOnWriteArrayList<>();\n    private final List<IExternalStorage<FluidStack>> fluidStorages = new CopyOnWriteArrayList<>();\n    private final CoverManager coverManager;\n    private int priority = 0;\n    private int compare = IComparer.COMPARE_NBT;\n    private int mode = IWhitelistBlacklist.BLACKLIST;\n    private int type = IType.ITEMS;\n    private AccessType accessType = AccessType.INSERT_EXTRACT;\n    private int networkTicks;\n\n    public ExternalStorageNetworkNode(Level level, BlockPos pos) {\n        super(level, pos);\n        this.coverManager = new CoverManager(this);\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        return RS.SERVER_CONFIG.getExternalStorage().getUsage();\n    }\n\n    @Override\n    public void onConnectedStateChange(INetwork network, boolean state, ConnectivityStateChangeCause cause) {\n        super.onConnectedStateChange(network, state, cause);\n\n        LOGGER.debug(\"Connectivity state of external storage at {} changed to {} due to {}\", pos, state, cause);\n\n        updateStorage(network, InvalidateCause.CONNECTED_STATE_CHANGED);\n    }\n\n    @Override\n    public void update() {\n        super.update();\n\n        if (canUpdate() && level.isLoaded(pos)) {\n            if (networkTicks++ == 0) {\n                updateStorage(network, InvalidateCause.INITIAL_TICK_INVALIDATION);\n\n                return;\n            }\n\n            for (IExternalStorage<ItemStack> storage : itemStorages) {\n                storage.update(network);\n            }\n\n            for (IExternalStorage<FluidStack> storage : fluidStorages) {\n                storage.update(network);\n            }\n        }\n    }\n\n    @Override\n    public void onDirectionChanged(Direction direction) {\n        super.onDirectionChanged(direction);\n\n        if (network != null) {\n            updateStorage(network, InvalidateCause.DEVICE_CONFIGURATION_CHANGED);\n        }\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    @Override\n    public CompoundTag writeConfiguration(CompoundTag tag) {\n        super.writeConfiguration(tag);\n\n        StackUtils.writeItems(itemFilters, 0, tag);\n\n        tag.put(NBT_FLUID_FILTERS, fluidFilters.writeToNbt());\n\n        tag.putInt(NBT_PRIORITY, priority);\n        tag.putInt(NBT_COMPARE, compare);\n        tag.putInt(NBT_MODE, mode);\n        tag.putInt(NBT_TYPE, type);\n\n        AccessTypeUtils.writeAccessType(tag, accessType);\n\n        return tag;\n    }\n\n    @Override\n    public void readConfiguration(CompoundTag tag) {\n        super.readConfiguration(tag);\n\n        StackUtils.readItems(itemFilters, 0, tag);\n\n        if (tag.contains(NBT_FLUID_FILTERS)) {\n            fluidFilters.readFromNbt(tag.getCompound(NBT_FLUID_FILTERS));\n        }\n\n        if (tag.contains(NBT_PRIORITY)) {\n            priority = tag.getInt(NBT_PRIORITY);\n        }\n\n        if (tag.contains(NBT_COMPARE)) {\n            compare = tag.getInt(NBT_COMPARE);\n        }\n\n        if (tag.contains(NBT_MODE)) {\n            mode = tag.getInt(NBT_MODE);\n        }\n\n        if (tag.contains(NBT_TYPE)) {\n            type = tag.getInt(NBT_TYPE);\n        }\n\n        accessType = AccessTypeUtils.readAccessType(tag);\n    }\n\n    @Override\n    public int getCompare() {\n        return compare;\n    }\n\n    @Override\n    public void setCompare(int compare) {\n        this.compare = compare;\n\n        markDirty();\n    }\n\n    @Override\n    public int getWhitelistBlacklistMode() {\n        return mode;\n    }\n\n    @Override\n    public void setWhitelistBlacklistMode(int mode) {\n        this.mode = mode;\n\n        markDirty();\n    }\n\n    @Override\n    public int getPriority() {\n        return priority;\n    }\n\n    @Override\n    public void setPriority(int priority) {\n        this.priority = priority;\n\n        markDirty();\n\n        if (network != null) {\n            network.getItemStorageCache().sort();\n            network.getFluidStorageCache().sort();\n        }\n    }\n\n    public void updateStorage(INetwork network, InvalidateCause cause) {\n        itemStorages.clear();\n        fluidStorages.clear();\n\n        BlockEntity facing = getFacingBlockEntity();\n\n        if (facing != null) {\n            if (type == IType.ITEMS) {\n                for (IExternalStorageProvider<ItemStack> provider : API.instance().<ItemStack>getExternalStorageProviders(StorageType.ITEM)) {\n                    if (provider.canProvide(level, pos.relative(getDirection()), getDirection())) {\n                        itemStorages.add(provider.provide(this, getFacingBlockEntity(), getDirection()));\n\n                        break;\n                    }\n                }\n            } else if (type == IType.FLUIDS) {\n                for (IExternalStorageProvider<FluidStack> provider : API.instance().<FluidStack>getExternalStorageProviders(StorageType.FLUID)) {\n                    if (provider.canProvide(level, pos.relative(getDirection()), getDirection())) {\n                        fluidStorages.add(provider.provide(this, getFacingBlockEntity(), getDirection()));\n\n                        break;\n                    }\n                }\n            }\n        }\n\n        network.getNodeGraph().runActionWhenPossible(ItemStorageCache.INVALIDATE_ACTION.apply(cause));\n        network.getNodeGraph().runActionWhenPossible(FluidStorageCache.INVALIDATE_ACTION.apply(cause));\n    }\n\n    @Override\n    public void addItemStorages(List<IStorage<ItemStack>> storages) {\n        storages.addAll(this.itemStorages);\n    }\n\n    @Override\n    public void addFluidStorages(List<IStorage<FluidStack>> storages) {\n        storages.addAll(this.fluidStorages);\n    }\n\n    @Override\n    public Component getTitle() {\n        return Component.translatable(\"gui.refinedstorage:external_storage\");\n    }\n\n    @Override\n    public long getStored() {\n        return ExternalStorageBlockEntity.STORED.getValue();\n    }\n\n    @Override\n    public long getCapacity() {\n        return ExternalStorageBlockEntity.CAPACITY.getValue();\n    }\n\n    @Override\n    public AccessType getAccessType() {\n        return accessType;\n    }\n\n    @Override\n    public void setAccessType(AccessType type) {\n        this.accessType = type;\n\n        if (network != null) {\n            network.getItemStorageCache().invalidate(InvalidateCause.DEVICE_CONFIGURATION_CHANGED);\n            network.getFluidStorageCache().invalidate(InvalidateCause.DEVICE_CONFIGURATION_CHANGED);\n        }\n\n        markDirty();\n    }\n\n    @Override\n    public boolean acceptsItem(ItemStack stack) {\n        return IWhitelistBlacklist.acceptsItem(itemFilters, mode, compare, stack);\n    }\n\n    @Override\n    public boolean acceptsFluid(FluidStack stack) {\n        return IWhitelistBlacklist.acceptsFluid(fluidFilters, mode, compare, stack);\n    }\n\n    @Override\n    public int getType() {\n        return level.isClientSide ? ExternalStorageBlockEntity.TYPE.getValue() : type;\n    }\n\n    @Override\n    public void setType(int type) {\n        this.type = type;\n\n        markDirty();\n\n        if (network != null) {\n            updateStorage(network, InvalidateCause.DEVICE_CONFIGURATION_CHANGED);\n        }\n    }\n\n    @Override\n    public IItemHandlerModifiable getItemFilters() {\n        return itemFilters;\n    }\n\n    @Override\n    public FluidInventory getFluidFilters() {\n        return fluidFilters;\n    }\n\n    public List<IExternalStorage<ItemStack>> getItemStorages() {\n        return itemStorages;\n    }\n\n    public List<IExternalStorage<FluidStack>> getFluidStorages() {\n        return fluidStorages;\n    }\n\n    @Override\n    public CoverManager getCoverManager() {\n        return coverManager;\n    }\n\n    @Override\n    public void read(CompoundTag tag) {\n        super.read(tag);\n\n        if (tag.contains(CoverManager.NBT_COVER_MANAGER)) {\n            this.coverManager.readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER));\n        }\n    }\n\n\n    @Override\n    public CompoundTag write(CompoundTag tag) {\n        super.write(tag);\n\n        tag.put(CoverManager.NBT_COVER_MANAGER, this.coverManager.writeToNbt());\n\n        return tag;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/FluidInterfaceNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.storage.externalstorage.FluidExternalStorage;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport com.refinedmods.refinedstorage.inventory.fluid.ProxyFluidHandler;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.UpgradeItemHandler;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener;\nimport com.refinedmods.refinedstorage.item.UpgradeItem;\nimport com.refinedmods.refinedstorage.blockentity.FluidInterfaceBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.fluids.FluidType;\nimport net.neoforged.neoforge.fluids.capability.IFluidHandler;\nimport net.neoforged.neoforge.fluids.capability.templates.FluidTank;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport net.neoforged.neoforge.items.wrapper.CombinedInvWrapper;\nimport org.apache.commons.lang3.tuple.Pair;\n\npublic class FluidInterfaceNetworkNode extends NetworkNode {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"fluid_interface\");\n\n    public static final int TANK_CAPACITY = 16_000;\n\n    private static final String NBT_TANK_IN = \"TankIn\";\n    private static final String NBT_TANK_OUT = \"TankOut\";\n    private static final String NBT_OUT = \"Out\";\n\n    private final FluidTank tankIn = new FluidTank(TANK_CAPACITY) {\n        @Override\n        protected void onContentsChanged() {\n            super.onContentsChanged();\n\n            if (!level.isClientSide && level.isLoaded(pos)) {\n                ((FluidInterfaceBlockEntity) level.getBlockEntity(pos)).getDataManager().sendParameterToWatchers(FluidInterfaceBlockEntity.TANK_IN);\n            }\n\n            markDirty();\n        }\n    };\n    private final FluidTank tankOut = new FluidTank(TANK_CAPACITY);\n\n    private final ProxyFluidHandler tank = new ProxyFluidHandler(tankIn, tankOut);\n\n    private final BaseItemHandler in = new BaseItemHandler(1).addListener(new NetworkNodeInventoryListener(this)).addValidator(stack -> !StackUtils.getFluid(stack, true).getValue().isEmpty());\n    private final FluidInventory out = new FluidInventory(1, TANK_CAPACITY).addListener(new NetworkNodeFluidInventoryListener(this));\n\n    private final UpgradeItemHandler upgrades = (UpgradeItemHandler) new UpgradeItemHandler(4, UpgradeItem.Type.SPEED, UpgradeItem.Type.STACK, UpgradeItem.Type.CRAFTING).addListener(new NetworkNodeInventoryListener(this));\n\n    public FluidInterfaceNetworkNode(Level level, BlockPos pos) {\n        super(level, pos);\n    }\n\n    @Override\n    public void update() {\n        super.update();\n\n        if (canUpdate()) {\n            ItemStack container = in.getStackInSlot(0);\n\n            if (!container.isEmpty()) {\n                Pair<ItemStack, FluidStack> result = StackUtils.getFluid(container, true);\n\n                if (!result.getValue().isEmpty() && tankIn.fill(result.getValue(), IFluidHandler.FluidAction.SIMULATE) == result.getValue().getAmount()) {\n                    result = StackUtils.getFluid(container, false);\n\n                    tankIn.fill(result.getValue(), IFluidHandler.FluidAction.EXECUTE);\n\n                    in.setStackInSlot(0, result.getLeft());\n                }\n            }\n\n            if (ticks % upgrades.getSpeed() == 0) {\n                FluidStack drained = tankIn.drain(FluidType.BUCKET_VOLUME * upgrades.getStackInteractCount(), IFluidHandler.FluidAction.EXECUTE);\n\n                // Drain in tank\n                if (!drained.isEmpty()) {\n                    FluidStack remainder = network.insertFluidTracked(drained, drained.getAmount());\n\n                    tankIn.fill(remainder, IFluidHandler.FluidAction.EXECUTE);\n                }\n            }\n\n            FluidStack wanted = out.getFluid(0);\n            FluidStack got = tankOut.getFluid();\n\n            if (wanted.isEmpty()) {\n                if (!got.isEmpty()) {\n                    tankOut.setFluid(network.insertFluidTracked(got, got.getAmount()));\n\n                    onTankOutChanged();\n                }\n            } else if (!got.isEmpty() && !API.instance().getComparer().isEqual(wanted, got, IComparer.COMPARE_NBT)) {\n                tankOut.setFluid(network.insertFluidTracked(got, got.getAmount()));\n\n                onTankOutChanged();\n            } else {\n                int delta = got.isEmpty() ? wanted.getAmount() : (wanted.getAmount() - got.getAmount());\n\n                if (delta > 0) {\n                    final boolean actingAsStorage = isActingAsStorage();\n\n                    FluidStack result = network.extractFluid(wanted, delta, IComparer.COMPARE_NBT, Action.PERFORM, s -> {\n                        // If we are not an interface acting as a storage, we can extract from anywhere.\n                        if (!actingAsStorage) {\n                            return true;\n                        }\n\n                        // If we are an interface acting as a storage, we don't want to extract from other interfaces to\n                        // avoid stealing from each other.\n                        return !(s instanceof FluidExternalStorage) || !((FluidExternalStorage) s).isConnectedToInterface();\n                    });\n\n                    if (!result.isEmpty()) {\n                        if (tankOut.getFluid().isEmpty()) {\n                            tankOut.setFluid(result);\n                        } else {\n                            tankOut.getFluid().grow(result.getAmount());\n                        }\n\n                        onTankOutChanged();\n                    }\n\n                    // Example: our delta is 5, we extracted 3 fluids.\n                    // That means we still have to autocraft 2 fluids.\n                    delta -= result.getAmount();\n\n                    if (delta > 0 && upgrades.hasUpgrade(UpgradeItem.Type.CRAFTING)) {\n                        network.getCraftingManager().request(this, wanted, delta);\n                    }\n                } else if (delta < 0) {\n                    FluidStack remainder = network.insertFluidTracked(got, Math.abs(delta));\n\n                    tankOut.getFluid().shrink(Math.abs(delta) - remainder.getAmount());\n\n                    onTankOutChanged();\n                }\n            }\n        }\n    }\n\n    private boolean isActingAsStorage() {\n        for (Direction facing : Direction.values()) {\n            INetworkNode facingNode = API.instance().getNetworkNodeManager((ServerLevel) level).getNode(pos.relative(facing));\n\n            if (facingNode instanceof ExternalStorageNetworkNode &&\n                facingNode.isActive() &&\n                ((ExternalStorageNetworkNode) facingNode).getDirection() == facing.getOpposite() &&\n                ((ExternalStorageNetworkNode) facingNode).getType() == IType.FLUIDS) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        return RS.SERVER_CONFIG.getFluidInterface().getUsage();\n    }\n\n    @Override\n    public CompoundTag write(CompoundTag tag) {\n        super.write(tag);\n\n        StackUtils.writeItems(upgrades, 0, tag);\n        StackUtils.writeItems(in, 1, tag);\n\n        tag.put(NBT_TANK_IN, tankIn.writeToNBT(new CompoundTag()));\n        tag.put(NBT_TANK_OUT, tankOut.writeToNBT(new CompoundTag()));\n\n        return tag;\n    }\n\n    @Override\n    public void read(CompoundTag tag) {\n        super.read(tag);\n\n        StackUtils.readItems(upgrades, 0, tag);\n        StackUtils.readItems(in, 1, tag);\n\n        if (tag.contains(NBT_TANK_IN)) {\n            tankIn.readFromNBT(tag.getCompound(NBT_TANK_IN));\n        }\n\n        if (tag.contains(NBT_TANK_OUT)) {\n            tankOut.readFromNBT(tag.getCompound(NBT_TANK_OUT));\n        }\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    @Override\n    public CompoundTag writeConfiguration(CompoundTag tag) {\n        super.writeConfiguration(tag);\n\n        tag.put(NBT_OUT, out.writeToNbt());\n\n        return tag;\n    }\n\n    @Override\n    public void readConfiguration(CompoundTag tag) {\n        super.readConfiguration(tag);\n\n        if (tag.contains(NBT_OUT)) {\n            out.readFromNbt(tag.getCompound(NBT_OUT));\n        }\n    }\n\n    public UpgradeItemHandler getUpgrades() {\n        return upgrades;\n    }\n\n    public BaseItemHandler getIn() {\n        return in;\n    }\n\n    public FluidInventory getOut() {\n        return out;\n    }\n\n    public ProxyFluidHandler getTank() {\n        return tank;\n    }\n\n    public FluidTank getTankIn() {\n        return tankIn;\n    }\n\n    public FluidTank getTankOut() {\n        return tankOut;\n    }\n\n    private void onTankOutChanged() {\n        if (!level.isClientSide && level.isLoaded(pos)) {\n            ((FluidInterfaceBlockEntity) level.getBlockEntity(pos)).getDataManager().sendParameterToWatchers(FluidInterfaceBlockEntity.TANK_OUT);\n        }\n\n        markDirty();\n    }\n\n    @Override\n    public IItemHandler getDrops() {\n        return new CombinedInvWrapper(in, upgrades);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/GridNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.api.network.grid.*;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.api.util.IFilter;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.AllowedTagList;\nimport com.refinedmods.refinedstorage.apiimpl.storage.cache.listener.FluidGridStorageCacheListener;\nimport com.refinedmods.refinedstorage.apiimpl.storage.cache.listener.ItemGridStorageCacheListener;\nimport com.refinedmods.refinedstorage.block.GridBlock;\nimport com.refinedmods.refinedstorage.block.NetworkNodeBlock;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport com.refinedmods.refinedstorage.blockentity.grid.GridBlockEntity;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.FilterItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.validator.ItemValidator;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener;\nimport com.refinedmods.refinedstorage.item.PatternItem;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.Container;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.*;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.crafting.CraftingRecipe;\nimport net.minecraft.world.item.crafting.RecipeHolder;\nimport net.minecraft.world.item.crafting.RecipeType;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.fluids.FluidType;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport net.neoforged.neoforge.items.wrapper.CombinedInvWrapper;\nimport net.neoforged.neoforge.items.wrapper.InvWrapper;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\npublic class GridNetworkNode extends NetworkNode implements INetworkAwareGrid, IType {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"grid\");\n    public static final ResourceLocation CRAFTING_ID = new ResourceLocation(RS.ID, \"crafting_grid\");\n    public static final ResourceLocation PATTERN_ID = new ResourceLocation(RS.ID, \"pattern_grid\");\n    public static final ResourceLocation FLUID_ID = new ResourceLocation(RS.ID, \"fluid_grid\");\n\n    public static final String NBT_VIEW_TYPE = \"ViewType\";\n    public static final String NBT_SORTING_DIRECTION = \"SortingDirection\";\n    public static final String NBT_SORTING_TYPE = \"SortingType\";\n    public static final String NBT_SEARCH_BOX_MODE = \"SearchBoxMode\";\n    public static final String NBT_TAB_SELECTED = \"TabSelected\";\n    public static final String NBT_TAB_PAGE = \"TabPage\";\n    public static final String NBT_SIZE = \"Size\";\n    public static final int PROCESSING_MATRIX_SIZE = 81;\n    private static final String NBT_EXACT_MODE = \"Exact\";\n    private static final String NBT_PROCESSING_PATTERN = \"ProcessingPattern\";\n    private static final String NBT_PROCESSING_TYPE = \"ProcessingType\";\n    private static final String NBT_PROCESSING_MATRIX_FLUIDS = \"ProcessingMatrixFluids\";\n    private static final String NBT_ALLOWED_TAGS = \"AllowedTags\";\n    private final AllowedTagList allowedTagList = new AllowedTagList(this::updateAllowedTags, PROCESSING_MATRIX_SIZE);\n    private final ResultContainer result = new ResultContainer();\n    private final BaseItemHandler processingMatrix = new BaseItemHandler(PROCESSING_MATRIX_SIZE * 2)\n        .addListener(new NetworkNodeInventoryListener(this))\n        .addListener((handler, slot, reading) -> {\n            if (!reading && slot < PROCESSING_MATRIX_SIZE) {\n                allowedTagList.clearItemTags(slot);\n            }\n        });\n    private final AbstractContainerMenu craftingContainer = new AbstractContainerMenu(MenuType.CRAFTING, 0) {\n        @Override\n        public boolean stillValid(Player player) {\n            return false;\n        }\n\n        @Override\n        public ItemStack quickMoveStack(Player p_38941_, int p_38942_) {\n            return ItemStack.EMPTY;\n        }\n\n        @Override\n        public void slotsChanged(Container inventory) {\n            if (!level.isClientSide) {\n                onCraftingMatrixChanged();\n            }\n        }\n    };\n    private final FluidInventory processingMatrixFluids = new FluidInventory(PROCESSING_MATRIX_SIZE * 2, FluidType.BUCKET_VOLUME * 64)\n        .addListener(new NetworkNodeFluidInventoryListener(this))\n        .addListener((handler, slot, reading) -> {\n            if (!reading && slot < PROCESSING_MATRIX_SIZE) {\n                allowedTagList.clearFluidTags(slot);\n            }\n        });\n    private final Set<ICraftingGridListener> craftingListeners = new HashSet<>();\n    private final List<IFilter> filters = new ArrayList<>();\n    private final CraftingContainer matrix = new TransientCraftingContainer(craftingContainer, 3, 3);\n    private final List<IGridTab> tabs = new ArrayList<>();\n    private final FilterItemHandler filter = (FilterItemHandler) new FilterItemHandler(filters, tabs).addListener(new NetworkNodeInventoryListener(this));\n    private final GridType type;\n    private CraftingRecipe currentRecipe;\n    private boolean readingInventory;\n    private int viewType = VIEW_TYPE_NORMAL;\n    private int sortingDirection = SORTING_DIRECTION_DESCENDING;\n    private final BaseItemHandler patterns = new BaseItemHandler(2) {\n        @Override\n        public int getSlotLimit(int slot) {\n            return slot == 1 ? 1 : super.getSlotLimit(slot);\n        }\n\n        @Nonnull\n        @Override\n        public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) {\n            // Allow in slot 0\n            // Disallow in slot 1\n            // Only allow in slot 1 when it isn't a blank pattern\n            // This makes it so that written patterns can be re-inserted in slot 1 to be overwritten again\n            // This makes it so that blank patterns can't be inserted in slot 1 through hoppers.\n            if (slot == 0 || stack.getTag() != null) {\n                return super.insertItem(slot, stack, simulate);\n            }\n\n            return stack;\n        }\n    }\n        .addValidator(new ItemValidator(RSItems.PATTERN.get()))\n        .addListener(new NetworkNodeInventoryListener(this))\n        .addListener(((handler, slot, reading) -> {\n            ItemStack pattern = handler.getStackInSlot(slot);\n\n            if (!reading && slot == 1 && !pattern.isEmpty()) {\n                boolean processing = PatternItem.isProcessing(pattern);\n\n                if (processing) {\n                    for (int i = 0; i < PROCESSING_MATRIX_SIZE; ++i) {\n                        processingMatrix.setStackInSlot(i, PatternItem.getInputSlot(pattern, i));\n                        processingMatrixFluids.setFluid(i, PatternItem.getFluidInputSlot(pattern, i));\n                        processingMatrix.setStackInSlot(PROCESSING_MATRIX_SIZE + i, PatternItem.getOutputSlot(pattern, i));\n                        processingMatrixFluids.setFluid(PROCESSING_MATRIX_SIZE + i, PatternItem.getFluidOutputSlot(pattern, i));\n                    }\n\n                    AllowedTagList allowedTagsFromPattern = PatternItem.getAllowedTags(pattern);\n\n                    if (allowedTagsFromPattern != null) {\n                        allowedTagList.setAllowedItemTags(allowedTagsFromPattern.getAllowedItemTags());\n                        allowedTagList.setAllowedFluidTags(allowedTagsFromPattern.getAllowedFluidTags());\n                    }\n                } else {\n                    for (int i = 0; i < 9; ++i) {\n                        matrix.setItem(i, PatternItem.getInputSlot(pattern, i));\n                    }\n                }\n\n                setProcessingPattern(processing);\n                markDirty();\n            }\n        }));\n    private int sortingType = SORTING_TYPE_QUANTITY;\n    private int searchBoxMode = SEARCH_BOX_MODE_NORMAL;\n    private int size = SIZE_STRETCH;\n    private int tabSelected = -1;\n    private int tabPage = 0;\n    private boolean exactPattern = true;\n    private boolean processingPattern = false;\n    private int processingType = IType.ITEMS;\n\n    public GridNetworkNode(Level level, BlockPos pos, GridType type) {\n        super(level, pos);\n\n        this.type = type;\n    }\n\n    public static ResourceLocation getId(GridType type) {\n        switch (type) {\n            case NORMAL:\n                return ID;\n            case CRAFTING:\n                return CRAFTING_ID;\n            case PATTERN:\n                return PATTERN_ID;\n            case FLUID:\n                return FLUID_ID;\n            default:\n                throw new IllegalArgumentException(\"Unknown grid type \" + type);\n        }\n    }\n\n    public AllowedTagList getAllowedTagList() {\n        return allowedTagList;\n    }\n\n    private void updateAllowedTags() {\n        markDirty();\n\n        BlockEntity blockEntity = level.getBlockEntity(pos);\n\n        if (blockEntity instanceof GridBlockEntity) {\n            ((GridBlockEntity) blockEntity).getDataManager().sendParameterToWatchers(GridBlockEntity.ALLOWED_ITEM_TAGS);\n            ((GridBlockEntity) blockEntity).getDataManager().sendParameterToWatchers(GridBlockEntity.ALLOWED_FLUID_TAGS);\n        }\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        switch (type) {\n            case NORMAL:\n                return RS.SERVER_CONFIG.getGrid().getGridUsage();\n            case CRAFTING:\n                return RS.SERVER_CONFIG.getGrid().getCraftingGridUsage();\n            case PATTERN:\n                return RS.SERVER_CONFIG.getGrid().getPatternGridUsage();\n            case FLUID:\n                return RS.SERVER_CONFIG.getGrid().getFluidGridUsage();\n            default:\n                return 0;\n        }\n    }\n\n    public boolean isExactPattern() {\n        return exactPattern;\n    }\n\n    public void setExactPattern(boolean exactPattern) {\n        this.exactPattern = exactPattern;\n    }\n\n    public boolean isProcessingPattern() {\n        return level.isClientSide ? GridBlockEntity.PROCESSING_PATTERN.getValue() : processingPattern;\n    }\n\n    public void setProcessingPattern(boolean processingPattern) {\n        this.processingPattern = processingPattern;\n    }\n\n    @Override\n    public GridType getGridType() {\n        return type;\n    }\n\n    @Override\n    public IStorageCacheListener createListener(ServerPlayer player) {\n        return type == GridType.FLUID ? new FluidGridStorageCacheListener(player, network) : new ItemGridStorageCacheListener(player, network);\n    }\n\n    @Nullable\n    @Override\n    public IStorageCache getStorageCache() {\n        if (network != null) {\n            return type == GridType.FLUID ? network.getFluidStorageCache() : network.getItemStorageCache();\n        }\n\n        return null;\n    }\n\n    @Nullable\n    @Override\n    public IItemGridHandler getItemHandler() {\n        return network != null ? network.getItemGridHandler() : null;\n    }\n\n    @Nullable\n    @Override\n    public IFluidGridHandler getFluidHandler() {\n        return network != null ? network.getFluidGridHandler() : null;\n    }\n\n    @Override\n    public void addCraftingListener(ICraftingGridListener listener) {\n        craftingListeners.add(listener);\n    }\n\n    @Override\n    public void removeCraftingListener(ICraftingGridListener listener) {\n        craftingListeners.remove(listener);\n    }\n\n    @Override\n    public Component getTitle() {\n        switch (type) {\n            case CRAFTING:\n                return Component.translatable(\"gui.refinedstorage.crafting_grid\");\n            case PATTERN:\n                return Component.translatable(\"gui.refinedstorage.pattern_grid\");\n            case FLUID:\n                return Component.translatable(\"gui.refinedstorage.fluid_grid\");\n            default:\n                return Component.translatable(\"gui.refinedstorage.grid\");\n        }\n    }\n\n    public IItemHandler getPatterns() {\n        return patterns;\n    }\n\n    @Override\n    public IItemHandlerModifiable getFilter() {\n        return filter;\n    }\n\n    @Override\n    public List<IFilter> getFilters() {\n        return filters;\n    }\n\n    @Override\n    public List<IGridTab> getTabs() {\n        return tabs;\n    }\n\n    @Override\n    public CraftingContainer getCraftingMatrix() {\n        return matrix;\n    }\n\n    @Override\n    public ResultContainer getCraftingResult() {\n        return result;\n    }\n\n    public BaseItemHandler getProcessingMatrix() {\n        return processingMatrix;\n    }\n\n    public FluidInventory getProcessingMatrixFluids() {\n        return processingMatrixFluids;\n    }\n\n    @Override\n    public void onCraftingMatrixChanged() {\n        if (currentRecipe == null || !currentRecipe.matches(matrix, level)) {\n            currentRecipe = level.getRecipeManager().getRecipeFor(RecipeType.CRAFTING, matrix, level)\n                .map(RecipeHolder::value)\n                .orElse(null);\n        }\n\n        if (currentRecipe == null) {\n            result.setItem(0, ItemStack.EMPTY);\n        } else {\n            result.setItem(0, currentRecipe.assemble(matrix, level.registryAccess()));\n        }\n\n        craftingListeners.forEach(ICraftingGridListener::onCraftingMatrixChanged);\n\n        if (!readingInventory) {\n            markDirty();\n        }\n    }\n\n    @Override\n    public void onRecipeTransfer(Player player, ItemStack[][] recipe) {\n        API.instance().getCraftingGridBehavior().onRecipeTransfer(this, player, recipe);\n    }\n\n    public void clearMatrix() {\n        for (int i = 0; i < processingMatrix.getSlots(); ++i) {\n            processingMatrix.setStackInSlot(i, ItemStack.EMPTY);\n        }\n\n        for (int i = 0; i < processingMatrixFluids.getSlots(); ++i) {\n            processingMatrixFluids.setFluid(i, FluidStack.EMPTY);\n        }\n\n        for (int i = 0; i < matrix.getContainerSize(); ++i) {\n            matrix.setItem(i, ItemStack.EMPTY);\n        }\n    }\n\n    @Override\n    public void onClosed(Player player) {\n        // NO OP\n    }\n\n    @Override\n    public boolean isGridActive() {\n        BlockState state = level.getBlockState(pos);\n\n        if (state.getBlock() instanceof GridBlock) {\n            return state.getValue(NetworkNodeBlock.CONNECTED);\n        }\n\n        return false;\n    }\n\n    @Override\n    public int getSlotId() {\n        return -1;\n    }\n\n    @Override\n    public void onCrafted(Player player, @Nullable IStackList<ItemStack> availableItems, @Nullable IStackList<ItemStack> usedItems) {\n        API.instance().getCraftingGridBehavior().onCrafted(this, currentRecipe, player, availableItems, usedItems);\n    }\n\n    @Override\n    public void onClear(Player player) {\n        if (type == GridType.CRAFTING) {\n            if (network != null && network.canRun() && network.getSecurityManager().hasPermission(Permission.INSERT, player)) {\n                for (int i = 0; i < matrix.getContainerSize(); ++i) {\n                    ItemStack slot = matrix.getItem(i);\n\n                    if (!slot.isEmpty()) {\n                        matrix.setItem(i, network.insertItem(slot, slot.getCount(), Action.PERFORM));\n\n                        network.getItemStorageTracker().changed(player, slot.copy());\n                    }\n                }\n            } else {\n                for (int i = 0; i < matrix.getContainerSize(); i++) {\n                    ItemStack slot = matrix.getItem(i);\n\n                    if (!slot.isEmpty()) {\n                        player.getInventory().add(matrix.getItem(i));\n                    }\n\n                    onCraftingMatrixChanged();\n                }\n            }\n        } else if (type == GridType.PATTERN) {\n            clearMatrix();\n        }\n\n    }\n\n    @Override\n    public void onCraftedShift(Player player) {\n        API.instance().getCraftingGridBehavior().onCraftedShift(this, player);\n    }\n\n    public void onCreatePattern() {\n        if (canCreatePattern()) {\n            if (patterns.getStackInSlot(1).isEmpty()) {\n                patterns.extractItem(0, 1, false);\n            }\n\n            ItemStack pattern = new ItemStack(RSItems.PATTERN.get());\n\n            PatternItem.setToCurrentVersion(pattern);\n            PatternItem.setProcessing(pattern, processingPattern);\n\n            if (!processingPattern) {\n                PatternItem.setExact(pattern, exactPattern);\n            } else {\n                PatternItem.setAllowedTags(pattern, allowedTagList);\n            }\n\n            if (processingPattern) {\n                for (int i = 0; i < processingMatrix.getSlots(); ++i) {\n                    if (!processingMatrix.getStackInSlot(i).isEmpty()) {\n                        if (i >= PROCESSING_MATRIX_SIZE) {\n                            PatternItem.setOutputSlot(pattern, i - PROCESSING_MATRIX_SIZE, processingMatrix.getStackInSlot(i));\n                        } else {\n                            PatternItem.setInputSlot(pattern, i, processingMatrix.getStackInSlot(i));\n                        }\n                    }\n\n                    FluidStack fluid = processingMatrixFluids.getFluid(i);\n                    if (!fluid.isEmpty()) {\n                        if (i >= PROCESSING_MATRIX_SIZE) {\n                            PatternItem.setFluidOutputSlot(pattern, i - PROCESSING_MATRIX_SIZE, fluid);\n                        } else {\n                            PatternItem.setFluidInputSlot(pattern, i, fluid);\n                        }\n                    }\n                }\n            } else {\n                for (int i = 0; i < 9; ++i) {\n                    ItemStack ingredient = matrix.getItem(i);\n\n                    if (!ingredient.isEmpty()) {\n                        PatternItem.setInputSlot(pattern, i, ingredient);\n                    }\n                }\n            }\n\n            patterns.setStackInSlot(1, pattern);\n        }\n    }\n\n    private boolean isPatternAvailable() {\n        return !(patterns.getStackInSlot(0).isEmpty() && patterns.getStackInSlot(1).isEmpty());\n    }\n\n    public boolean canCreatePattern() {\n        if (!isPatternAvailable()) {\n            return false;\n        }\n\n        if (isProcessingPattern()) {\n            int inputsFilled = 0;\n            int outputsFilled = 0;\n\n            for (int i = 0; i < PROCESSING_MATRIX_SIZE; ++i) {\n                if (!processingMatrix.getStackInSlot(i).isEmpty()) {\n                    inputsFilled++;\n                }\n\n                if (!processingMatrixFluids.getFluid(i).isEmpty()) {\n                    inputsFilled++;\n                }\n            }\n\n            for (int i = PROCESSING_MATRIX_SIZE; i < processingMatrix.getSlots(); ++i) {\n                if (!processingMatrix.getStackInSlot(i).isEmpty()) {\n                    outputsFilled++;\n                }\n\n                if (!processingMatrixFluids.getFluid(i).isEmpty()) {\n                    outputsFilled++;\n                }\n            }\n\n            return inputsFilled > 0 && outputsFilled > 0;\n        } else {\n            return !result.getItem(0).isEmpty() && isPatternAvailable();\n        }\n    }\n\n    @Override\n    public int getViewType() {\n        return level.isClientSide ? GridBlockEntity.VIEW_TYPE.getValue() : viewType;\n    }\n\n    public void setViewType(int viewType) {\n        this.viewType = viewType;\n    }\n\n    @Override\n    public int getSortingDirection() {\n        return level.isClientSide ? GridBlockEntity.SORTING_DIRECTION.getValue() : sortingDirection;\n    }\n\n    public void setSortingDirection(int sortingDirection) {\n        this.sortingDirection = sortingDirection;\n    }\n\n    @Override\n    public int getSortingType() {\n        return level.isClientSide ? GridBlockEntity.SORTING_TYPE.getValue() : sortingType;\n    }\n\n    public void setSortingType(int sortingType) {\n        this.sortingType = sortingType;\n    }\n\n    @Override\n    public int getSearchBoxMode() {\n        return level.isClientSide ? GridBlockEntity.SEARCH_BOX_MODE.getValue() : searchBoxMode;\n    }\n\n    public void setSearchBoxMode(int searchBoxMode) {\n        this.searchBoxMode = searchBoxMode;\n    }\n\n    @Override\n    public int getSize() {\n        return level.isClientSide ? GridBlockEntity.SIZE.getValue() : size;\n    }\n\n    public void setSize(int size) {\n        this.size = size;\n    }\n\n    @Override\n    public int getTabSelected() {\n        return level.isClientSide ? GridBlockEntity.TAB_SELECTED.getValue() : tabSelected;\n    }\n\n    public void setTabSelected(int tabSelected) {\n        this.tabSelected = tabSelected;\n    }\n\n    @Override\n    public int getTabPage() {\n        return level.isClientSide ? GridBlockEntity.TAB_PAGE.getValue() : Math.min(tabPage, getTotalTabPages());\n    }\n\n    public void setTabPage(int page) {\n        this.tabPage = page;\n    }\n\n    @Override\n    public int getTotalTabPages() {\n        return (int) Math.floor((float) Math.max(0, tabs.size() - 1) / (float) IGrid.TABS_PER_PAGE);\n    }\n\n    @Override\n    public void onViewTypeChanged(int type) {\n        BlockEntitySynchronizationManager.setParameter(GridBlockEntity.VIEW_TYPE, type);\n    }\n\n    @Override\n    public void onSortingTypeChanged(int type) {\n        BlockEntitySynchronizationManager.setParameter(GridBlockEntity.SORTING_TYPE, type);\n    }\n\n    @Override\n    public void onSortingDirectionChanged(int direction) {\n        BlockEntitySynchronizationManager.setParameter(GridBlockEntity.SORTING_DIRECTION, direction);\n    }\n\n    @Override\n    public void onSearchBoxModeChanged(int searchBoxMode) {\n        BlockEntitySynchronizationManager.setParameter(GridBlockEntity.SEARCH_BOX_MODE, searchBoxMode);\n    }\n\n    @Override\n    public void onSizeChanged(int size) {\n        BlockEntitySynchronizationManager.setParameter(GridBlockEntity.SIZE, size);\n    }\n\n    @Override\n    public void onTabSelectionChanged(int tab) {\n        BlockEntitySynchronizationManager.setParameter(GridBlockEntity.TAB_SELECTED, tab);\n    }\n\n    @Override\n    public void onTabPageChanged(int page) {\n        if (page >= 0 && page <= getTotalTabPages()) {\n            BlockEntitySynchronizationManager.setParameter(GridBlockEntity.TAB_PAGE, page);\n        }\n    }\n\n    @Override\n    public int getType() {\n        return level.isClientSide ? GridBlockEntity.PROCESSING_TYPE.getValue() : processingType;\n    }\n\n    @Override\n    public void setType(int type) {\n        this.processingType = type;\n\n        this.markDirty();\n    }\n\n    @Override\n    public IItemHandlerModifiable getItemFilters() {\n        return getProcessingMatrix();\n    }\n\n    @Override\n    public FluidInventory getFluidFilters() {\n        return getProcessingMatrixFluids();\n    }\n\n    @Override\n    public void read(CompoundTag tag) {\n        super.read(tag);\n\n        if (tag.contains(NBT_ALLOWED_TAGS)) {\n            allowedTagList.readFromNbt(tag.getCompound(NBT_ALLOWED_TAGS));\n        }\n\n        readingInventory = true;\n\n        StackUtils.readItems(matrix, 0, tag);\n        StackUtils.readItems(patterns, 1, tag);\n        StackUtils.readItems(filter, 2, tag);\n        StackUtils.readItems(processingMatrix, 3, tag);\n\n        if (tag.contains(NBT_PROCESSING_MATRIX_FLUIDS)) {\n            processingMatrixFluids.readFromNbt(tag.getCompound(NBT_PROCESSING_MATRIX_FLUIDS));\n        }\n\n        if (tag.contains(NBT_TAB_SELECTED)) {\n            tabSelected = tag.getInt(NBT_TAB_SELECTED);\n        }\n\n        if (tag.contains(NBT_TAB_PAGE)) {\n            tabPage = tag.getInt(NBT_TAB_PAGE);\n        }\n\n        readingInventory = false;\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return getId(type);\n    }\n\n    @Override\n    public CompoundTag write(CompoundTag tag) {\n        super.write(tag);\n\n        tag.put(NBT_ALLOWED_TAGS, allowedTagList.writeToNbt());\n\n        StackUtils.writeItems(matrix, 0, tag);\n        StackUtils.writeItems(patterns, 1, tag);\n        StackUtils.writeItems(filter, 2, tag);\n        StackUtils.writeItems(processingMatrix, 3, tag);\n\n        tag.put(NBT_PROCESSING_MATRIX_FLUIDS, processingMatrixFluids.writeToNbt());\n        tag.putInt(NBT_TAB_SELECTED, tabSelected);\n        tag.putInt(NBT_TAB_PAGE, tabPage);\n\n        return tag;\n    }\n\n    @Override\n    public CompoundTag writeConfiguration(CompoundTag tag) {\n        super.writeConfiguration(tag);\n\n        tag.putInt(NBT_VIEW_TYPE, viewType);\n        tag.putInt(NBT_SORTING_DIRECTION, sortingDirection);\n        tag.putInt(NBT_SORTING_TYPE, sortingType);\n        tag.putInt(NBT_SEARCH_BOX_MODE, searchBoxMode);\n        tag.putInt(NBT_SIZE, size);\n\n        tag.putBoolean(NBT_EXACT_MODE, exactPattern);\n        tag.putBoolean(NBT_PROCESSING_PATTERN, processingPattern);\n        tag.putInt(NBT_PROCESSING_TYPE, processingType);\n\n        return tag;\n    }\n\n    @Override\n    public void readConfiguration(CompoundTag tag) {\n        super.readConfiguration(tag);\n\n        if (tag.contains(NBT_VIEW_TYPE)) {\n            viewType = tag.getInt(NBT_VIEW_TYPE);\n        }\n\n        if (tag.contains(NBT_SORTING_DIRECTION)) {\n            sortingDirection = tag.getInt(NBT_SORTING_DIRECTION);\n        }\n\n        if (tag.contains(NBT_SORTING_TYPE)) {\n            sortingType = tag.getInt(NBT_SORTING_TYPE);\n        }\n\n        if (tag.contains(NBT_SEARCH_BOX_MODE)) {\n            searchBoxMode = tag.getInt(NBT_SEARCH_BOX_MODE);\n        }\n\n        if (tag.contains(NBT_SIZE)) {\n            size = tag.getInt(NBT_SIZE);\n        }\n\n        if (tag.contains(NBT_EXACT_MODE)) {\n            exactPattern = tag.getBoolean(NBT_EXACT_MODE);\n        }\n\n        if (tag.contains(NBT_PROCESSING_PATTERN)) {\n            processingPattern = tag.getBoolean(NBT_PROCESSING_PATTERN);\n        }\n\n        if (tag.contains(NBT_PROCESSING_TYPE)) {\n            processingType = tag.getInt(NBT_PROCESSING_TYPE);\n        }\n    }\n\n    @Override\n    public IItemHandler getDrops() {\n        switch (type) {\n            case CRAFTING:\n                return new CombinedInvWrapper(filter, new InvWrapper(matrix));\n            case PATTERN:\n                return new CombinedInvWrapper(filter, patterns);\n            default:\n                return new CombinedInvWrapper(filter);\n        }\n    }\n\n\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/IStorageScreen.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport net.minecraft.network.chat.Component;\n\npublic interface IStorageScreen {\n    Component getTitle();\n\n    long getStored();\n\n    long getCapacity();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/ImporterNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.node.ICoverable;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;\nimport com.refinedmods.refinedstorage.blockentity.DiskDriveBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.ImporterBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IComparable;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.UpgradeItemHandler;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener;\nimport com.refinedmods.refinedstorage.item.UpgradeItem;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.fluids.FluidType;\nimport net.neoforged.neoforge.fluids.capability.IFluidHandler;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\n\npublic class ImporterNetworkNode extends NetworkNode implements IComparable, IWhitelistBlacklist, IType, ICoverable {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"importer\");\n\n    private static final String NBT_COMPARE = \"Compare\";\n    private static final String NBT_MODE = \"Mode\";\n    private static final String NBT_TYPE = \"Type\";\n    private static final String NBT_FLUID_FILTERS = \"FLuidFilters\";\n\n    private final BaseItemHandler itemFilters = new BaseItemHandler(9).addListener(new NetworkNodeInventoryListener(this));\n    private final FluidInventory fluidFilters = new FluidInventory(9).addListener(new NetworkNodeFluidInventoryListener(this));\n\n    private final UpgradeItemHandler upgrades = (UpgradeItemHandler) new UpgradeItemHandler(4, UpgradeItem.Type.SPEED, UpgradeItem.Type.STACK).addListener(new NetworkNodeInventoryListener(this));\n    private final CoverManager coverManager;\n    private int compare = IComparer.COMPARE_NBT;\n    private int mode = IWhitelistBlacklist.BLACKLIST;\n    private int type = IType.ITEMS;\n    private int currentSlot;\n\n    public ImporterNetworkNode(Level level, BlockPos pos) {\n        super(level, pos);\n        this.coverManager = new CoverManager(this);\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        return RS.SERVER_CONFIG.getImporter().getUsage() + upgrades.getEnergyUsage();\n    }\n\n    @Override\n    public void update() {\n        super.update();\n\n        if (!canUpdate() || !level.isLoaded(pos)) {\n            return;\n        }\n\n        if (type == IType.ITEMS) {\n            BlockEntity facing = getFacingBlockEntity();\n            IItemHandler handler = LevelUtils.getItemHandler(\n                level,\n                pos.relative(getDirection()),\n                getDirection().getOpposite()\n            );\n\n            if (facing instanceof DiskDriveBlockEntity || handler == null) {\n                return;\n            }\n\n            if (currentSlot >= handler.getSlots()) {\n                currentSlot = 0;\n            }\n\n            if (handler.getSlots() > 0) {\n                while (currentSlot + 1 < handler.getSlots() && handler.getStackInSlot(currentSlot).isEmpty()) {\n                    currentSlot++;\n                }\n\n                ItemStack stack = handler.getStackInSlot(currentSlot);\n\n                if (!IWhitelistBlacklist.acceptsItem(itemFilters, mode, compare, stack)) {\n                    currentSlot++;\n                } else if (ticks % upgrades.getSpeed() == 0) {\n                    ItemStack result = handler.extractItem(currentSlot, upgrades.getStackInteractCount(), true);\n\n                    if (!result.isEmpty() && network.insertItem(result, result.getCount(), Action.SIMULATE).isEmpty()) {\n                        result = handler.extractItem(currentSlot, upgrades.getStackInteractCount(), false);\n\n                        network.insertItemTracked(result, result.getCount());\n                    } else {\n                        currentSlot++;\n                    }\n                }\n            }\n        } else if (type == IType.FLUIDS && ticks % upgrades.getSpeed() == 0) {\n            IFluidHandler handler = LevelUtils.getFluidHandler(\n                level,\n                pos.relative(getDirection()),\n                getDirection().getOpposite()\n            );\n\n            if (handler != null) {\n                FluidStack extractedSimulated = handler.drain(FluidType.BUCKET_VOLUME * upgrades.getStackInteractCount(), IFluidHandler.FluidAction.SIMULATE);\n\n                if (!extractedSimulated.isEmpty()\n                        && IWhitelistBlacklist.acceptsFluid(fluidFilters, mode, compare, extractedSimulated)\n                        && network.insertFluid(extractedSimulated, extractedSimulated.getAmount(), Action.SIMULATE).isEmpty()) {\n                    FluidStack extracted = handler.drain(extractedSimulated, IFluidHandler.FluidAction.EXECUTE);\n\n                    if (!extracted.isEmpty()) {\n                        network.insertFluidTracked(extracted, extracted.getAmount());\n                    }\n                }\n            }\n        }\n    }\n\n    @Override\n    public int getCompare() {\n        return compare;\n    }\n\n    @Override\n    public void setCompare(int compare) {\n        this.compare = compare;\n\n        markDirty();\n    }\n\n    @Override\n    public int getWhitelistBlacklistMode() {\n        return mode;\n    }\n\n    @Override\n    public void setWhitelistBlacklistMode(int mode) {\n        this.mode = mode;\n\n        markDirty();\n    }\n\n    @Override\n    public void read(CompoundTag tag) {\n        super.read(tag);\n\n        if (tag.contains(CoverManager.NBT_COVER_MANAGER)) {\n            this.coverManager.readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER));\n        }\n\n        StackUtils.readItems(upgrades, 1, tag);\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    @Override\n    public CompoundTag write(CompoundTag tag) {\n        super.write(tag);\n\n        tag.put(CoverManager.NBT_COVER_MANAGER, this.coverManager.writeToNbt());\n\n        StackUtils.writeItems(upgrades, 1, tag);\n\n        return tag;\n    }\n\n    @Override\n    public CompoundTag writeConfiguration(CompoundTag tag) {\n        super.writeConfiguration(tag);\n\n        tag.putInt(NBT_COMPARE, compare);\n        tag.putInt(NBT_MODE, mode);\n        tag.putInt(NBT_TYPE, type);\n\n        StackUtils.writeItems(itemFilters, 0, tag);\n\n        tag.put(NBT_FLUID_FILTERS, fluidFilters.writeToNbt());\n\n        return tag;\n    }\n\n    @Override\n    public void readConfiguration(CompoundTag tag) {\n        super.readConfiguration(tag);\n\n        if (tag.contains(NBT_COMPARE)) {\n            compare = tag.getInt(NBT_COMPARE);\n        }\n\n        if (tag.contains(NBT_MODE)) {\n            mode = tag.getInt(NBT_MODE);\n        }\n\n        if (tag.contains(NBT_TYPE)) {\n            type = tag.getInt(NBT_TYPE);\n        }\n\n        StackUtils.readItems(itemFilters, 0, tag);\n\n        if (tag.contains(NBT_FLUID_FILTERS)) {\n            fluidFilters.readFromNbt(tag.getCompound(NBT_FLUID_FILTERS));\n        }\n    }\n\n    public IItemHandler getUpgrades() {\n        return upgrades;\n    }\n\n    @Override\n    public IItemHandler getDrops() {\n        return getUpgrades();\n    }\n\n    @Override\n    public int getType() {\n        return level.isClientSide ? ImporterBlockEntity.TYPE.getValue() : type;\n    }\n\n    @Override\n    public void setType(int type) {\n        this.type = type;\n\n        markDirty();\n    }\n\n    @Override\n    public IItemHandlerModifiable getItemFilters() {\n        return itemFilters;\n    }\n\n    @Override\n    public FluidInventory getFluidFilters() {\n        return fluidFilters;\n    }\n\n    @Override\n    public CoverManager getCoverManager() {\n        return coverManager;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/InterfaceNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.storage.externalstorage.ItemExternalStorage;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.ProxyItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.UpgradeItemHandler;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener;\nimport com.refinedmods.refinedstorage.item.UpgradeItem;\nimport com.refinedmods.refinedstorage.blockentity.config.IComparable;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport net.neoforged.neoforge.items.wrapper.CombinedInvWrapper;\n\npublic class InterfaceNetworkNode extends NetworkNode implements IComparable {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"interface\");\n\n    private static final String NBT_COMPARE = \"Compare\";\n\n    private final BaseItemHandler importItems = new BaseItemHandler(9).addListener(new NetworkNodeInventoryListener(this));\n\n    private final BaseItemHandler exportFilterItems = new BaseItemHandler(9).addListener(new NetworkNodeInventoryListener(this));\n    private final BaseItemHandler exportItems = new BaseItemHandler(9).addListener(new NetworkNodeInventoryListener(this));\n\n    private final IItemHandler items = new ProxyItemHandler(importItems, exportItems);\n\n    private final UpgradeItemHandler upgrades = (UpgradeItemHandler) new UpgradeItemHandler(4, UpgradeItem.Type.SPEED, UpgradeItem.Type.STACK, UpgradeItem.Type.CRAFTING)\n        .addListener(new NetworkNodeInventoryListener(this));\n\n    private int compare = IComparer.COMPARE_NBT;\n\n    private int currentSlot = 0;\n\n    public InterfaceNetworkNode(Level level, BlockPos pos) {\n        super(level, pos);\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        return RS.SERVER_CONFIG.getInterface().getUsage() + upgrades.getEnergyUsage();\n    }\n\n    @Override\n    public void update() {\n        super.update();\n\n        if (!canUpdate()) {\n            return;\n        }\n\n        if (currentSlot >= importItems.getSlots()) {\n            currentSlot = 0;\n        }\n\n        ItemStack slot = importItems.getStackInSlot(currentSlot);\n\n        if (slot.isEmpty()) {\n            currentSlot++;\n        } else if (ticks % upgrades.getSpeed() == 0) {\n            int size = Math.min(slot.getCount(), upgrades.getStackInteractCount());\n\n            ItemStack remainder = network.insertItemTracked(slot, size);\n\n            importItems.extractItem(currentSlot, size - remainder.getCount(), false);\n        }\n\n        for (int i = 0; i < 9; ++i) {\n            ItemStack wanted = exportFilterItems.getStackInSlot(i);\n            ItemStack got = exportItems.getStackInSlot(i);\n\n            if (wanted.isEmpty()) {\n                if (!got.isEmpty()) {\n                    exportItems.setStackInSlot(i, network.insertItemTracked(got, got.getCount()));\n                }\n            } else if (!got.isEmpty() && !API.instance().getComparer().isEqual(wanted, got, getCompare())) {\n                exportItems.setStackInSlot(i, network.insertItemTracked(got, got.getCount()));\n            } else {\n                int delta = got.isEmpty() ? wanted.getCount() : (wanted.getCount() - got.getCount());\n\n                if (delta > 0) {\n                    final boolean actingAsStorage = isActingAsStorage();\n\n                    ItemStack result = network.extractItem(wanted, delta, compare, Action.PERFORM, s -> {\n                        // If we are not an interface acting as a storage, we can extract from anywhere.\n                        if (!actingAsStorage) {\n                            return true;\n                        }\n\n                        // If we are an interface acting as a storage, we don't want to extract from other interfaces to\n                        // avoid stealing from each other.\n                        return !(s instanceof ItemExternalStorage) || !((ItemExternalStorage) s).isConnectedToInterface();\n                    });\n\n                    if (!result.isEmpty()) {\n                        if (exportItems.getStackInSlot(i).isEmpty()) {\n                            exportItems.setStackInSlot(i, result);\n                        } else {\n                            exportItems.getStackInSlot(i).grow(result.getCount());\n                        }\n                    }\n\n                    // Example: our delta is 5, we extracted 3 items.\n                    // That means we still have to autocraft 2 items.\n                    delta -= result.getCount();\n\n                    if (delta > 0 && upgrades.hasUpgrade(UpgradeItem.Type.CRAFTING)) {\n                        network.getCraftingManager().request(new SlottedCraftingRequest(this, i), wanted, delta);\n                    }\n                } else if (delta < 0) {\n                    ItemStack remainder = network.insertItemTracked(got, Math.abs(delta));\n\n                    exportItems.extractItem(i, Math.abs(delta) - remainder.getCount(), false);\n                }\n            }\n        }\n    }\n\n    private boolean isActingAsStorage() {\n        for (Direction facing : Direction.values()) {\n            INetworkNode facingNode = API.instance().getNetworkNodeManager((ServerLevel) level).getNode(pos.relative(facing));\n\n            if (facingNode instanceof ExternalStorageNetworkNode &&\n                facingNode.isActive() &&\n                ((ExternalStorageNetworkNode) facingNode).getDirection() == facing.getOpposite() &&\n                ((ExternalStorageNetworkNode) facingNode).getType() == IType.ITEMS) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public int getCompare() {\n        return compare;\n    }\n\n    @Override\n    public void setCompare(int compare) {\n        this.compare = compare;\n\n        markDirty();\n    }\n\n    @Override\n    public void read(CompoundTag tag) {\n        super.read(tag);\n\n        StackUtils.readItems(importItems, 0, tag);\n        StackUtils.readItems(exportItems, 2, tag);\n        StackUtils.readItems(upgrades, 3, tag);\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    @Override\n    public CompoundTag write(CompoundTag tag) {\n        super.write(tag);\n\n        StackUtils.writeItems(importItems, 0, tag);\n        StackUtils.writeItems(exportItems, 2, tag);\n        StackUtils.writeItems(upgrades, 3, tag);\n\n        return tag;\n    }\n\n    @Override\n    public CompoundTag writeConfiguration(CompoundTag tag) {\n        super.writeConfiguration(tag);\n\n        StackUtils.writeItems(exportFilterItems, 1, tag);\n\n        tag.putInt(NBT_COMPARE, compare);\n\n        return tag;\n    }\n\n    @Override\n    public void readConfiguration(CompoundTag tag) {\n        super.readConfiguration(tag);\n\n        StackUtils.readItems(exportFilterItems, 1, tag);\n\n        if (tag.contains(NBT_COMPARE)) {\n            compare = tag.getInt(NBT_COMPARE);\n        }\n    }\n\n    public IItemHandler getImportItems() {\n        return importItems;\n    }\n\n    public IItemHandler getExportFilterItems() {\n        return exportFilterItems;\n    }\n\n    public IItemHandler getExportItems() {\n        return exportItems;\n    }\n\n    public IItemHandler getItems() {\n        return items;\n    }\n\n    public IItemHandler getUpgrades() {\n        return upgrades;\n    }\n\n    @Override\n    public IItemHandler getDrops() {\n        return new CombinedInvWrapper(importItems, exportItems, upgrades);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/NetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.INetworkNodeVisitor;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.block.BaseBlock;\nimport com.refinedmods.refinedstorage.block.NetworkNodeBlock;\nimport com.refinedmods.refinedstorage.blockentity.config.RedstoneMode;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.level.block.state.properties.DirectionProperty;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.UUID;\n\npublic abstract class NetworkNode implements INetworkNode, INetworkNodeVisitor {\n    private static final Logger LOGGER = LogManager.getLogger();\n\n    private static final String NBT_OWNER = \"Owner\";\n    private static final String NBT_VERSION = \"Version\";\n    private static final int CURRENT_VERSION = 1;\n\n    @Nullable\n    protected INetwork network;\n    // @Volatile: Mental note. At this moment world instances are retained in Minecraft (since 1.16).\n    // This means that during the entire server lifetime, all worlds are present and will not change their instance.\n    // However, due to the memory footprint of worlds and modded minecraft having the tendency to have lots of worlds,\n    // Forge is planning to unload (aka remove) worlds so their instances will change.\n    // This is problematic as this attribute will target the wrong world in that case.\n    // Idea: possibly change to a getter based on RegistryKey<Level>?\n    // Another note: this attribute isn't the *real* problem. Because network nodes are in SavedData in a tick handler,\n    // new instances of network nodes will be created when the world refreshes (causing this field to be different too).\n    // However, network nodes in the network graph *AREN'T* recreated when the world refreshes, causing the graph to have the incorrect instance, and even worse,\n    // having multiple different instances of the same network node.\n    protected Level level;\n    protected BlockPos pos;\n    protected int ticks;\n    protected RedstoneMode redstoneMode = RedstoneMode.IGNORE;\n    @Nullable\n    protected UUID owner;\n    protected String version;\n    private boolean redstonePowered = false;\n    private Direction direction;\n\n    // Disable throttling for the first tick.\n    // This is to make sure couldUpdate is going to be correctly set.\n    // If we place 2 blocks next to each other, and disconnect the first one really fast,\n    // the second one would not realize it has been disconnected because couldUpdate == canUpdate.\n    // It would however still have the connected state, due to the initial block update packet.\n    // The couldUpdate/canUpdate system is separate from that.\n    private boolean throttlingDisabled = true;\n    private boolean couldUpdate;\n    private int ticksSinceUpdateChanged;\n\n    protected NetworkNode(Level level, BlockPos pos) {\n        if (level == null) {\n            throw new IllegalArgumentException(\"World cannot be null\");\n        }\n\n        this.level = level;\n        this.pos = pos;\n    }\n\n    public RedstoneMode getRedstoneMode() {\n        return redstoneMode;\n    }\n\n    public void setRedstoneMode(RedstoneMode redstoneMode) {\n        this.redstoneMode = redstoneMode;\n\n        markDirty();\n    }\n\n    @Nonnull\n    @Override\n    public ItemStack getItemStack() {\n        return new ItemStack(Item.BY_BLOCK.get(level.getBlockState(pos).getBlock()), 1);\n    }\n\n    @Override\n    public void onConnected(INetwork network) {\n        onConnectedStateChange(network, true, ConnectivityStateChangeCause.GRAPH_CHANGE);\n\n        this.network = network;\n    }\n\n    @Override\n    public void onDisconnected(INetwork network) {\n        this.network = null;\n\n        onConnectedStateChange(network, false, ConnectivityStateChangeCause.GRAPH_CHANGE);\n    }\n\n    protected void onConnectedStateChange(INetwork network, boolean state, ConnectivityStateChangeCause cause) {\n        // NO OP\n    }\n\n    @Override\n    public void markDirty() {\n        if (!level.isClientSide) {\n            API.instance().getNetworkNodeManager((ServerLevel) level).markForSaving();\n        }\n    }\n\n    @Override\n    public boolean isActive() {\n        return redstoneMode.isEnabled(redstonePowered);\n    }\n\n    protected final boolean canUpdate() {\n        if (isActive() && network != null) {\n            return network.canRun();\n        }\n\n        return false;\n    }\n\n    protected int getUpdateThrottleInactiveToActive() {\n        return 20;\n    }\n\n    protected int getUpdateThrottleActiveToInactive() {\n        return 4;\n    }\n\n    public void setRedstonePowered(boolean redstonePowered) {\n        this.redstonePowered = redstonePowered;\n    }\n\n    @Override\n    public void update() {\n        if (ticks == 0) {\n            redstonePowered = level.hasNeighborSignal(pos);\n        }\n\n        ++ticks;\n\n        boolean canUpdate = canUpdate();\n\n        if (couldUpdate != canUpdate) {\n            ++ticksSinceUpdateChanged;\n\n            if ((canUpdate ? (ticksSinceUpdateChanged > getUpdateThrottleInactiveToActive()) : (ticksSinceUpdateChanged > getUpdateThrottleActiveToInactive())) || throttlingDisabled) {\n                ticksSinceUpdateChanged = 0;\n                couldUpdate = canUpdate;\n                throttlingDisabled = false;\n\n                BlockState blockState = level.getBlockState(pos);\n\n                if (blockState.getBlock() instanceof NetworkNodeBlock && ((NetworkNodeBlock) blockState.getBlock()).hasConnectedState()) {\n                    level.setBlockAndUpdate(pos, level.getBlockState(pos).setValue(NetworkNodeBlock.CONNECTED, canUpdate));\n                }\n\n                if (network != null) {\n                    onConnectedStateChange(network, canUpdate, ConnectivityStateChangeCause.REDSTONE_MODE_OR_NETWORK_ENERGY_CHANGE);\n\n                    if (shouldRebuildGraphOnChange()) {\n                        network.getNodeGraph().invalidate(Action.PERFORM, network.getLevel(), network.getPosition());\n                    }\n                }\n            }\n        } else {\n            ticksSinceUpdateChanged = 0;\n        }\n    }\n\n    @Override\n    public CompoundTag write(CompoundTag tag) {\n        if (owner != null) {\n            tag.putUUID(NBT_OWNER, owner);\n        }\n\n        tag.putInt(NBT_VERSION, CURRENT_VERSION);\n\n        writeConfiguration(tag);\n\n        return tag;\n    }\n\n    public CompoundTag writeConfiguration(CompoundTag tag) {\n        redstoneMode.write(tag);\n\n        return tag;\n    }\n\n    public void read(CompoundTag tag) {\n        if (tag.hasUUID(NBT_OWNER)) {\n            owner = tag.getUUID(NBT_OWNER);\n        }\n\n        if (tag.contains(NBT_VERSION)) {\n            version = tag.getString(NBT_VERSION);\n        }\n\n        readConfiguration(tag);\n    }\n\n    public void readConfiguration(CompoundTag tag) {\n        redstoneMode = RedstoneMode.read(tag);\n    }\n\n    @Nullable\n    @Override\n    public INetwork getNetwork() {\n        return network;\n    }\n\n    @Override\n    public BlockPos getPos() {\n        return pos;\n    }\n\n    @Override\n    public Level getLevel() {\n        return level;\n    }\n\n    @Override\n    public boolean canConduct(Direction direction) {\n        return true;\n    }\n\n    @Override\n    public void visit(Operator operator) {\n        for (Direction facing : Direction.values()) {\n            BlockPos facingPos = pos.relative(facing);\n            if (!level.isLoaded(facingPos)) {\n                continue;\n            }\n            INetworkNode oppositeNode = NetworkUtils.getNodeFromBlockEntity(level.getBlockEntity(facingPos));\n            if (oppositeNode == null) {\n                continue;\n            }\n            if (canConduct(facing) && oppositeNode.canReceive(facing.getOpposite())) {\n                operator.apply(level, facingPos, facing.getOpposite());\n            }\n        }\n    }\n\n    @Nullable\n    public BlockEntity getFacingBlockEntity() {\n        BlockPos facingPos = pos.relative(getDirection());\n        if (!level.isLoaded(facingPos)) {\n            return null;\n        }\n\n        return level.getBlockEntity(facingPos);\n    }\n\n    public Direction getDirection() {\n        if (direction == null) {\n            BlockState state = level.getBlockState(pos);\n\n            if (state.getBlock() instanceof BaseBlock baseBlock) {\n                DirectionProperty property = baseBlock.getDirection().getProperty();\n\n                if (state.hasProperty(property)) {\n                    direction = state.getValue(property);\n                } else {\n                    LOGGER.warn(\"Node @ {} has no direction! Consider recreating the block\", pos);\n                    return Direction.NORTH;\n                }\n            }\n        }\n\n        return direction;\n    }\n\n    public void onDirectionChanged(Direction direction) {\n        this.direction = direction;\n    }\n\n    @Nullable\n    public IItemHandler getDrops() {\n        return null;\n    }\n\n    public boolean shouldRebuildGraphOnChange() {\n        return false;\n    }\n\n    @Override\n    @Nullable\n    public UUID getOwner() {\n        return owner;\n    }\n\n    @Override\n    public void setOwner(@Nullable UUID owner) {\n        this.owner = owner;\n\n        markDirty();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/NetworkReceiverNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.RS;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\n\npublic class NetworkReceiverNetworkNode extends NetworkNode {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"network_receiver\");\n\n    public NetworkReceiverNetworkNode(Level level, BlockPos pos) {\n        super(level, pos);\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        return RS.SERVER_CONFIG.getNetworkReceiver().getUsage();\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/NetworkTransmitterNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.api.network.INetworkNodeVisitor;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.blockentity.NetworkReceiverBlockEntity;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.validator.ItemValidator;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener;\nimport com.refinedmods.refinedstorage.item.NetworkCardItem;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceKey;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport javax.annotation.Nullable;\n\npublic class NetworkTransmitterNetworkNode extends NetworkNode {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"network_transmitter\");\n    private BlockPos receiver;\n    private ResourceKey<Level> receiverDimension;\n    private final BaseItemHandler networkCard = new BaseItemHandler(1)\n        .addValidator(new ItemValidator(RSItems.NETWORK_CARD.get()))\n        .addListener(new NetworkNodeInventoryListener(this))\n        .addListener((handler, slot, reading) -> {\n            ItemStack card = handler.getStackInSlot(slot);\n\n            if (card.isEmpty()) {\n                receiver = null;\n                receiverDimension = null;\n            } else {\n                receiver = NetworkCardItem.getReceiver(card);\n                receiverDimension = NetworkCardItem.getDimension(card);\n            }\n\n            if (network != null) {\n                network.getNodeGraph().invalidate(Action.PERFORM, network.getLevel(), network.getPosition());\n            }\n        });\n\n    public NetworkTransmitterNetworkNode(Level level, BlockPos pos) {\n        super(level, pos);\n    }\n\n    @Override\n    public CompoundTag write(CompoundTag tag) {\n        super.write(tag);\n\n        StackUtils.writeItems(networkCard, 0, tag);\n\n        return tag;\n    }\n\n    @Override\n    public void read(CompoundTag tag) {\n        super.read(tag);\n\n        StackUtils.readItems(networkCard, 0, tag);\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        return RS.SERVER_CONFIG.getNetworkTransmitter().getUsage();\n    }\n\n    public BaseItemHandler getNetworkCard() {\n        return networkCard;\n    }\n\n    @Override\n    public IItemHandler getDrops() {\n        return getNetworkCard();\n    }\n\n    @Nullable\n    public ResourceKey<Level> getReceiverDimension() {\n        return receiverDimension;\n    }\n\n    public int getDistance() {\n        if (receiver == null || receiverDimension == null || !isSameDimension()) {\n            return -1;\n        }\n\n        return (int) Math.sqrt(Math.pow(pos.getX() - receiver.getX(), 2) + Math.pow(pos.getY() - receiver.getY(), 2) + Math.pow(pos.getZ() - receiver.getZ(), 2));\n    }\n\n    public boolean isSameDimension() {\n        return level.dimension() == receiverDimension;\n    }\n\n    private boolean canTransmit() {\n        return canUpdate() && receiver != null && receiverDimension != null;\n    }\n\n    @Override\n    public boolean shouldRebuildGraphOnChange() {\n        return true;\n    }\n\n    @Override\n    public void visit(INetworkNodeVisitor.Operator operator) {\n        super.visit(operator);\n\n        if (canTransmit()) {\n            if (!isSameDimension()) {\n                Level dimensionLevel = level.getServer().getLevel(receiverDimension);\n\n                if (dimensionLevel != null && dimensionLevel.isLoaded(receiver) && dimensionLevel.getBlockEntity(receiver) instanceof NetworkReceiverBlockEntity) {\n                    operator.apply(dimensionLevel, receiver, null);\n                }\n            } else {\n                if (level.isLoaded(receiver) && level.getBlockEntity(receiver) instanceof NetworkReceiverBlockEntity) {\n                    operator.apply(level, receiver, null);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/RelayNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.blockentity.config.RedstoneMode;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\n\npublic class RelayNetworkNode extends NetworkNode {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"relay\");\n\n    public RelayNetworkNode(Level level, BlockPos pos) {\n        super(level, pos);\n        this.redstoneMode = RedstoneMode.LOW;\n    }\n\n    @Override\n    protected int getUpdateThrottleInactiveToActive() {\n        return 0;\n    }\n\n    @Override\n    protected int getUpdateThrottleActiveToInactive() {\n        return 0;\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        return RS.SERVER_CONFIG.getRelay().getUsage();\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    @Override\n    public boolean canConduct(Direction direction) {\n        return canUpdate();\n    }\n\n    @Override\n    public boolean canReceive(Direction direction) {\n        return true;\n    }\n\n    @Override\n    public boolean shouldRebuildGraphOnChange() {\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/RootNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.INetworkNodeVisitor;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.UUID;\n\npublic class RootNetworkNode implements INetworkNode, INetworkNodeVisitor {\n    private final INetwork network;\n    private final Level level;\n    private final BlockPos pos;\n\n    public RootNetworkNode(INetwork network, Level level, BlockPos pos) {\n        this.network = network;\n        this.level = level;\n        this.pos = pos;\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return null;\n    }\n\n    @Nullable\n    @Override\n    public UUID getOwner() {\n        return null;\n    }\n\n    @Override\n    public void setOwner(@Nullable UUID owner) {\n        // NO OP\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        return 0;\n    }\n\n    @Nonnull\n    @Override\n    public ItemStack getItemStack() {\n        BlockState state = level.getBlockState(pos);\n\n        @SuppressWarnings(\"deprecation\")\n        Item item = Item.byBlock(state.getBlock());\n\n        return new ItemStack(item, 1);\n    }\n\n    @Override\n    public void onConnected(INetwork network) {\n        // NO OP\n    }\n\n    @Override\n    public void onDisconnected(INetwork network) {\n        // NO OP\n    }\n\n    @Override\n    public boolean isActive() {\n        return false;\n    }\n\n    @Override\n    public INetwork getNetwork() {\n        return network;\n    }\n\n    @Override\n    public void update() {\n        // NO OP\n    }\n\n    @Override\n    public CompoundTag write(CompoundTag tag) {\n        return tag;\n    }\n\n    @Override\n    public BlockPos getPos() {\n        return pos;\n    }\n\n    @Override\n    public Level getLevel() {\n        return level;\n    }\n\n    @Override\n    public void markDirty() {\n        // NO OP\n    }\n\n    @Override\n    public void visit(Operator operator) {\n        for (Direction facing : Direction.values()) {\n            BlockPos relativePos = pos.relative(facing);\n            if (!level.isLoaded(relativePos)) {\n                continue;\n            }\n            operator.apply(level, relativePos, facing.getOpposite());\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/SecurityManagerNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.security.ISecurityCard;\nimport com.refinedmods.refinedstorage.api.network.security.ISecurityCardContainer;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.apiimpl.network.security.SecurityCard;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.validator.ItemValidator;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener;\nimport com.refinedmods.refinedstorage.item.SecurityCardItem;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport net.neoforged.neoforge.items.wrapper.CombinedInvWrapper;\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.UUID;\n\npublic class SecurityManagerNetworkNode extends NetworkNode implements ISecurityCardContainer {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"security_manager\");\n\n    private final List<ISecurityCard> cards = new ArrayList<>();\n    private final BaseItemHandler editCard = new BaseItemHandler(1)\n        .addValidator(new ItemValidator(RSItems.SECURITY_CARD.get()))\n        .addListener(new NetworkNodeInventoryListener(this));\n    private ISecurityCard globalCard;\n    public SecurityManagerNetworkNode(Level level, BlockPos pos) {\n        super(level, pos);\n    }    private final BaseItemHandler cardsInv = new BaseItemHandler(9 * 2)\n        .addValidator(new ItemValidator(RSItems.SECURITY_CARD.get()))\n        .addListener(new NetworkNodeInventoryListener(this))\n        .addListener(((handler, slot, reading) -> {\n            if (!level.isClientSide) {\n                invalidate();\n            }\n\n            if (network != null) {\n                network.getSecurityManager().invalidate();\n            }\n        }));\n\n    @Override\n    public int getEnergyUsage() {\n        int usage = RS.SERVER_CONFIG.getSecurityManager().getUsage();\n\n        for (int i = 0; i < cardsInv.getSlots(); ++i) {\n            if (!cardsInv.getStackInSlot(i).isEmpty()) {\n                usage += RS.SERVER_CONFIG.getSecurityManager().getUsagePerCard();\n            }\n        }\n\n        return usage;\n    }\n\n    @Override\n    public void update() {\n        super.update();\n\n        if (ticks == 1) {\n            invalidate();\n        }\n    }\n\n    private void invalidate() {\n        this.cards.clear();\n        this.globalCard = null;\n\n        for (int i = 0; i < cardsInv.getSlots(); ++i) {\n            ItemStack stack = cardsInv.getStackInSlot(i);\n\n            if (!stack.isEmpty()) {\n                UUID uuid = SecurityCardItem.getOwner(stack);\n\n                if (uuid == null) {\n                    this.globalCard = createCard(stack, null);\n\n                    continue;\n                }\n\n                this.cards.add(createCard(stack, uuid));\n            }\n        }\n    }\n\n    private ISecurityCard createCard(ItemStack stack, @Nullable UUID uuid) {\n        SecurityCard card = new SecurityCard(uuid);\n\n        for (Permission permission : Permission.values()) {\n            card.getPermissions().put(permission, SecurityCardItem.hasPermission(stack, permission));\n        }\n\n        return card;\n    }\n\n    @Override\n    public void read(CompoundTag tag) {\n        super.read(tag);\n\n        StackUtils.readItems(cardsInv, 0, tag);\n        StackUtils.readItems(editCard, 1, tag);\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    @Override\n    public CompoundTag write(CompoundTag tag) {\n        super.write(tag);\n\n        StackUtils.writeItems(cardsInv, 0, tag);\n        StackUtils.writeItems(editCard, 1, tag);\n\n        return tag;\n    }\n\n    @Override\n    public void onConnectedStateChange(INetwork network, boolean state, ConnectivityStateChangeCause cause) {\n        super.onConnectedStateChange(network, state, cause);\n\n        network.getSecurityManager().invalidate();\n    }\n\n    public BaseItemHandler getCardsItems() {\n        return cardsInv;\n    }\n\n    public BaseItemHandler getEditCard() {\n        return editCard;\n    }\n\n    public void updatePermission(Permission permission, boolean state) {\n        ItemStack card = getEditCard().getStackInSlot(0);\n\n        if (!card.isEmpty()) {\n            SecurityCardItem.setPermission(card, permission, state);\n        }\n    }\n\n    @Override\n    public List<ISecurityCard> getCards() {\n        return cards;\n    }\n\n    @Nullable\n    @Override\n    public ISecurityCard getGlobalCard() {\n        return globalCard;\n    }\n\n    @Override\n    public IItemHandler getDrops() {\n        return new CombinedInvWrapper(cardsInv, editCard);\n    }\n\n\n\n\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/SlottedCraftingRequest.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\n\nimport java.util.Objects;\n\npublic class SlottedCraftingRequest {\n    private final INetworkNode node;\n    private final int slot;\n\n    public SlottedCraftingRequest(INetworkNode node, int slot) {\n        this.node = node;\n        this.slot = slot;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SlottedCraftingRequest that = (SlottedCraftingRequest) o;\n\n        return slot == that.slot && Objects.equals(node, that.node);\n    }\n\n    @Override\n    public int hashCode() {\n        return Objects.hash(node, slot);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/StorageMonitorNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.blockentity.StorageMonitorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IComparable;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.blockentity.config.RedstoneMode;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport com.refinedmods.refinedstorage.util.StackUtils;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.Containers;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.capabilities.Capabilities;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.fluids.FluidType;\nimport net.neoforged.neoforge.fluids.capability.IFluidHandler;\nimport net.neoforged.neoforge.fluids.capability.IFluidHandlerItem;\nimport org.apache.commons.lang3.tuple.Pair;\n\npublic class StorageMonitorNetworkNode extends NetworkNode implements IComparable, IType {\n    public static final int DEPOSIT_ALL_MAX_DELAY = 500;\n\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"storage_monitor\");\n\n    private static final String NBT_COMPARE = \"Compare\";\n    private static final String NBT_TYPE = \"Type\";\n    private static final String NBT_FLUID_FILTERS = \"FluidFilters\";\n\n    private final BaseItemHandler itemFilter = new BaseItemHandler(1)\n        .addListener(new NetworkNodeInventoryListener(this))\n        .addListener((handler, slot, reading) -> {\n            if (!reading) {\n                LevelUtils.updateBlock(level, pos);\n            }\n        });\n\n    private final FluidInventory fluidFilter = new FluidInventory(1, FluidType.BUCKET_VOLUME)\n        .addListener((handler, slot, reading) -> {\n            if (!reading) {\n                LevelUtils.updateBlock(level, pos);\n            }\n        });\n    private final Map<String, Pair<ItemStack, Long>> deposits = new HashMap<>();\n\n    private int compare = IComparer.COMPARE_NBT;\n    private int type = IType.ITEMS;\n\n    private int oldAmount = -1;\n\n    public StorageMonitorNetworkNode(Level level, BlockPos pos) {\n        super(level, pos);\n    }\n\n    @Override\n    public void update() {\n        super.update();\n\n        if (!canUpdate()) {\n            return;\n        }\n\n        int newAmount = getAmount();\n\n        if (oldAmount == -1) {\n            oldAmount = newAmount;\n        } else if (oldAmount != newAmount) {\n            oldAmount = newAmount;\n\n            LevelUtils.updateBlock(level, pos);\n        }\n    }\n\n    public InteractionResult depositAll(Player player) {\n        if (getType() != IType.ITEMS) {\n            return InteractionResult.FAIL;\n        }\n\n        if (network == null) {\n            return InteractionResult.FAIL;\n        }\n\n        if (!network.getSecurityManager().hasPermission(Permission.INSERT, player)) {\n            return InteractionResult.FAIL;\n        }\n\n        Pair<ItemStack, Long> deposit = deposits.get(player.getGameProfile().getName());\n\n        if (deposit == null) {\n            return InteractionResult.FAIL;\n        }\n\n        ItemStack inserted = deposit.getKey();\n        long insertedAt = deposit.getValue();\n\n        if (System.currentTimeMillis() - insertedAt < DEPOSIT_ALL_MAX_DELAY) {\n            for (int i = 0; i < player.getInventory().getContainerSize(); ++i) {\n                ItemStack toInsert = player.getInventory().getItem(i);\n\n                if (API.instance().getComparer().isEqual(inserted, toInsert, compare)) {\n                    player.getInventory().setItem(i, network.insertItemTracked(toInsert, toInsert.getCount()));\n                }\n            }\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n\n    public InteractionResult deposit(Player player, ItemStack toInsert) {\n        if (network == null) {\n            return InteractionResult.FAIL;\n        }\n\n        if (!network.getSecurityManager().hasPermission(Permission.INSERT, player)) {\n            return InteractionResult.FAIL;\n        }\n\n        if (getType() == IType.ITEMS) {\n            depositItems(player, toInsert);\n        } else if (getType() == IType.FLUIDS) {\n            depositFluids(player, toInsert);\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n\n    private void depositItems(Player player, ItemStack toInsert) {\n        ItemStack filter = itemFilter.getStackInSlot(0);\n\n        if (!filter.isEmpty() && API.instance().getComparer().isEqual(filter, toInsert, compare)) {\n            player.getInventory()\n                .setItem(player.getInventory().selected, network.insertItemTracked(toInsert, toInsert.getCount()));\n\n            deposits.put(player.getGameProfile().getName(), Pair.of(toInsert, System.currentTimeMillis()));\n        }\n    }\n\n    private void depositFluids(Player player, ItemStack toInsert) {\n        FluidStack filter = fluidFilter.getFluid(0);\n\n        Pair<ItemStack, FluidStack> result = StackUtils.getFluid(toInsert, true);\n\n        if (filter.isEmpty() || !API.instance().getComparer().isEqual(filter, result.getRight(), compare)) {\n            return;\n        }\n\n        if (!result.getValue().isEmpty() &&\n            network.insertFluid(result.getValue(), result.getValue().getAmount(), Action.SIMULATE).isEmpty()) {\n            network.getFluidStorageTracker().changed(player, result.getValue().copy());\n\n            result = StackUtils.getFluid(toInsert, false);\n\n            network.insertFluidTracked(result.getValue(), result.getValue().getAmount());\n\n            player.getInventory().setItem(player.getInventory().selected, ItemStack.EMPTY);\n\n            ItemStack container = result.getLeft();\n            if (!player.getInventory().add(container.copy())) {\n                Containers.dropItemStack(player.getCommandSenderWorld(), player.getX(), player.getY(), player.getZ(),\n                    container);\n            }\n        }\n    }\n\n    public void extract(Player player, Direction side) {\n        if (network == null || getDirection() != side) {\n            return;\n        }\n\n        if (!network.getSecurityManager().hasPermission(Permission.EXTRACT, player)) {\n            return;\n        }\n\n        if (getType() == IType.ITEMS) {\n            extractItems(player);\n        } else if (getType() == IType.FLUIDS) {\n            extractFluids(player);\n        }\n    }\n\n    private void extractItems(Player player) {\n        ItemStack filter = itemFilter.getStackInSlot(0);\n\n        int toExtract = player.isCrouching() ? 1 : filter.getMaxStackSize();\n\n        if (!filter.isEmpty()) {\n            ItemStack result = network.extractItem(filter, toExtract, compare, Action.PERFORM);\n\n            if (!result.isEmpty() && !player.getInventory().add(result.copy())) {\n                Containers.dropItemStack(level, player.getX(), player.getY(), player.getZ(), result);\n            }\n        }\n    }\n\n    private void extractFluids(Player player) {\n        FluidStack filter = fluidFilter.getFluid(0);\n\n        if (filter.isEmpty()) {\n            return;\n        }\n\n        FluidStack stack = network.getFluidStorageCache().getList().get(filter);\n        if (stack == null || stack.getAmount() < FluidType.BUCKET_VOLUME) {\n            return;\n        }\n\n        boolean shift = player.isCrouching();\n        if (shift) {\n            NetworkUtils.extractBucketFromPlayerInventoryOrNetwork(player, network, bucket -> {\n                IFluidHandlerItem fluidHandler = bucket.getCapability(Capabilities.FluidHandler.ITEM);\n                if (fluidHandler == null) {\n                    return;\n                }\n                network.getFluidStorageTracker().changed(player, stack.copy());\n\n                fluidHandler.fill(network.extractFluid(stack, FluidType.BUCKET_VOLUME, Action.PERFORM),\n                    IFluidHandler.FluidAction.EXECUTE);\n\n                if (!player.getInventory().add(fluidHandler.getContainer().copy())) {\n                    Containers.dropItemStack(player.getCommandSenderWorld(), player.getX(), player.getY(),\n                        player.getZ(), fluidHandler.getContainer());\n                }\n            });\n        }\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        return RS.SERVER_CONFIG.getStorageMonitor().getUsage();\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    @Override\n    public int getCompare() {\n        return compare;\n    }\n\n    @Override\n    public void setCompare(int compare) {\n        this.compare = compare;\n\n        LevelUtils.updateBlock(level, pos);\n\n        markDirty();\n    }\n\n    @Override\n    public CompoundTag writeConfiguration(CompoundTag tag) {\n        super.writeConfiguration(tag);\n\n        tag.putInt(NBT_COMPARE, compare);\n        tag.putInt(NBT_TYPE, type);\n\n        StackUtils.writeItems(itemFilter, 0, tag);\n\n        tag.put(NBT_FLUID_FILTERS, fluidFilter.writeToNbt());\n\n        return tag;\n    }\n\n    @Override\n    public void readConfiguration(CompoundTag tag) {\n        super.readConfiguration(tag);\n\n        if (tag.contains(NBT_COMPARE)) {\n            compare = tag.getInt(NBT_COMPARE);\n        }\n\n        if (tag.contains(NBT_TYPE)) {\n            type = tag.getInt(NBT_TYPE);\n        }\n\n        StackUtils.readItems(itemFilter, 0, tag);\n\n        if (tag.contains(NBT_FLUID_FILTERS)) {\n            fluidFilter.readFromNbt(tag.getCompound(NBT_FLUID_FILTERS));\n        }\n    }\n\n    public int getAmount() {\n        if (network == null) {\n            return 0;\n        }\n\n        if (getType() == IType.ITEMS) {\n            ItemStack toCheck = itemFilter.getStackInSlot(0);\n\n            if (toCheck.isEmpty()) {\n                return 0;\n            }\n\n            if (compare == IComparer.COMPARE_NBT) {\n                ItemStack stored = network.getItemStorageCache().getList().get(toCheck, compare);\n                return stored != null ? stored.getCount() : 0;\n            } else {\n                return network.getItemStorageCache().getList().getStacks(toCheck).stream()\n                    .mapToInt(entry -> entry.getStack().getCount()).sum();\n            }\n\n        } else if (getType() == IType.FLUIDS) {\n            FluidStack toCheck = fluidFilter.getFluid(0);\n\n            if (toCheck.isEmpty()) {\n                return 0;\n            }\n\n            FluidStack stored = network.getFluidStorageCache().getList().get(toCheck, compare);\n\n            return stored != null ? stored.getAmount() : 0;\n        }\n        return 0;\n    }\n\n    @Override\n    public int getType() {\n        return level.isClientSide ? StorageMonitorBlockEntity.TYPE.getValue() : type;\n    }\n\n    @Override\n    public void setType(int type) {\n        this.type = type;\n\n        LevelUtils.updateBlock(level, pos);\n        markDirty();\n    }\n\n    public BaseItemHandler getItemFilters() {\n        return itemFilter;\n    }\n\n    @Override\n    public FluidInventory getFluidFilters() {\n        return fluidFilter;\n    }\n\n    @Override\n    public void setRedstoneMode(RedstoneMode mode) {\n        // NO OP\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/WirelessTransmitterNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.IWirelessTransmitter;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.UpgradeItemHandler;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener;\nimport com.refinedmods.refinedstorage.item.UpgradeItem;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceKey;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.items.IItemHandler;\n\npublic class WirelessTransmitterNetworkNode extends NetworkNode implements IWirelessTransmitter {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"wireless_transmitter\");\n\n    private final UpgradeItemHandler upgrades = (UpgradeItemHandler) new UpgradeItemHandler(4, UpgradeItem.Type.RANGE).addListener(new NetworkNodeInventoryListener(this));\n\n    public WirelessTransmitterNetworkNode(Level level, BlockPos pos) {\n        super(level, pos);\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        return RS.SERVER_CONFIG.getWirelessTransmitter().getUsage() + upgrades.getEnergyUsage();\n    }\n\n    @Override\n    public void read(CompoundTag tag) {\n        super.read(tag);\n\n        StackUtils.readItems(upgrades, 0, tag);\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    @Override\n    public CompoundTag write(CompoundTag tag) {\n        super.write(tag);\n\n        StackUtils.writeItems(upgrades, 0, tag);\n\n        return tag;\n    }\n\n    @Override\n    public int getRange() {\n        return RS.SERVER_CONFIG.getWirelessTransmitter().getBaseRange() + (upgrades.getUpgradeCount(UpgradeItem.Type.RANGE) * RS.SERVER_CONFIG.getWirelessTransmitter().getRangePerUpgrade());\n    }\n\n    @Override\n    public BlockPos getOrigin() {\n        return pos;\n    }\n\n    @Override\n    public ResourceKey<Level> getDimension() {\n        return level.dimension();\n    }\n\n    public BaseItemHandler getUpgrades() {\n        return upgrades;\n    }\n\n    @Override\n    public IItemHandler getDrops() {\n        return getUpgrades();\n    }\n\n    @Override\n    public boolean canConduct(Direction direction) {\n        return getDirection() == direction;\n    }\n\n    @Override\n    public void visit(Operator operator) {\n        operator.apply(level, pos.relative(Direction.DOWN), Direction.UP);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/cover/Cover.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node.cover;\n\nimport net.minecraft.world.item.ItemStack;\n\npublic class Cover {\n\n    private ItemStack stack;\n    private CoverType type;\n\n    public Cover(ItemStack stack, CoverType type) {\n        this.stack = stack;\n        this.type = type;\n    }\n\n    public ItemStack getStack() {\n        return stack;\n    }\n\n    public CoverType getType() {\n        return type;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/cover/CoverManager.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node.cover;\n\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.CableNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.NetworkNode;\nimport com.refinedmods.refinedstorage.item.CoverItem;\nimport net.minecraft.core.Direction;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.Block;\nimport net.minecraft.world.level.block.Blocks;\nimport net.minecraft.world.level.block.EntityBlock;\nimport net.minecraft.world.level.block.RenderShape;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.model.data.ModelProperty;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport net.neoforged.neoforge.items.ItemStackHandler;\nimport javax.annotation.Nullable;\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class CoverManager {\n\n    public static final ModelProperty<CoverManager> PROPERTY = new ModelProperty<>();\n    private static final String NBT_DIRECTION = \"Direction\";\n    private static final String NBT_ITEM = \"Item\";\n    private static final String NBT_TYPE = \"Type\";\n    public static String NBT_COVER_MANAGER = \"Cover\";\n    private Map<Direction, Cover> covers = new HashMap<>();\n    private NetworkNode node;\n\n    public CoverManager(NetworkNode node) {\n        this.node = node;\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    public static boolean isValidCover(ItemStack item) {\n        if (item.isEmpty()) {\n            return false;\n        }\n\n        Block block = getBlock(item);\n\n        BlockState state = getBlockState(item);\n\n        return block != null\n            && state != null\n            && isModelSupported(state)\n            && !block.isRandomlyTicking(state)\n            && !(block instanceof EntityBlock)\n            && !state.useShapeForLightOcclusion();\n    }\n\n    private static boolean isModelSupported(BlockState state) {\n        if (state.getRenderShape() != RenderShape.MODEL) {\n            return false;\n        }\n\n        return state.canOcclude();\n    }\n\n    @Nullable\n    public static Block getBlock(ItemStack item) {\n        if (item.isEmpty()) {\n            return null;\n        }\n\n        Block block = Block.byItem(item.getItem());\n\n        if (block == Blocks.AIR) {\n            return null;\n        }\n\n        return block;\n    }\n\n    @Nullable\n    public static BlockState getBlockState(ItemStack item) {\n        Block block = getBlock(item);\n        if (block == null) {\n            return null;\n        }\n        return block.defaultBlockState();\n    }\n\n    @Nullable\n    public Cover getCover(Direction facing) {\n        return covers.get(facing);\n    }\n\n    public boolean hasCover(Direction facing) {\n        return covers.containsKey(facing);\n    }\n\n    public boolean setCover(Direction facing, @Nullable Cover cover) {\n        if (cover == null || (isValidCover(cover.getStack()) && !hasCover(facing))) {\n            if (cover != null) {\n                if (!(node instanceof CableNetworkNode) && facing == node.getDirection() && cover.getType() != CoverType.HOLLOW) {\n                    return false;\n                }\n            }\n\n            if (cover == null) {\n                covers.remove(facing);\n            } else {\n                covers.put(facing, cover);\n            }\n\n            node.markDirty();\n\n            if (node.getNetwork() != null) {\n                node.getNetwork().getNodeGraph().invalidate(Action.PERFORM, node.getNetwork().getLevel(), node.getNetwork().getPosition());\n            }\n\n            return true;\n        }\n\n        return false;\n    }\n\n    @Nullable\n    public Cover removeCover(Direction direction) {\n        if (hasCover(direction)) {\n            Cover cover = covers.remove(direction);\n\n            node.markDirty();\n\n            if (node.getNetwork() != null) {\n                node.getNetwork().getNodeGraph().invalidate(Action.PERFORM, node.getNetwork().getLevel(), node.getNetwork().getPosition());\n            }\n\n            return cover;\n        }\n        return null;\n    }\n\n    public void readFromNbt(CompoundTag nbt) {\n        covers.clear();\n        for (String s : nbt.getAllKeys()) {\n            CompoundTag tag = nbt.getCompound(s);\n            if (tag.contains(NBT_DIRECTION) && tag.contains(NBT_ITEM)) {\n                Direction direction = Direction.from3DDataValue(tag.getInt(NBT_DIRECTION));\n                ItemStack item = ItemStack.of(tag.getCompound(NBT_ITEM));\n                int type = tag.contains(NBT_TYPE) ? tag.getInt(NBT_TYPE) : 0;\n\n                if (type >= CoverType.values().length) {\n                    type = 0;\n                }\n\n                if (isValidCover(item)) {\n                    covers.put(direction, new Cover(item, CoverType.values()[type]));\n                }\n            }\n        }\n    }\n\n    public CompoundTag writeToNbt() {\n        CompoundTag list = new CompoundTag();\n\n        for (Map.Entry<Direction, Cover> entry : covers.entrySet()) {\n            CompoundTag tag = new CompoundTag();\n\n            tag.putInt(NBT_DIRECTION, entry.getKey().ordinal());\n            tag.put(NBT_ITEM, entry.getValue().getStack().save(new CompoundTag()));\n            tag.putInt(NBT_TYPE, entry.getValue().getType().ordinal());\n\n            list.put(entry.getKey().ordinal() + \"\", tag);\n        }\n        return list;\n    }\n\n    public IItemHandlerModifiable getAsInventory() {\n        ItemStackHandler handler = new ItemStackHandler(covers.size());\n\n        int i = 0;\n\n        for (Map.Entry<Direction, Cover> entry : covers.entrySet()) {\n            ItemStack cover = entry.getValue().getType().createStack();\n\n            CoverItem.setItem(cover, entry.getValue().getStack());\n\n            handler.setStackInSlot(i++, cover);\n        }\n\n        return handler;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/cover/CoverType.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node.cover;\n\nimport com.refinedmods.refinedstorage.RSItems;\nimport net.minecraft.world.item.ItemStack;\n\npublic enum CoverType {\n    NORMAL,\n    HOLLOW;\n\n    public ItemStack createStack() {\n        return new ItemStack(this == NORMAL ? RSItems.COVER.get() : RSItems.HOLLOW_COVER.get());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/diskdrive/DiskDriveNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node.diskdrive;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.IStorage;\nimport com.refinedmods.refinedstorage.api.storage.IStorageProvider;\nimport com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.ConnectivityStateChangeCause;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.DiskState;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.NetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.storage.cache.FluidStorageCache;\nimport com.refinedmods.refinedstorage.apiimpl.storage.cache.ItemStorageCache;\nimport com.refinedmods.refinedstorage.blockentity.DiskDriveBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.*;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.validator.StorageDiskItemValidator;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener;\nimport com.refinedmods.refinedstorage.util.AccessTypeUtils;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\n\nimport java.util.List;\n\npublic class DiskDriveNetworkNode extends NetworkNode implements IStorageProvider, IComparable, IWhitelistBlacklist, IPrioritizable, IType, IAccessType, IStorageDiskContainerContext {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"disk_drive\");\n\n    private static final String NBT_PRIORITY = \"Priority\";\n    private static final String NBT_COMPARE = \"Compare\";\n    private static final String NBT_MODE = \"Mode\";\n    private static final String NBT_TYPE = \"Type\";\n    private static final String NBT_FLUID_FILTERS = \"FluidFilters\";\n\n    private static final int DISK_STATE_UPDATE_THROTTLE = 30;\n\n    private static final Logger LOGGER = LogManager.getLogger(DiskDriveNetworkNode.class);\n    private final BaseItemHandler itemFilters = new BaseItemHandler(9).addListener(new NetworkNodeInventoryListener(this));\n    private final FluidInventory fluidFilters = new FluidInventory(9).addListener(new NetworkNodeFluidInventoryListener(this));\n    private final IStorageDisk[] itemDisks = new IStorageDisk[8];\n    private final IStorageDisk[] fluidDisks = new IStorageDisk[8];\n    private final BaseItemHandler disks = new BaseItemHandler(8)\n        .addValidator(new StorageDiskItemValidator())\n        .addListener(new NetworkNodeInventoryListener(this))\n        .addListener((handler, slot, reading) -> {\n            if (!level.isClientSide) {\n                StackUtils.createStorages(\n                    (ServerLevel) level,\n                    handler.getStackInSlot(slot),\n                    slot,\n                    itemDisks,\n                    fluidDisks,\n                    s -> new ItemDriveWrapperStorageDisk(DiskDriveNetworkNode.this, s),\n                    s -> new FluidDriveWrapperStorageDisk(DiskDriveNetworkNode.this, s)\n                );\n\n                if (network != null) {\n                    network.getItemStorageCache().invalidate(InvalidateCause.DISK_INVENTORY_CHANGED);\n                    network.getFluidStorageCache().invalidate(InvalidateCause.DISK_INVENTORY_CHANGED);\n                }\n\n                if (!reading) {\n                    LevelUtils.updateBlock(level, pos);\n                }\n            }\n        });\n    private int ticksSinceBlockUpdateRequested;\n    private boolean blockUpdateRequested;\n    private AccessType accessType = AccessType.INSERT_EXTRACT;\n    private int priority = 0;\n    private int compare = IComparer.COMPARE_NBT;\n    private int mode = IWhitelistBlacklist.BLACKLIST;\n    private int type = IType.ITEMS;\n\n    public DiskDriveNetworkNode(Level level, BlockPos pos) {\n        super(level, pos);\n    }\n\n    public IStorageDisk[] getItemDisks() {\n        return itemDisks;\n    }\n\n    public IStorageDisk[] getFluidDisks() {\n        return fluidDisks;\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        int usage = RS.SERVER_CONFIG.getDiskDrive().getUsage();\n\n        for (IStorage storage : itemDisks) {\n            if (storage != null) {\n                usage += RS.SERVER_CONFIG.getDiskDrive().getDiskUsage();\n            }\n        }\n        for (IStorage storage : fluidDisks) {\n            if (storage != null) {\n                usage += RS.SERVER_CONFIG.getDiskDrive().getDiskUsage();\n            }\n        }\n\n        return usage;\n    }\n\n    @Override\n    public void update() {\n        super.update();\n\n        if (blockUpdateRequested) {\n            ++ticksSinceBlockUpdateRequested;\n\n            if (ticksSinceBlockUpdateRequested > DISK_STATE_UPDATE_THROTTLE) {\n                LevelUtils.updateBlock(level, pos);\n\n                this.blockUpdateRequested = false;\n                this.ticksSinceBlockUpdateRequested = 0;\n            }\n        } else {\n            this.ticksSinceBlockUpdateRequested = 0;\n        }\n    }\n\n    void requestBlockUpdate() {\n        this.blockUpdateRequested = true;\n    }\n\n    @Override\n    public void onConnectedStateChange(INetwork network, boolean state, ConnectivityStateChangeCause cause) {\n        super.onConnectedStateChange(network, state, cause);\n\n        LOGGER.debug(\"Connectivity state of disk drive at {} changed to {} due to {}\", pos, state, cause);\n\n        network.getNodeGraph().runActionWhenPossible(ItemStorageCache.INVALIDATE_ACTION.apply(InvalidateCause.CONNECTED_STATE_CHANGED));\n        network.getNodeGraph().runActionWhenPossible(FluidStorageCache.INVALIDATE_ACTION.apply(InvalidateCause.CONNECTED_STATE_CHANGED));\n\n        LevelUtils.updateBlock(level, pos);\n    }\n\n    @Override\n    public void addItemStorages(List<IStorage<ItemStack>> storages) {\n        for (IStorage<ItemStack> storage : this.itemDisks) {\n            if (storage != null) {\n                storages.add(storage);\n            }\n        }\n    }\n\n    @Override\n    public void addFluidStorages(List<IStorage<FluidStack>> storages) {\n        for (IStorage<FluidStack> storage : this.fluidDisks) {\n            if (storage != null) {\n                storages.add(storage);\n            }\n        }\n    }\n\n    @Override\n    public void read(CompoundTag tag) {\n        super.read(tag);\n\n        StackUtils.readItems(disks, 0, tag);\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    @Override\n    public CompoundTag write(CompoundTag tag) {\n        super.write(tag);\n\n        StackUtils.writeItems(disks, 0, tag);\n\n        return tag;\n    }\n\n    @Override\n    public CompoundTag writeConfiguration(CompoundTag tag) {\n        super.writeConfiguration(tag);\n\n        StackUtils.writeItems(itemFilters, 1, tag);\n\n        tag.put(NBT_FLUID_FILTERS, fluidFilters.writeToNbt());\n        tag.putInt(NBT_PRIORITY, priority);\n        tag.putInt(NBT_COMPARE, compare);\n        tag.putInt(NBT_MODE, mode);\n        tag.putInt(NBT_TYPE, type);\n\n        AccessTypeUtils.writeAccessType(tag, accessType);\n\n        return tag;\n    }\n\n    @Override\n    public void readConfiguration(CompoundTag tag) {\n        super.readConfiguration(tag);\n\n        StackUtils.readItems(itemFilters, 1, tag);\n\n        if (tag.contains(NBT_FLUID_FILTERS)) {\n            fluidFilters.readFromNbt(tag.getCompound(NBT_FLUID_FILTERS));\n        }\n\n        if (tag.contains(NBT_PRIORITY)) {\n            priority = tag.getInt(NBT_PRIORITY);\n        }\n\n        if (tag.contains(NBT_COMPARE)) {\n            compare = tag.getInt(NBT_COMPARE);\n        }\n\n        if (tag.contains(NBT_MODE)) {\n            mode = tag.getInt(NBT_MODE);\n        }\n\n        if (tag.contains(NBT_TYPE)) {\n            type = tag.getInt(NBT_TYPE);\n        }\n\n        accessType = AccessTypeUtils.readAccessType(tag);\n    }\n\n    @Override\n    public int getCompare() {\n        return compare;\n    }\n\n    @Override\n    public void setCompare(int compare) {\n        this.compare = compare;\n\n        markDirty();\n    }\n\n    @Override\n    public int getWhitelistBlacklistMode() {\n        return mode;\n    }\n\n    @Override\n    public void setWhitelistBlacklistMode(int mode) {\n        this.mode = mode;\n\n        markDirty();\n    }\n\n    @Override\n    public AccessType getAccessType() {\n        return accessType;\n    }\n\n    @Override\n    public void setAccessType(AccessType value) {\n        this.accessType = value;\n\n        if (network != null) {\n            network.getFluidStorageCache().invalidate(InvalidateCause.DEVICE_CONFIGURATION_CHANGED);\n            network.getItemStorageCache().invalidate(InvalidateCause.DEVICE_CONFIGURATION_CHANGED);\n        }\n\n        markDirty();\n    }\n\n    @Override\n    public int getPriority() {\n        return priority;\n    }\n\n    @Override\n    public void setPriority(int priority) {\n        this.priority = priority;\n\n        markDirty();\n\n        if (network != null) {\n            network.getItemStorageCache().sort();\n            network.getFluidStorageCache().sort();\n        }\n    }\n\n    public DiskState[] getDiskState() {\n        DiskState[] diskStates = new DiskState[8];\n\n        for (int i = 0; i < 8; ++i) {\n            DiskState state = DiskState.NONE;\n\n            if (itemDisks[i] != null || fluidDisks[i] != null) {\n                if (!canUpdate()) {\n                    state = DiskState.DISCONNECTED;\n                } else {\n                    state = DiskState.get(\n                        itemDisks[i] != null ? itemDisks[i].getStored() : fluidDisks[i].getStored(),\n                        itemDisks[i] != null ? itemDisks[i].getCapacity() : fluidDisks[i].getCapacity()\n                    );\n                }\n            }\n\n            diskStates[i] = state;\n        }\n\n        return diskStates;\n    }\n\n    public IItemHandler getDisks() {\n        return disks;\n    }\n\n    @Override\n    public int getType() {\n        return level.isClientSide ? DiskDriveBlockEntity.TYPE.getValue() : type;\n    }\n\n    @Override\n    public void setType(int type) {\n        this.type = type;\n\n        markDirty();\n    }\n\n    @Override\n    public IItemHandlerModifiable getItemFilters() {\n        return itemFilters;\n    }\n\n    @Override\n    public FluidInventory getFluidFilters() {\n        return fluidFilters;\n    }\n\n    @Override\n    public IItemHandler getDrops() {\n        return getDisks();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/diskdrive/FluidDriveWrapperStorageDisk.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node.diskdrive;\n\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskListener;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.DiskState;\nimport com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.Collection;\nimport java.util.UUID;\n\npublic class FluidDriveWrapperStorageDisk implements IStorageDisk<FluidStack> {\n    private final DiskDriveNetworkNode diskDrive;\n    private final IStorageDisk<FluidStack> parent;\n    private DiskState lastState;\n\n    public FluidDriveWrapperStorageDisk(DiskDriveNetworkNode diskDrive, IStorageDisk<FluidStack> parent) {\n        this.diskDrive = diskDrive;\n        this.parent = parent;\n        this.setSettings(\n            () -> {\n                DiskState currentState = DiskState.get(getStored(), getCapacity());\n\n                if (this.lastState != currentState) {\n                    this.lastState = currentState;\n\n                    diskDrive.requestBlockUpdate();\n                }\n            },\n            diskDrive\n        );\n        this.lastState = DiskState.get(getStored(), getCapacity());\n    }\n\n    @Override\n    public int getPriority() {\n        return diskDrive.getPriority();\n    }\n\n    @Override\n    public AccessType getAccessType() {\n        return parent.getAccessType();\n    }\n\n    @Override\n    public Collection<FluidStack> getStacks() {\n        return parent.getStacks();\n    }\n\n    @Override\n    @Nonnull\n    public FluidStack insert(@Nonnull FluidStack stack, int size, Action action) {\n        if (!IWhitelistBlacklist.acceptsFluid(diskDrive.getFluidFilters(), diskDrive.getWhitelistBlacklistMode(), diskDrive.getCompare(), stack)) {\n            return StackUtils.copy(stack, size);\n        }\n\n        return parent.insert(stack, size, action);\n    }\n\n    @Override\n    @Nonnull\n    public FluidStack extract(@Nonnull FluidStack stack, int size, int flags, Action action) {\n        return parent.extract(stack, size, flags, action);\n    }\n\n    @Override\n    public int getStored() {\n        return parent.getStored();\n    }\n\n    @Override\n    public int getCacheDelta(int storedPreInsertion, int size, @Nullable FluidStack remainder) {\n        return parent.getCacheDelta(storedPreInsertion, size, remainder);\n    }\n\n    @Override\n    public int getCapacity() {\n        return parent.getCapacity();\n    }\n\n    @Nullable\n    @Override\n    public UUID getOwner() {\n        return parent.getOwner();\n    }\n\n    @Override\n    public void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context) {\n        parent.setSettings(listener, context);\n    }\n\n    @Override\n    public CompoundTag writeToNbt() {\n        return parent.writeToNbt();\n    }\n\n    @Override\n    public ResourceLocation getFactoryId() {\n        return parent.getFactoryId();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/diskdrive/ItemDriveWrapperStorageDisk.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node.diskdrive;\n\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskListener;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.DiskState;\nimport com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.Collection;\nimport java.util.UUID;\n\npublic class ItemDriveWrapperStorageDisk implements IStorageDisk<ItemStack> {\n    private final DiskDriveNetworkNode diskDrive;\n    private final IStorageDisk<ItemStack> parent;\n    private DiskState lastState;\n\n    public ItemDriveWrapperStorageDisk(DiskDriveNetworkNode diskDrive, IStorageDisk<ItemStack> parent) {\n        this.diskDrive = diskDrive;\n        this.parent = parent;\n        this.setSettings(\n            () -> {\n                DiskState currentState = DiskState.get(getStored(), getCapacity());\n\n                if (this.lastState != currentState) {\n                    this.lastState = currentState;\n\n                    diskDrive.requestBlockUpdate();\n                }\n            },\n            diskDrive\n        );\n        this.lastState = DiskState.get(getStored(), getCapacity());\n    }\n\n    @Override\n    public int getPriority() {\n        return diskDrive.getPriority();\n    }\n\n    @Override\n    public AccessType getAccessType() {\n        return parent.getAccessType();\n    }\n\n    @Override\n    public Collection<ItemStack> getStacks() {\n        return parent.getStacks();\n    }\n\n    @Override\n    @Nonnull\n    public ItemStack insert(@Nonnull ItemStack stack, int size, Action action) {\n        if (!IWhitelistBlacklist.acceptsItem(diskDrive.getItemFilters(), diskDrive.getWhitelistBlacklistMode(), diskDrive.getCompare(), stack)) {\n            return ItemHandlerHelper.copyStackWithSize(stack, size);\n        }\n\n        return parent.insert(stack, size, action);\n    }\n\n    @Override\n    @Nonnull\n    public ItemStack extract(@Nonnull ItemStack stack, int size, int flags, Action action) {\n        return parent.extract(stack, size, flags, action);\n    }\n\n    @Override\n    public int getStored() {\n        return parent.getStored();\n    }\n\n    @Override\n    public int getCacheDelta(int storedPreInsertion, int size, @Nullable ItemStack remainder) {\n        return parent.getCacheDelta(storedPreInsertion, size, remainder);\n    }\n\n    @Override\n    public int getCapacity() {\n        return parent.getCapacity();\n    }\n\n    @Nullable\n    @Override\n    public UUID getOwner() {\n        return parent.getOwner();\n    }\n\n    @Override\n    public void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context) {\n        parent.setSettings(listener, context);\n    }\n\n    @Override\n    public CompoundTag writeToNbt() {\n        return parent.writeToNbt();\n    }\n\n    @Override\n    public ResourceLocation getFactoryId() {\n        return parent.getFactoryId();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/diskmanipulator/DiskManipulatorNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node.diskmanipulator;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.api.util.StackListEntry;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.DiskState;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.NetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.DiskManipulatorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IComparable;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.ProxyItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.UpgradeItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.validator.StorageDiskItemValidator;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener;\nimport com.refinedmods.refinedstorage.item.UpgradeItem;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.fluids.FluidType;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport net.neoforged.neoforge.items.wrapper.CombinedInvWrapper;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\npublic class DiskManipulatorNetworkNode extends NetworkNode implements IComparable, IWhitelistBlacklist, IType, IStorageDiskContainerContext {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"disk_manipulator\");\n\n    public static final int IO_MODE_INSERT = 0;\n    public static final int IO_MODE_EXTRACT = 1;\n\n    private static final String NBT_COMPARE = \"Compare\";\n    private static final String NBT_MODE = \"Mode\";\n    private static final String NBT_TYPE = \"Type\";\n    private static final String NBT_IO_MODE = \"IOMode\";\n    private static final String NBT_FLUID_FILTERS = \"FluidFilters\";\n    private final IStorageDisk<ItemStack>[] itemDisks = new IStorageDisk[6];\n    private final IStorageDisk<FluidStack>[] fluidDisks = new IStorageDisk[6];\n    private final BaseItemHandler inputDisks = new BaseItemHandler(3)\n        .addValidator(new StorageDiskItemValidator())\n        .addListener(new NetworkNodeInventoryListener(this))\n        .addListener((handler, slot, reading) -> {\n            if (!level.isClientSide) {\n                StackUtils.createStorages(\n                    (ServerLevel) level,\n                    handler.getStackInSlot(slot),\n                    slot,\n                    itemDisks,\n                    fluidDisks,\n                    s -> new StorageDiskItemManipulatorWrapper(DiskManipulatorNetworkNode.this, s),\n                    s -> new StorageDiskFluidManipulatorWrapper(DiskManipulatorNetworkNode.this, s)\n                );\n\n                if (!reading) {\n                    LevelUtils.updateBlock(level, pos);\n                }\n            }\n        });\n    private final BaseItemHandler outputDisks = new BaseItemHandler(3)\n        .addValidator(new StorageDiskItemValidator())\n        .addListener(new NetworkNodeInventoryListener(this))\n        .addListener(((handler, slot, reading) -> {\n            if (!level.isClientSide) {\n                StackUtils.createStorages(\n                    (ServerLevel) level,\n                    handler.getStackInSlot(slot),\n                    3 + slot,\n                    itemDisks,\n                    fluidDisks,\n                    s -> new StorageDiskItemManipulatorWrapper(DiskManipulatorNetworkNode.this, s),\n                    s -> new StorageDiskFluidManipulatorWrapper(DiskManipulatorNetworkNode.this, s)\n                );\n\n                if (!reading) {\n                    LevelUtils.updateBlock(level, pos);\n                }\n            }\n        }));\n    private final ProxyItemHandler disks = new ProxyItemHandler(inputDisks, outputDisks);\n    private final BaseItemHandler itemFilters = new BaseItemHandler(9).addListener(new NetworkNodeInventoryListener(this));\n    private final FluidInventory fluidFilters = new FluidInventory(9).addListener(new NetworkNodeFluidInventoryListener(this));\n    private int compare = IComparer.COMPARE_NBT;\n    private int mode = IWhitelistBlacklist.BLACKLIST;\n    private int type = IType.ITEMS;\n    private final UpgradeItemHandler upgrades = (UpgradeItemHandler) new UpgradeItemHandler(4, UpgradeItem.Type.SPEED, UpgradeItem.Type.STACK) {\n        @Override\n        public int getStackInteractCount() {\n            int count = super.getStackInteractCount();\n\n            if (type == IType.FLUIDS) {\n                count *= FluidType.BUCKET_VOLUME;\n            }\n\n            return count;\n        }\n    }.addListener(new NetworkNodeInventoryListener(this));\n    private int ioMode = IO_MODE_INSERT;\n\n    public DiskManipulatorNetworkNode(Level level, BlockPos pos) {\n        super(level, pos);\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        return RS.SERVER_CONFIG.getDiskManipulator().getUsage() + upgrades.getEnergyUsage();\n    }\n\n    @Override\n    public void update() {\n        super.update();\n\n        if (!canUpdate() || ticks % upgrades.getSpeed() != 0) {\n            return;\n        }\n\n        int slot = 0;\n        if (type == IType.ITEMS) {\n            while (slot < 3 && (itemDisks[slot] == null || isItemDiskDone(itemDisks[slot], slot))) {\n                slot++;\n            }\n\n            if (slot == 3) {\n                return;\n            }\n\n            IStorageDisk<ItemStack> storage = itemDisks[slot];\n\n            if (ioMode == IO_MODE_INSERT) {\n                insertItemIntoNetwork(storage);\n            } else if (ioMode == IO_MODE_EXTRACT) {\n                extractItemFromNetwork(storage, slot);\n            }\n        } else if (type == IType.FLUIDS) {\n            while (slot < 3 && (fluidDisks[slot] == null || isFluidDiskDone(fluidDisks[slot], slot))) {\n                slot++;\n            }\n\n            if (slot == 3) {\n                return;\n            }\n\n            IStorageDisk<FluidStack> storage = fluidDisks[slot];\n\n            if (ioMode == IO_MODE_INSERT) {\n                insertFluidIntoNetwork(storage, slot);\n            } else if (ioMode == IO_MODE_EXTRACT) {\n                extractFluidFromNetwork(storage, slot);\n            }\n        }\n    }\n\n    private void insertItemIntoNetwork(IStorageDisk<ItemStack> storage) {\n        List<ItemStack> stacks = new ArrayList<>(storage.getStacks());\n\n        for (int i = 0; i < stacks.size(); ++i) {\n            ItemStack stack = stacks.get(i);\n\n            ItemStack extracted = storage.extract(stack, upgrades.getStackInteractCount(), compare, Action.PERFORM);\n            if (extracted.isEmpty()) {\n                continue;\n            }\n\n            ItemStack remainder = network.insertItem(extracted, extracted.getCount(), Action.PERFORM);\n            if (remainder.isEmpty()) {\n                break;\n            }\n\n            // We need to check if the stack was inserted\n            storage.insert(((extracted == remainder) ? remainder.copy() : remainder), remainder.getCount(), Action.PERFORM);\n        }\n    }\n\n    // Iterate through disk stacks, if none can be inserted, return that it is done processing and can be output.\n    private boolean isItemDiskDone(IStorageDisk<ItemStack> storage, int slot) {\n        if (ioMode == IO_MODE_INSERT && storage.getStored() == 0) {\n            moveDriveToOutput(slot);\n            return true;\n        }\n\n        // In Extract mode, we just need to check if the disk is full or not.\n        if (ioMode == IO_MODE_EXTRACT) {\n            if (storage.getStored() == storage.getCapacity()) {\n                moveDriveToOutput(slot);\n                return true;\n            } else {\n                return false;\n            }\n        }\n\n        List<ItemStack> stacks = new ArrayList<>(storage.getStacks());\n\n        for (int i = 0; i < stacks.size(); ++i) {\n            ItemStack stack = stacks.get(i);\n\n            ItemStack extracted = storage.extract(stack, upgrades.getStackInteractCount(), compare, Action.SIMULATE);\n            if (extracted.isEmpty()) {\n                continue;\n            }\n\n            ItemStack remainder = network.insertItem(extracted, extracted.getCount(), Action.SIMULATE);\n            if (remainder.isEmpty()) { // An item could be inserted (no remainders when trying to). This disk isn't done.\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    private void extractItemFromNetwork(IStorageDisk<ItemStack> storage, int slot) {\n        ItemStack extracted = ItemStack.EMPTY;\n        int i = 0;\n\n        if (itemFilters.isEmpty()) {\n            ItemStack toExtract = null;\n            List<ItemStack> networkItems = network.getItemStorageCache().getList().getStacks().stream().map(StackListEntry::getStack).collect(Collectors.toList());\n\n            int j = 0;\n\n            while ((toExtract == null || toExtract.isEmpty()) && j < networkItems.size()) {\n                toExtract = networkItems.get(j++);\n            }\n\n            if (toExtract != null) {\n                extracted = network.extractItem(toExtract, upgrades.getStackInteractCount(), compare, Action.PERFORM);\n            }\n        } else {\n            while (itemFilters.getSlots() > i && extracted.isEmpty()) {\n                ItemStack filterStack = ItemStack.EMPTY;\n\n                while (itemFilters.getSlots() > i && filterStack.isEmpty()) {\n                    filterStack = itemFilters.getStackInSlot(i++);\n                }\n\n                if (!filterStack.isEmpty()) {\n                    extracted = network.extractItem(filterStack, upgrades.getStackInteractCount(), compare, Action.PERFORM);\n                }\n            }\n        }\n\n        if (extracted.isEmpty()) {\n            moveDriveToOutput(slot);\n            return;\n        }\n\n        ItemStack remainder = storage.insert(extracted, extracted.getCount(), Action.PERFORM);\n\n        network.insertItem(remainder, remainder.getCount(), Action.PERFORM);\n    }\n\n    private void insertFluidIntoNetwork(IStorageDisk<FluidStack> storage, int slot) {\n        List<FluidStack> stacks = new ArrayList<>(storage.getStacks());\n\n        FluidStack extracted = FluidStack.EMPTY;\n        int i = 0;\n\n        while (extracted.isEmpty() && stacks.size() > i) {\n            FluidStack stack = stacks.get(i++);\n\n            extracted = storage.extract(stack, upgrades.getStackInteractCount(), compare, Action.PERFORM);\n        }\n\n        if (extracted.isEmpty()) {\n            moveDriveToOutput(slot);\n            return;\n        }\n\n        FluidStack remainder = network.insertFluid(extracted, extracted.getAmount(), Action.PERFORM);\n\n        storage.insert(remainder, remainder.getAmount(), Action.PERFORM);\n    }\n\n    private boolean isFluidDiskDone(IStorageDisk<FluidStack> storage, int slot) {\n        if (ioMode == IO_MODE_INSERT && storage.getStored() == 0) {\n            moveDriveToOutput(slot);\n            return true;\n        }\n\n        //In Extract mode, we just need to check if the disk is full or not.\n        if (ioMode == IO_MODE_EXTRACT) {\n            if (storage.getStored() == storage.getCapacity()) {\n                moveDriveToOutput(slot);\n                return true;\n            } else {\n                return false;\n            }\n        }\n\n        List<FluidStack> stacks = new ArrayList<>(storage.getStacks());\n\n        for (int i = 0; i < stacks.size(); ++i) {\n            FluidStack stack = stacks.get(i);\n\n            FluidStack extracted = storage.extract(stack, upgrades.getStackInteractCount(), compare, Action.SIMULATE);\n            if (extracted.isEmpty()) {\n                continue;\n            }\n\n            FluidStack remainder = network.insertFluid(extracted, extracted.getAmount(), Action.SIMULATE);\n            if (remainder.isEmpty()) { // A fluid could be inserted (no remainders when trying to). This disk isn't done.\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    private void extractFluidFromNetwork(IStorageDisk<FluidStack> storage, int slot) {\n        FluidStack extracted = FluidStack.EMPTY;\n        int i = 0;\n\n        if (fluidFilters.isEmpty()) {\n            FluidStack toExtract = null;\n            List<FluidStack> networkFluids = network.getFluidStorageCache().getList().getStacks().stream().map(StackListEntry::getStack).collect(Collectors.toList());\n\n            int j = 0;\n\n            while ((toExtract == null || toExtract.getAmount() == 0) && j < networkFluids.size()) {\n                toExtract = networkFluids.get(j++);\n            }\n\n            if (toExtract != null) {\n                extracted = network.extractFluid(toExtract, upgrades.getStackInteractCount(), compare, Action.PERFORM);\n            }\n        } else {\n            while (fluidFilters.getSlots() > i && extracted.isEmpty()) {\n                FluidStack filterStack = FluidStack.EMPTY;\n\n                while (fluidFilters.getSlots() > i && filterStack.isEmpty()) {\n                    filterStack = fluidFilters.getFluid(i++);\n                }\n\n                if (!filterStack.isEmpty()) {\n                    extracted = network.extractFluid(filterStack, upgrades.getStackInteractCount(), compare, Action.PERFORM);\n                }\n            }\n        }\n\n        if (extracted.isEmpty()) {\n            moveDriveToOutput(slot);\n            return;\n        }\n\n        FluidStack remainder = storage.insert(extracted, extracted.getAmount(), Action.PERFORM);\n\n        network.insertFluid(remainder, remainder.getAmount(), Action.PERFORM);\n    }\n\n    private void moveDriveToOutput(int slot) {\n        ItemStack disk = inputDisks.getStackInSlot(slot);\n        if (!disk.isEmpty()) {\n            int i = 0;\n            while (i < 3 && !outputDisks.getStackInSlot(i).isEmpty()) {\n                i++;\n            }\n\n            if (i == 3) {\n                return;\n            }\n\n            inputDisks.extractItem(slot, 1, false);\n            outputDisks.insertItem(i, disk, false);\n        }\n    }\n\n    public DiskState[] getDiskState() {\n        DiskState[] diskStates = new DiskState[6];\n\n        for (int i = 0; i < 6; ++i) {\n            DiskState state = DiskState.NONE;\n\n            if (itemDisks[i] != null || fluidDisks[i] != null) {\n                if (!canUpdate()) {\n                    state = DiskState.DISCONNECTED;\n                } else {\n                    state = DiskState.get(\n                        itemDisks[i] != null ? itemDisks[i].getStored() : fluidDisks[i].getStored(),\n                        itemDisks[i] != null ? itemDisks[i].getCapacity() : fluidDisks[i].getCapacity()\n                    );\n                }\n            }\n\n            diskStates[i] = state;\n        }\n\n        return diskStates;\n    }\n\n    @Override\n    public int getCompare() {\n        return compare;\n    }\n\n    @Override\n    public void setCompare(int compare) {\n        this.compare = compare;\n    }\n\n    @Override\n    public int getType() {\n        return level.isClientSide ? DiskManipulatorBlockEntity.TYPE.getValue() : type;\n    }\n\n    @Override\n    public void setType(int type) {\n        this.type = type;\n    }\n\n    @Override\n    public IItemHandlerModifiable getItemFilters() {\n        return itemFilters;\n    }\n\n    @Override\n    public FluidInventory getFluidFilters() {\n        return fluidFilters;\n    }\n\n    @Override\n    public int getWhitelistBlacklistMode() {\n        return this.mode;\n    }\n\n    @Override\n    public void setWhitelistBlacklistMode(int mode) {\n        this.mode = mode;\n    }\n\n    public int getIoMode() {\n        return ioMode;\n    }\n\n    public void setIoMode(int ioMode) {\n        this.ioMode = ioMode;\n    }\n\n    public IItemHandler getInputDisks() {\n        return inputDisks;\n    }\n\n    public IItemHandler getOutputDisks() {\n        return outputDisks;\n    }\n\n    public ProxyItemHandler getDisks() {\n        return disks;\n    }\n\n    public IItemHandler getUpgrades() {\n        return upgrades;\n    }\n\n    @Override\n    public void read(CompoundTag tag) {\n        super.read(tag);\n\n        StackUtils.readItems(upgrades, 3, tag);\n        StackUtils.readItems(inputDisks, 4, tag);\n        StackUtils.readItems(outputDisks, 5, tag);\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return ID;\n    }\n\n    @Override\n    public CompoundTag write(CompoundTag tag) {\n        super.write(tag);\n\n        StackUtils.writeItems(upgrades, 3, tag);\n        StackUtils.writeItems(inputDisks, 4, tag);\n        StackUtils.writeItems(outputDisks, 5, tag);\n\n        return tag;\n    }\n\n    @Override\n    public CompoundTag writeConfiguration(CompoundTag tag) {\n        super.writeConfiguration(tag);\n\n        StackUtils.writeItems(itemFilters, 1, tag);\n\n        tag.put(NBT_FLUID_FILTERS, fluidFilters.writeToNbt());\n        tag.putInt(NBT_COMPARE, compare);\n        tag.putInt(NBT_MODE, mode);\n        tag.putInt(NBT_TYPE, type);\n        tag.putInt(NBT_IO_MODE, ioMode);\n\n        return tag;\n    }\n\n    @Override\n    public void readConfiguration(CompoundTag tag) {\n        super.readConfiguration(tag);\n\n        StackUtils.readItems(itemFilters, 1, tag);\n\n        if (tag.contains(NBT_FLUID_FILTERS)) {\n            fluidFilters.readFromNbt(tag.getCompound(NBT_FLUID_FILTERS));\n        }\n\n        if (tag.contains(NBT_COMPARE)) {\n            compare = tag.getInt(NBT_COMPARE);\n        }\n\n        if (tag.contains(NBT_MODE)) {\n            mode = tag.getInt(NBT_MODE);\n        }\n\n        if (tag.contains(NBT_TYPE)) {\n            type = tag.getInt(NBT_TYPE);\n        }\n\n        if (tag.contains(NBT_IO_MODE)) {\n            ioMode = tag.getInt(NBT_IO_MODE);\n        }\n    }\n\n    @Override\n    public IItemHandler getDrops() {\n        return new CombinedInvWrapper(inputDisks, outputDisks, upgrades);\n    }\n\n    @Override\n    public AccessType getAccessType() {\n        return AccessType.INSERT_EXTRACT;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/diskmanipulator/StorageDiskFluidManipulatorWrapper.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node.diskmanipulator;\n\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskListener;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.DiskState;\nimport com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.Collection;\nimport java.util.UUID;\n\npublic class StorageDiskFluidManipulatorWrapper implements IStorageDisk<FluidStack> {\n    private final DiskManipulatorNetworkNode diskManipulator;\n    private final IStorageDisk<FluidStack> parent;\n    private DiskState lastState;\n\n    public StorageDiskFluidManipulatorWrapper(DiskManipulatorNetworkNode diskManipulator, IStorageDisk<FluidStack> parent) {\n        this.diskManipulator = diskManipulator;\n        this.parent = parent;\n        this.setSettings(\n            () -> {\n                DiskState currentState = DiskState.get(getStored(), getCapacity());\n\n                if (lastState != currentState) {\n                    lastState = currentState;\n\n                    LevelUtils.updateBlock(diskManipulator.getLevel(), diskManipulator.getPos());\n                }\n            },\n            diskManipulator\n        );\n        this.lastState = DiskState.get(getStored(), getCapacity());\n    }\n\n    @Override\n    public int getCapacity() {\n        return parent.getCapacity();\n    }\n\n    @Nullable\n    @Override\n    public UUID getOwner() {\n        return parent.getOwner();\n    }\n\n    @Override\n    public void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context) {\n        parent.setSettings(listener, context);\n    }\n\n    @Override\n    public CompoundTag writeToNbt() {\n        return parent.writeToNbt();\n    }\n\n    @Override\n    public ResourceLocation getFactoryId() {\n        return parent.getFactoryId();\n    }\n\n    @Override\n    public Collection<FluidStack> getStacks() {\n        return parent.getStacks();\n    }\n\n    @Override\n    @Nonnull\n    public FluidStack insert(@Nonnull FluidStack stack, int size, Action action) {\n        if (stack.isEmpty()) {\n            return stack;\n        }\n\n        if (!IWhitelistBlacklist.acceptsFluid(diskManipulator.getFluidFilters(), diskManipulator.getWhitelistBlacklistMode(), diskManipulator.getCompare(), stack)) {\n            return StackUtils.copy(stack, size);\n        }\n\n        return parent.insert(stack, size, action);\n    }\n\n    @Override\n    @Nonnull\n    public FluidStack extract(@Nonnull FluidStack stack, int size, int flags, Action action) {\n        if (!IWhitelistBlacklist.acceptsFluid(diskManipulator.getFluidFilters(), diskManipulator.getWhitelistBlacklistMode(), diskManipulator.getCompare(), stack)) {\n            return FluidStack.EMPTY;\n        }\n\n        return parent.extract(stack, size, flags, action);\n    }\n\n    @Override\n    public int getStored() {\n        return parent.getStored();\n    }\n\n    @Override\n    public int getPriority() {\n        return parent.getPriority();\n    }\n\n    @Override\n    public AccessType getAccessType() {\n        return parent.getAccessType();\n    }\n\n    @Override\n    public int getCacheDelta(int storedPreInsertion, int size, @Nullable FluidStack remainder) {\n        return parent.getCacheDelta(storedPreInsertion, size, remainder);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/diskmanipulator/StorageDiskItemManipulatorWrapper.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node.diskmanipulator;\n\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskListener;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.DiskState;\nimport com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.Collection;\nimport java.util.UUID;\n\npublic class StorageDiskItemManipulatorWrapper implements IStorageDisk<ItemStack> {\n    private final DiskManipulatorNetworkNode diskManipulator;\n    private final IStorageDisk<ItemStack> parent;\n    private DiskState lastState;\n\n    public StorageDiskItemManipulatorWrapper(DiskManipulatorNetworkNode diskManipulator, IStorageDisk<ItemStack> parent) {\n        this.diskManipulator = diskManipulator;\n        this.parent = parent;\n        this.setSettings(\n            () -> {\n                DiskState currentState = DiskState.get(getStored(), getCapacity());\n\n                if (lastState != currentState) {\n                    lastState = currentState;\n\n                    LevelUtils.updateBlock(diskManipulator.getLevel(), diskManipulator.getPos());\n                }\n            },\n            diskManipulator\n        );\n        this.lastState = DiskState.get(getStored(), getCapacity());\n    }\n\n    @Override\n    public int getCapacity() {\n        return parent.getCapacity();\n    }\n\n    @Nullable\n    @Override\n    public UUID getOwner() {\n        return parent.getOwner();\n    }\n\n    @Override\n    public void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context) {\n        parent.setSettings(listener, context);\n    }\n\n    @Override\n    public CompoundTag writeToNbt() {\n        return parent.writeToNbt();\n    }\n\n    @Override\n    public Collection<ItemStack> getStacks() {\n        return parent.getStacks();\n    }\n\n    @Override\n    @Nonnull\n    public ItemStack insert(@Nonnull ItemStack stack, int size, Action action) {\n        if (stack.isEmpty()) {\n            return stack;\n        }\n\n        if (!IWhitelistBlacklist.acceptsItem(diskManipulator.getItemFilters(), diskManipulator.getWhitelistBlacklistMode(), diskManipulator.getCompare(), stack)) {\n            return ItemHandlerHelper.copyStackWithSize(stack, size);\n        }\n\n        return parent.insert(stack, size, action);\n    }\n\n    @Override\n    @Nonnull\n    public ItemStack extract(@Nonnull ItemStack stack, int size, int flags, Action action) {\n        if (!IWhitelistBlacklist.acceptsItem(diskManipulator.getItemFilters(), diskManipulator.getWhitelistBlacklistMode(), diskManipulator.getCompare(), stack)) {\n            return ItemStack.EMPTY;\n        }\n\n        return parent.extract(stack, size, flags, action);\n    }\n\n    @Override\n    public int getStored() {\n        return parent.getStored();\n    }\n\n    @Override\n    public int getPriority() {\n        return parent.getPriority();\n    }\n\n    @Override\n    public AccessType getAccessType() {\n        return parent.getAccessType();\n    }\n\n    @Override\n    public int getCacheDelta(int storedPreInsertion, int size, @Nullable ItemStack remainder) {\n        return parent.getCacheDelta(storedPreInsertion, size, remainder);\n    }\n\n    @Override\n    public ResourceLocation getFactoryId() {\n        return parent.getFactoryId();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/storage/FluidStorageNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node.storage;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.IStorage;\nimport com.refinedmods.refinedstorage.api.storage.IStorageProvider;\nimport com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.ConnectivityStateChangeCause;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.IStorageScreen;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.NetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType;\nimport com.refinedmods.refinedstorage.apiimpl.storage.cache.FluidStorageCache;\nimport com.refinedmods.refinedstorage.blockentity.FluidStorageBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IAccessType;\nimport com.refinedmods.refinedstorage.blockentity.config.IComparable;\nimport com.refinedmods.refinedstorage.blockentity.config.IPrioritizable;\nimport com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener;\nimport com.refinedmods.refinedstorage.util.AccessTypeUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.chat.Component;\n\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\n\nimport javax.annotation.Nullable;\nimport java.util.List;\nimport java.util.UUID;\n\npublic class FluidStorageNetworkNode extends NetworkNode implements IStorageScreen, IStorageProvider, IComparable, IWhitelistBlacklist, IPrioritizable, IAccessType, IStorageDiskContainerContext {\n    public static final ResourceLocation SIXTY_FOUR_K_FLUID_STORAGE_BLOCK_ID = new ResourceLocation(RS.ID, \"64k_fluid_storage_block\");\n    public static final ResourceLocation TWO_HUNDRED_FIFTY_SIX_K_FLUID_STORAGE_BLOCK_ID = new ResourceLocation(RS.ID, \"256k_fluid_storage_block\");\n    public static final ResourceLocation THOUSAND_TWENTY_FOUR_K_FLUID_STORAGE_BLOCK_ID = new ResourceLocation(RS.ID, \"1024k_fluid_storage_block\");\n    public static final ResourceLocation FOUR_THOUSAND_NINETY_SIX_K_FLUID_STORAGE_BLOCK_ID = new ResourceLocation(RS.ID, \"4096k_fluid_storage_block\");\n    public static final ResourceLocation CREATIVE_FLUID_STORAGE_BLOCK_ID = new ResourceLocation(RS.ID, \"creative_fluid_storage_block\");\n    public static final String NBT_ID = \"Id\";\n    private static final Logger LOGGER = LogManager.getLogger(FluidStorageNetworkNode.class);\n    private static final String NBT_PRIORITY = \"Priority\";\n    private static final String NBT_COMPARE = \"Compare\";\n    private static final String NBT_MODE = \"Mode\";\n    private static final String NBT_FILTERS = \"Filters\";\n    private final FluidInventory filters = new FluidInventory(9).addListener(new NetworkNodeFluidInventoryListener(this));\n\n    private final FluidStorageType type;\n\n    private AccessType accessType = AccessType.INSERT_EXTRACT;\n    private int priority = 0;\n    private int compare = IComparer.COMPARE_NBT;\n    private int mode = IWhitelistBlacklist.BLACKLIST;\n\n    private UUID storageId = UUID.randomUUID();\n    private IStorageDisk<FluidStack> storage;\n\n    public FluidStorageNetworkNode(Level level, BlockPos pos, FluidStorageType type) {\n        super(level, pos);\n\n        this.type = type;\n    }\n\n    public static ResourceLocation getId(FluidStorageType type) {\n        switch (type) {\n            case SIXTY_FOUR_K:\n                return SIXTY_FOUR_K_FLUID_STORAGE_BLOCK_ID;\n            case TWO_HUNDRED_FIFTY_SIX_K:\n                return TWO_HUNDRED_FIFTY_SIX_K_FLUID_STORAGE_BLOCK_ID;\n            case THOUSAND_TWENTY_FOUR_K:\n                return THOUSAND_TWENTY_FOUR_K_FLUID_STORAGE_BLOCK_ID;\n            case FOUR_THOUSAND_NINETY_SIX_K:\n                return FOUR_THOUSAND_NINETY_SIX_K_FLUID_STORAGE_BLOCK_ID;\n            case CREATIVE:\n                return CREATIVE_FLUID_STORAGE_BLOCK_ID;\n            default:\n                throw new IllegalArgumentException(\"Unknown storage type \" + type);\n        }\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        switch (type) {\n            case SIXTY_FOUR_K:\n                return RS.SERVER_CONFIG.getFluidStorageBlock().getSixtyFourKUsage();\n            case TWO_HUNDRED_FIFTY_SIX_K:\n                return RS.SERVER_CONFIG.getFluidStorageBlock().getTwoHundredFiftySixKUsage();\n            case THOUSAND_TWENTY_FOUR_K:\n                return RS.SERVER_CONFIG.getFluidStorageBlock().getThousandTwentyFourKUsage();\n            case FOUR_THOUSAND_NINETY_SIX_K:\n                return RS.SERVER_CONFIG.getFluidStorageBlock().getFourThousandNinetySixKUsage();\n            case CREATIVE:\n                return RS.SERVER_CONFIG.getFluidStorageBlock().getCreativeUsage();\n            default:\n                return 0;\n        }\n    }\n\n    @Override\n    public void onConnectedStateChange(INetwork network, boolean state, ConnectivityStateChangeCause cause) {\n        super.onConnectedStateChange(network, state, cause);\n\n        LOGGER.debug(\"Connectivity state of fluid storage block at {} changed to {} due to {}\", pos, state, cause);\n\n        network.getNodeGraph().runActionWhenPossible(FluidStorageCache.INVALIDATE_ACTION.apply(InvalidateCause.CONNECTED_STATE_CHANGED));\n    }\n\n    @Override\n    public void addItemStorages(List<IStorage<ItemStack>> storages) {\n        // NO OP\n    }\n\n    @Override\n    public void addFluidStorages(List<IStorage<FluidStack>> storages) {\n        if (storage == null) {\n            loadStorage(null);\n        }\n\n        storages.add(storage);\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return getId(type);\n    }\n\n    @Override\n    public CompoundTag write(CompoundTag tag) {\n        super.write(tag);\n\n        tag.putUUID(NBT_ID, storageId);\n\n        return tag;\n    }\n\n    @Override\n    public void read(CompoundTag tag) {\n        super.read(tag);\n\n        if (tag.hasUUID(NBT_ID)) {\n            storageId = tag.getUUID(NBT_ID);\n\n            loadStorage(null);\n        }\n    }\n\n    public void loadStorage(@Nullable Player owner) {\n        IStorageDisk disk = API.instance().getStorageDiskManager((ServerLevel) level).get(storageId);\n\n        if (disk == null) {\n            disk = API.instance().createDefaultFluidDisk((ServerLevel) level, type.getCapacity(), owner);\n\n            API.instance().getStorageDiskManager((ServerLevel) level).set(storageId, disk);\n            API.instance().getStorageDiskManager((ServerLevel) level).markForSaving();\n        }\n\n        this.storage = new FluidStorageWrapperStorageDisk(this, disk);\n    }\n\n    public UUID getStorageId() {\n        return storageId;\n    }\n\n    public void setStorageId(UUID id) {\n        this.storageId = id;\n\n        markDirty();\n    }\n\n    public IStorageDisk<FluidStack> getStorage() {\n        return storage;\n    }\n\n    @Override\n    public CompoundTag writeConfiguration(CompoundTag tag) {\n        super.writeConfiguration(tag);\n\n        tag.put(NBT_FILTERS, filters.writeToNbt());\n        tag.putInt(NBT_PRIORITY, priority);\n        tag.putInt(NBT_COMPARE, compare);\n        tag.putInt(NBT_MODE, mode);\n\n        AccessTypeUtils.writeAccessType(tag, accessType);\n\n        return tag;\n    }\n\n    @Override\n    public void readConfiguration(CompoundTag tag) {\n        super.readConfiguration(tag);\n\n        if (tag.contains(NBT_FILTERS)) {\n            filters.readFromNbt(tag.getCompound(NBT_FILTERS));\n        }\n\n        if (tag.contains(NBT_PRIORITY)) {\n            priority = tag.getInt(NBT_PRIORITY);\n        }\n\n        if (tag.contains(NBT_COMPARE)) {\n            compare = tag.getInt(NBT_COMPARE);\n        }\n\n        if (tag.contains(NBT_MODE)) {\n            mode = tag.getInt(NBT_MODE);\n        }\n\n        accessType = AccessTypeUtils.readAccessType(tag);\n    }\n\n    @Override\n    public int getCompare() {\n        return compare;\n    }\n\n    @Override\n    public void setCompare(int compare) {\n        this.compare = compare;\n\n        markDirty();\n    }\n\n    @Override\n    public int getWhitelistBlacklistMode() {\n        return mode;\n    }\n\n    @Override\n    public void setWhitelistBlacklistMode(int mode) {\n        this.mode = mode;\n\n        markDirty();\n    }\n\n    public FluidInventory getFilters() {\n        return filters;\n    }\n\n    @Override\n    public Component getTitle() {\n        return Component.translatable(\"block.refinedstorage.\" + type.getName() + \"_fluid_storage_block\");\n    }\n\n    @Override\n    public long getStored() {\n        return FluidStorageBlockEntity.STORED.getValue();\n    }\n\n    @Override\n    public long getCapacity() {\n        return type.getCapacity();\n    }\n\n    @Override\n    public AccessType getAccessType() {\n        return accessType;\n    }\n\n    @Override\n    public void setAccessType(AccessType value) {\n        this.accessType = value;\n\n        if (network != null) {\n            network.getFluidStorageCache().invalidate(InvalidateCause.DEVICE_CONFIGURATION_CHANGED);\n        }\n\n        markDirty();\n    }\n\n    @Override\n    public int getPriority() {\n        return priority;\n    }\n\n    @Override\n    public void setPriority(int priority) {\n        this.priority = priority;\n\n        markDirty();\n\n        if (network != null) {\n            network.getFluidStorageCache().sort();\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/storage/FluidStorageWrapperStorageDisk.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node.storage;\n\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskListener;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.Collection;\nimport java.util.UUID;\n\npublic class FluidStorageWrapperStorageDisk implements IStorageDisk<FluidStack> {\n    private final FluidStorageNetworkNode storage;\n    private final IStorageDisk<FluidStack> parent;\n\n    public FluidStorageWrapperStorageDisk(FluidStorageNetworkNode storage, IStorageDisk<FluidStack> parent) {\n        this.storage = storage;\n        this.parent = parent;\n        this.setSettings(null, storage);\n    }\n\n    @Override\n    public int getPriority() {\n        return storage.getPriority();\n    }\n\n    @Override\n    public AccessType getAccessType() {\n        return parent.getAccessType();\n    }\n\n    @Override\n    public Collection<FluidStack> getStacks() {\n        return parent.getStacks();\n    }\n\n    @Override\n    @Nonnull\n    public FluidStack insert(@Nonnull FluidStack stack, int size, Action action) {\n        if (!IWhitelistBlacklist.acceptsFluid(storage.getFilters(), storage.getWhitelistBlacklistMode(), storage.getCompare(), stack)) {\n            return StackUtils.copy(stack, size);\n        }\n\n        return parent.insert(stack, size, action);\n    }\n\n    @Override\n    @Nonnull\n    public FluidStack extract(@Nonnull FluidStack stack, int size, int flags, Action action) {\n        return parent.extract(stack, size, flags, action);\n    }\n\n    @Override\n    public int getStored() {\n        return parent.getStored();\n    }\n\n    @Override\n    public int getCacheDelta(int storedPreInsertion, int size, @Nullable FluidStack remainder) {\n        return parent.getCacheDelta(storedPreInsertion, size, remainder);\n    }\n\n    @Override\n    public int getCapacity() {\n        return parent.getCapacity();\n    }\n\n    @Nullable\n    @Override\n    public UUID getOwner() {\n        return parent.getOwner();\n    }\n\n    @Override\n    public void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context) {\n        parent.setSettings(listener, context);\n    }\n\n    @Override\n    public CompoundTag writeToNbt() {\n        return parent.writeToNbt();\n    }\n\n    @Override\n    public ResourceLocation getFactoryId() {\n        return parent.getFactoryId();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/storage/ItemStorageWrapperStorageDisk.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node.storage;\n\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskListener;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.Collection;\nimport java.util.UUID;\n\npublic class ItemStorageWrapperStorageDisk implements IStorageDisk<ItemStack> {\n    private final StorageNetworkNode storage;\n    private final IStorageDisk<ItemStack> parent;\n\n    public ItemStorageWrapperStorageDisk(StorageNetworkNode storage, IStorageDisk<ItemStack> parent) {\n        this.storage = storage;\n        this.parent = parent;\n        this.setSettings(null, storage);\n    }\n\n    @Override\n    public int getPriority() {\n        return storage.getPriority();\n    }\n\n    @Override\n    public AccessType getAccessType() {\n        return parent.getAccessType();\n    }\n\n    @Override\n    public Collection<ItemStack> getStacks() {\n        return parent.getStacks();\n    }\n\n    @Override\n    @Nonnull\n    public ItemStack insert(@Nonnull ItemStack stack, int size, Action action) {\n        if (!IWhitelistBlacklist.acceptsItem(storage.getFilters(), storage.getWhitelistBlacklistMode(), storage.getCompare(), stack)) {\n            return ItemHandlerHelper.copyStackWithSize(stack, size);\n        }\n\n        return parent.insert(stack, size, action);\n    }\n\n    @Override\n    @Nonnull\n    public ItemStack extract(@Nonnull ItemStack stack, int size, int flags, Action action) {\n        return parent.extract(stack, size, flags, action);\n    }\n\n    @Override\n    public int getStored() {\n        return parent.getStored();\n    }\n\n    @Override\n    public int getCacheDelta(int storedPreInsertion, int size, @Nullable ItemStack remainder) {\n        return parent.getCacheDelta(storedPreInsertion, size, remainder);\n    }\n\n    @Override\n    public int getCapacity() {\n        return parent.getCapacity();\n    }\n\n    @Nullable\n    @Override\n    public UUID getOwner() {\n        return parent.getOwner();\n    }\n\n    @Override\n    public void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context) {\n        parent.setSettings(listener, context);\n    }\n\n    @Override\n    public CompoundTag writeToNbt() {\n        return parent.writeToNbt();\n    }\n\n    @Override\n    public ResourceLocation getFactoryId() {\n        return parent.getFactoryId();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/storage/StorageNetworkNode.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.node.storage;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.IStorage;\nimport com.refinedmods.refinedstorage.api.storage.IStorageProvider;\nimport com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.ConnectivityStateChangeCause;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.IStorageScreen;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.NetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType;\nimport com.refinedmods.refinedstorage.apiimpl.storage.cache.ItemStorageCache;\nimport com.refinedmods.refinedstorage.blockentity.StorageBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IAccessType;\nimport com.refinedmods.refinedstorage.blockentity.config.IComparable;\nimport com.refinedmods.refinedstorage.blockentity.config.IPrioritizable;\nimport com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener;\nimport com.refinedmods.refinedstorage.util.AccessTypeUtils;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.chat.Component;\n\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\n\nimport javax.annotation.Nullable;\nimport java.util.List;\nimport java.util.UUID;\n\npublic class StorageNetworkNode extends NetworkNode implements IStorageScreen, IStorageProvider, IComparable, IWhitelistBlacklist, IPrioritizable, IAccessType, IStorageDiskContainerContext {\n    public static final ResourceLocation ONE_K_STORAGE_BLOCK_ID = new ResourceLocation(RS.ID, \"1k_storage_block\");\n    public static final ResourceLocation FOUR_K_STORAGE_BLOCK_ID = new ResourceLocation(RS.ID, \"4k_storage_block\");\n    public static final ResourceLocation SIXTEEN_K_STORAGE_BLOCK_ID = new ResourceLocation(RS.ID, \"16k_storage_block\");\n    public static final ResourceLocation SIXTY_FOUR_K_STORAGE_BLOCK_ID = new ResourceLocation(RS.ID, \"64k_storage_block\");\n    public static final ResourceLocation CREATIVE_STORAGE_BLOCK_ID = new ResourceLocation(RS.ID, \"creative_storage_block\");\n    public static final String NBT_ID = \"Id\";\n    private static final Logger LOGGER = LogManager.getLogger(StorageNetworkNode.class);\n    private static final String NBT_PRIORITY = \"Priority\";\n    private static final String NBT_COMPARE = \"Compare\";\n    private static final String NBT_MODE = \"Mode\";\n    private final BaseItemHandler filters = new BaseItemHandler(9).addListener(new NetworkNodeInventoryListener(this));\n\n    private final ItemStorageType type;\n\n    private AccessType accessType = AccessType.INSERT_EXTRACT;\n    private int priority = 0;\n    private int compare = IComparer.COMPARE_NBT;\n    private int mode = IWhitelistBlacklist.BLACKLIST;\n\n    private UUID storageId = UUID.randomUUID();\n    private IStorageDisk<ItemStack> storage;\n\n    public StorageNetworkNode(Level level, BlockPos pos, ItemStorageType type) {\n        super(level, pos);\n\n        this.type = type;\n    }\n\n    public static ResourceLocation getId(ItemStorageType type) {\n        switch (type) {\n            case ONE_K:\n                return ONE_K_STORAGE_BLOCK_ID;\n            case FOUR_K:\n                return FOUR_K_STORAGE_BLOCK_ID;\n            case SIXTEEN_K:\n                return SIXTEEN_K_STORAGE_BLOCK_ID;\n            case SIXTY_FOUR_K:\n                return SIXTY_FOUR_K_STORAGE_BLOCK_ID;\n            case CREATIVE:\n                return CREATIVE_STORAGE_BLOCK_ID;\n            default:\n                throw new IllegalArgumentException(\"Unknown storage type \" + type);\n        }\n    }\n\n    @Override\n    public int getEnergyUsage() {\n        switch (type) {\n            case ONE_K:\n                return RS.SERVER_CONFIG.getStorageBlock().getOneKUsage();\n            case FOUR_K:\n                return RS.SERVER_CONFIG.getStorageBlock().getFourKUsage();\n            case SIXTEEN_K:\n                return RS.SERVER_CONFIG.getStorageBlock().getSixteenKUsage();\n            case SIXTY_FOUR_K:\n                return RS.SERVER_CONFIG.getStorageBlock().getSixtyFourKUsage();\n            case CREATIVE:\n                return RS.SERVER_CONFIG.getStorageBlock().getCreativeUsage();\n            default:\n                return 0;\n        }\n    }\n\n    @Override\n    public void onConnectedStateChange(INetwork network, boolean state, ConnectivityStateChangeCause cause) {\n        super.onConnectedStateChange(network, state, cause);\n\n        LOGGER.debug(\"Connectivity state of item storage block at {} changed to {} due to {}\", pos, state, cause);\n\n        network.getNodeGraph().runActionWhenPossible(ItemStorageCache.INVALIDATE_ACTION.apply(InvalidateCause.CONNECTED_STATE_CHANGED));\n    }\n\n    @Override\n    public void addItemStorages(List<IStorage<ItemStack>> storages) {\n        if (storage == null) {\n            loadStorage(null);\n        }\n\n        storages.add(storage);\n    }\n\n    @Override\n    public void addFluidStorages(List<IStorage<FluidStack>> storages) {\n        // NO OP\n    }\n\n    @Override\n    public ResourceLocation getId() {\n        return getId(type);\n    }\n\n    @Override\n    public CompoundTag write(CompoundTag tag) {\n        super.write(tag);\n\n        tag.putUUID(NBT_ID, storageId);\n\n        return tag;\n    }\n\n    @Override\n    public void read(CompoundTag tag) {\n        super.read(tag);\n\n        if (tag.hasUUID(NBT_ID)) {\n            storageId = tag.getUUID(NBT_ID);\n\n            loadStorage(null);\n        }\n    }\n\n    public void loadStorage(@Nullable Player owner) {\n        IStorageDisk disk = API.instance().getStorageDiskManager((ServerLevel) level).get(storageId);\n\n        if (disk == null) {\n            disk = API.instance().createDefaultItemDisk((ServerLevel) level, type.getCapacity(), owner);\n\n            API.instance().getStorageDiskManager((ServerLevel) level).set(storageId, disk);\n            API.instance().getStorageDiskManager((ServerLevel) level).markForSaving();\n        }\n\n        this.storage = new ItemStorageWrapperStorageDisk(this, disk);\n    }\n\n    public UUID getStorageId() {\n        return storageId;\n    }\n\n    public void setStorageId(UUID id) {\n        this.storageId = id;\n\n        markDirty();\n    }\n\n    public IStorageDisk<ItemStack> getStorage() {\n        return storage;\n    }\n\n    @Override\n    public CompoundTag writeConfiguration(CompoundTag tag) {\n        super.writeConfiguration(tag);\n\n        StackUtils.writeItems(filters, 0, tag);\n\n        tag.putInt(NBT_PRIORITY, priority);\n        tag.putInt(NBT_COMPARE, compare);\n        tag.putInt(NBT_MODE, mode);\n\n        AccessTypeUtils.writeAccessType(tag, accessType);\n\n        return tag;\n    }\n\n    @Override\n    public void readConfiguration(CompoundTag tag) {\n        super.readConfiguration(tag);\n\n        StackUtils.readItems(filters, 0, tag);\n\n        if (tag.contains(NBT_PRIORITY)) {\n            priority = tag.getInt(NBT_PRIORITY);\n        }\n\n        if (tag.contains(NBT_COMPARE)) {\n            compare = tag.getInt(NBT_COMPARE);\n        }\n\n        if (tag.contains(NBT_MODE)) {\n            mode = tag.getInt(NBT_MODE);\n        }\n\n        accessType = AccessTypeUtils.readAccessType(tag);\n    }\n\n    @Override\n    public int getCompare() {\n        return compare;\n    }\n\n    @Override\n    public void setCompare(int compare) {\n        this.compare = compare;\n\n        markDirty();\n    }\n\n    @Override\n    public int getWhitelistBlacklistMode() {\n        return mode;\n    }\n\n    @Override\n    public void setWhitelistBlacklistMode(int mode) {\n        this.mode = mode;\n\n        markDirty();\n    }\n\n    public BaseItemHandler getFilters() {\n        return filters;\n    }\n\n    @Override\n    public Component getTitle() {\n        return Component.translatable(\"block.refinedstorage.\" + type.getName() + \"_storage_block\");\n    }\n\n    @Override\n    public long getStored() {\n        return StorageBlockEntity.STORED.getValue();\n    }\n\n    @Override\n    public long getCapacity() {\n        return type.getCapacity();\n    }\n\n    @Override\n    public AccessType getAccessType() {\n        return accessType;\n    }\n\n    @Override\n    public void setAccessType(AccessType value) {\n        this.accessType = value;\n\n        if (network != null) {\n            network.getItemStorageCache().invalidate(InvalidateCause.DEVICE_CONFIGURATION_CHANGED);\n        }\n\n        markDirty();\n    }\n\n    @Override\n    public int getPriority() {\n        return priority;\n    }\n\n    @Override\n    public void setPriority(int priority) {\n        this.priority = priority;\n\n        markDirty();\n\n        if (network != null) {\n            network.getItemStorageCache().sort();\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/security/SecurityCard.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.security;\n\nimport com.refinedmods.refinedstorage.api.network.security.ISecurityCard;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\n\nimport javax.annotation.Nullable;\nimport java.util.EnumMap;\nimport java.util.Map;\nimport java.util.UUID;\n\npublic class SecurityCard implements ISecurityCard {\n    private final UUID owner;\n    private final Map<Permission, Boolean> permissions = new EnumMap<>(Permission.class);\n\n    public SecurityCard(@Nullable UUID owner) {\n        this.owner = owner;\n    }\n\n    public Map<Permission, Boolean> getPermissions() {\n        return permissions;\n    }\n\n    @Override\n    @Nullable\n    public UUID getOwner() {\n        return owner;\n    }\n\n    @Override\n    public boolean hasPermission(Permission permission) {\n        return permissions.get(permission);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/network/security/SecurityManager.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.network.security;\n\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.INetworkNodeGraphEntry;\nimport com.refinedmods.refinedstorage.api.network.security.ISecurityCard;\nimport com.refinedmods.refinedstorage.api.network.security.ISecurityCardContainer;\nimport com.refinedmods.refinedstorage.api.network.security.ISecurityManager;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport net.minecraft.server.players.ServerOpList;\nimport net.minecraft.world.entity.player.Player;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.UUID;\n\npublic class SecurityManager implements ISecurityManager {\n    private final INetwork network;\n    private final Map<UUID, ISecurityCard> cards = new HashMap<>();\n    private ISecurityCard globalCard;\n\n    public SecurityManager(INetwork network) {\n        this.network = network;\n    }\n\n    @Override\n    public boolean hasPermission(Permission permission, Player player) {\n        ServerOpList ops = player.getServer().getPlayerList().getOps();\n\n        if (ops.get(player.getGameProfile()) != null) {\n            return true;\n        }\n\n        UUID uuid = player.getGameProfile().getId();\n\n        if (!cards.containsKey(uuid)) {\n            if (globalCard != null) {\n                return globalCard.hasPermission(permission);\n            }\n\n            return true;\n        }\n\n        return cards.get(uuid).hasPermission(permission);\n    }\n\n    @Override\n    public void invalidate() {\n        this.cards.clear();\n        this.globalCard = null;\n\n        for (INetworkNodeGraphEntry entry : network.getNodeGraph().all()) {\n            if (entry.getNode() instanceof ISecurityCardContainer && entry.getNode().isActive()) {\n                ISecurityCardContainer container = (ISecurityCardContainer) entry.getNode();\n\n                for (ISecurityCard card : container.getCards()) {\n                    if (card.getOwner() == null) {\n                        throw new IllegalStateException(\"Owner in #getCards() cannot be null!\");\n                    }\n\n                    this.cards.put(card.getOwner(), card);\n                }\n\n                if (container.getGlobalCard() != null) {\n                    this.globalCard = container.getGlobalCard();\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/render/CraftingMonitorElementDrawers.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.render;\n\nimport com.mojang.blaze3d.systems.RenderSystem;\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.render.IElementDrawer;\nimport com.refinedmods.refinedstorage.container.CraftingMonitorContainerMenu;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport net.minecraft.resources.ResourceLocation;\n\npublic class CraftingMonitorElementDrawers extends ElementDrawers<CraftingMonitorContainerMenu> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/crafting_preview.png\");\n\n    private final IElementDrawer<Integer> overlayDrawer;\n    private final IElementDrawer<Void> errorDrawer;\n\n    public CraftingMonitorElementDrawers(BaseScreen<CraftingMonitorContainerMenu> screen, int itemWidth, int itemHeight) {\n        super(screen);\n\n        this.overlayDrawer = (graphics, x, y, color) -> {\n            RenderSystem.setShaderColor(1, 1, 1, 1);\n            graphics.fill(x, y, x + itemWidth, y + itemHeight, color);\n        };\n\n        this.errorDrawer = (graphics, x, y, nothing) -> {\n            RenderSystem.setShaderColor(1, 1, 1, 1);\n            graphics.blit(TEXTURE, x + itemWidth - 12 - 2, y + itemHeight - 12 - 2, 0, 244, 12, 12);\n        };\n    }\n\n    @Override\n    public IElementDrawer<Integer> getOverlayDrawer() {\n        return overlayDrawer;\n    }\n\n    @Override\n    public IElementDrawer<Void> getErrorDrawer() {\n        return errorDrawer;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/render/CraftingPreviewElementDrawers.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.render;\n\nimport com.mojang.blaze3d.systems.RenderSystem;\nimport com.refinedmods.refinedstorage.api.render.IElementDrawer;\nimport com.refinedmods.refinedstorage.screen.grid.CraftingPreviewScreen;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\n\npublic class CraftingPreviewElementDrawers extends ElementDrawers<AbstractContainerMenu> {\n    private final IElementDrawer<Integer> overlayDrawer = (graphics, x, y, color) -> {\n        RenderSystem.setShaderColor(1, 1, 1, 1);\n        graphics.fill(x, y, x + 73, y + 29, color);\n    };\n\n    public CraftingPreviewElementDrawers(CraftingPreviewScreen screen) {\n        super(screen);\n    }\n\n    @Override\n    public IElementDrawer<Integer> getOverlayDrawer() {\n        return overlayDrawer;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/render/ElementDrawers.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.render;\n\nimport com.refinedmods.refinedstorage.api.render.IElementDrawer;\nimport com.refinedmods.refinedstorage.api.render.IElementDrawers;\nimport com.refinedmods.refinedstorage.render.FluidRenderer;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\n\npublic class ElementDrawers<T extends AbstractContainerMenu> implements IElementDrawers {\n    protected final BaseScreen<T> screen;\n\n    public ElementDrawers(BaseScreen<T> screen) {\n        this.screen = screen;\n    }\n\n    @Override\n    public IElementDrawer<ItemStack> getItemDrawer() {\n        return screen::renderItem;\n    }\n\n    @Override\n    public IElementDrawer<FluidStack> getFluidDrawer() {\n        return FluidRenderer.INSTANCE::render;\n    }\n\n    @Override\n    public IElementDrawer<String> getStringDrawer() {\n        return screen::renderString;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/FluidStorageType.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage;\n\npublic enum FluidStorageType {\n    SIXTY_FOUR_K(\"64k\", 64_000),\n    TWO_HUNDRED_FIFTY_SIX_K(\"256k\", 256_000),\n    THOUSAND_TWENTY_FOUR_K(\"1024k\", 1024_000),\n    FOUR_THOUSAND_NINETY_SIX_K(\"4096k\", 4096_000),\n    CREATIVE(\"creative\", -1);\n\n    private final String name;\n    private final int capacity;\n\n    FluidStorageType(String name, int capacity) {\n        this.name = name;\n        this.capacity = capacity;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public int getCapacity() {\n        return capacity;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/ItemStorageType.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage;\n\npublic enum ItemStorageType {\n    ONE_K(\"1k\", 1000),\n    FOUR_K(\"4k\", 4000),\n    SIXTEEN_K(\"16k\", 16_000),\n    SIXTY_FOUR_K(\"64k\", 64_000),\n    CREATIVE(\"creative\", -1);\n\n    private final String name;\n    private final int capacity;\n\n    ItemStorageType(String name, int capacity) {\n        this.name = name;\n        this.capacity = capacity;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public int getCapacity() {\n        return capacity;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/cache/FluidStorageCache.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.cache;\n\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.INetworkNodeGraphEntry;\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.IStorage;\nimport com.refinedmods.refinedstorage.api.storage.IStorageProvider;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener;\nimport com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.api.util.StackListEntry;\nimport com.refinedmods.refinedstorage.api.util.StackListResult;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.screen.grid.stack.FluidGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack;\n\nimport net.minecraft.world.item.ItemStack;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\n\nimport javax.annotation.Nonnull;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport java.util.ArrayList;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.function.Consumer;\nimport java.util.function.Function;\n\npublic class FluidStorageCache implements IStorageCache<FluidStack> {\n    public static final Function<InvalidateCause, Consumer<INetwork>> INVALIDATE_ACTION = cause -> invalidatedNetwork -> invalidatedNetwork.getFluidStorageCache().invalidate(cause);\n\n    private static final Logger LOGGER = LogManager.getLogger(FluidStorageCache.class);\n\n    private final INetwork network;\n    private final CopyOnWriteArrayList<IStorage<FluidStack>> storages = new CopyOnWriteArrayList<>();\n    private final IStackList<FluidStack> list = API.instance().createFluidStackList();\n    private final IStackList<FluidStack> craftables = API.instance().createFluidStackList();\n    private final List<IStorageCacheListener<FluidStack>> listeners = new LinkedList<>();\n    private final List<StackListResult<FluidStack>> batchedChanges = new ArrayList<>();\n\n    public FluidStorageCache(INetwork network) {\n        this.network = network;\n    }\n\n    @Override\n    public void invalidate(InvalidateCause cause) {\n        LOGGER.debug(\"Invalidating fluid storage cache of network at position {} due to {}\", network.getPosition(), cause);\n\n        storages.clear();\n\n        network.getNodeGraph()\n            .all()\n            .stream()\n            .map(INetworkNodeGraphEntry::getNode)\n            .filter(node -> node.isActive() && node instanceof IStorageProvider)\n            .forEach(node -> ((IStorageProvider) node).addFluidStorages(storages));\n\n        list.clear();\n\n        sort();\n\n        for (IStorage<FluidStack> storage : storages) {\n            if (storage.getAccessType() == AccessType.INSERT) {\n                continue;\n            }\n\n            for (FluidStack stack : storage.getStacks()) {\n                if (!stack.isEmpty()) {\n                    add(stack, stack.getAmount(), true, false);\n                }\n            }\n        }\n\n        listeners.forEach(IStorageCacheListener::onInvalidated);\n    }\n\n    @Override\n    public void add(@Nonnull FluidStack stack, int size, boolean rebuilding, boolean batched) {\n        StackListResult<FluidStack> result = list.add(stack, size);\n\n        if (!rebuilding) {\n            if (!batched) {\n                listeners.forEach(l -> l.onChanged(result));\n            } else {\n                batchedChanges.add(result);\n            }\n        }\n    }\n\n    @Override\n    public void remove(@Nonnull FluidStack stack, int size, boolean batched) {\n        StackListResult<FluidStack> result = list.remove(stack, size);\n\n        if (result != null) {\n            if (!batched) {\n                listeners.forEach(l -> l.onChanged(result));\n            } else {\n                batchedChanges.add(result);\n            }\n        }\n    }\n\n    @Override\n    public void flush() {\n        if (!batchedChanges.isEmpty()) {\n            if (batchedChanges.size() > 1) {\n                listeners.forEach(l -> l.onChangedBulk(batchedChanges));\n            } else {\n                batchedChanges.forEach(change -> listeners.forEach(l -> l.onChanged(change)));\n            }\n\n            batchedChanges.clear();\n        }\n    }\n\n    @Override\n    public void addListener(IStorageCacheListener<FluidStack> listener) {\n        listeners.add(listener);\n\n        listener.onAttached();\n    }\n\n    @Override\n    public void removeListener(IStorageCacheListener<FluidStack> listener) {\n        listeners.remove(listener);\n    }\n\n    @Override\n    public void reAttachListeners() {\n        listeners.forEach(IStorageCacheListener::onAttached);\n    }\n\n    @Override\n    public void sort() {\n        storages.sort(IStorage.COMPARATOR);\n    }\n\n    @Override\n    public IStackList<FluidStack> getList() {\n        return list;\n    }\n\n    @Override\n    public IStackList<FluidStack> getCraftablesList() {\n        return craftables;\n    }\n\n    @Override\n    public List<? extends IGridStack> getGridStacks() {\n        final List<FluidGridStack> stacks = new ArrayList<>();\n\n        for (StackListEntry<FluidStack> stack : network.getFluidStorageCache().getList().getStacks()) {\n            stacks.add(FluidGridStack.of(\n                stack,\n                network.getFluidStorageTracker(),\n                network.getFluidStorageCache().getCraftablesList(),\n                false\n            ));\n        }\n\n        for (StackListEntry<FluidStack> stack : network.getFluidStorageCache().getCraftablesList().getStacks()) {\n            stacks.add(FluidGridStack.of(\n                stack,\n                network.getFluidStorageTracker(),\n                network.getFluidStorageCache().getList(),\n                true\n            ));\n        }\n\n        return stacks;\n    }\n\n    @Override\n    public List<IStorage<FluidStack>> getStorages() {\n        return storages;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/cache/ItemStorageCache.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.cache;\n\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.INetworkNodeGraphEntry;\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.IStorage;\nimport com.refinedmods.refinedstorage.api.storage.IStorageProvider;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener;\nimport com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.api.util.StackListEntry;\nimport com.refinedmods.refinedstorage.api.util.StackListResult;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack;\n\nimport net.minecraft.world.item.ItemStack;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\n\nimport javax.annotation.Nonnull;\nimport java.util.ArrayList;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.function.Consumer;\nimport java.util.function.Function;\n\npublic class ItemStorageCache implements IStorageCache<ItemStack> {\n    public static final Function<InvalidateCause, Consumer<INetwork>> INVALIDATE_ACTION = cause -> invalidatedNetwork -> invalidatedNetwork.getItemStorageCache().invalidate(cause);\n\n    private static final Logger LOGGER = LogManager.getLogger(ItemStorageCache.class);\n\n    private final INetwork network;\n    private final CopyOnWriteArrayList<IStorage<ItemStack>> storages = new CopyOnWriteArrayList<>();\n    private final IStackList<ItemStack> list = API.instance().createItemStackList();\n    private final IStackList<ItemStack> craftables = API.instance().createItemStackList();\n    private final List<IStorageCacheListener<ItemStack>> listeners = new LinkedList<>();\n    private final List<StackListResult<ItemStack>> batchedChanges = new ArrayList<>();\n\n    public ItemStorageCache(INetwork network) {\n        this.network = network;\n    }\n\n    @Override\n    public void invalidate(InvalidateCause cause) {\n        LOGGER.debug(\"Invalidating item storage cache of network at position {} due to {}\", network.getPosition(), cause);\n\n        storages.clear();\n\n        network.getNodeGraph()\n            .all()\n            .stream()\n            .map(INetworkNodeGraphEntry::getNode)\n            .filter(node -> node.isActive() && node instanceof IStorageProvider)\n            .forEach(node -> ((IStorageProvider) node).addItemStorages(storages));\n\n        list.clear();\n\n        sort();\n\n        for (IStorage<ItemStack> storage : storages) {\n            if (storage.getAccessType() == AccessType.INSERT) {\n                continue;\n            }\n\n            for (ItemStack stack : storage.getStacks()) {\n                if (!stack.isEmpty()) {\n                    add(stack, stack.getCount(), true, false);\n                }\n            }\n        }\n\n        listeners.forEach(IStorageCacheListener::onInvalidated);\n    }\n\n    @Override\n    public void add(@Nonnull ItemStack stack, int size, boolean rebuilding, boolean batched) {\n        StackListResult<ItemStack> result = list.add(stack, size);\n\n        if (!rebuilding) {\n            if (!batched) {\n                listeners.forEach(l -> l.onChanged(result));\n            } else {\n                batchedChanges.add(result);\n            }\n        }\n    }\n\n    @Override\n    public void remove(@Nonnull ItemStack stack, int size, boolean batched) {\n        StackListResult<ItemStack> result = list.remove(stack, size);\n\n        if (result != null) {\n            if (!batched) {\n                listeners.forEach(l -> l.onChanged(result));\n            } else {\n                batchedChanges.add(result);\n            }\n        }\n    }\n\n    @Override\n    public void flush() {\n        if (!batchedChanges.isEmpty()) {\n            if (batchedChanges.size() > 1) {\n                listeners.forEach(l -> l.onChangedBulk(batchedChanges));\n            } else {\n                batchedChanges.forEach(change -> listeners.forEach(l -> l.onChanged(change)));\n            }\n\n            batchedChanges.clear();\n        }\n    }\n\n    @Override\n    public void addListener(IStorageCacheListener<ItemStack> listener) {\n        listeners.add(listener);\n\n        listener.onAttached();\n    }\n\n    @Override\n    public void removeListener(IStorageCacheListener<ItemStack> listener) {\n        listeners.remove(listener);\n    }\n\n    @Override\n    public void reAttachListeners() {\n        listeners.forEach(IStorageCacheListener::onAttached);\n    }\n\n    @Override\n    public void sort() {\n        storages.sort(IStorage.COMPARATOR);\n    }\n\n    @Override\n    public IStackList<ItemStack> getList() {\n        return list;\n    }\n\n    @Override\n    public IStackList<ItemStack> getCraftablesList() {\n        return craftables;\n    }\n\n    @Override\n    public List<? extends IGridStack> getGridStacks() {\n        final List<ItemGridStack> stacks = new ArrayList<>();\n\n        for (StackListEntry<ItemStack> stack : network.getItemStorageCache().getList().getStacks()) {\n            stacks.add(ItemGridStack.of(\n                stack,\n                network.getItemStorageTracker(),\n                network.getItemStorageCache().getCraftablesList(),\n                false\n            ));\n        }\n\n        for (StackListEntry<ItemStack> stack : network.getItemStorageCache().getCraftablesList().getStacks()) {\n            stacks.add(ItemGridStack.of(\n                stack,\n                network.getItemStorageTracker(),\n                network.getItemStorageCache().getList(),\n                true\n            ));\n        }\n\n        return stacks;\n    }\n\n    @Override\n    public List<IStorage<ItemStack>> getStorages() {\n        return storages;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/cache/PortableFluidStorageCache.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.cache;\n\nimport com.refinedmods.refinedstorage.api.storage.IStorage;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener;\nimport com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.api.util.StackListResult;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.blockentity.grid.portable.IPortableGrid;\nimport com.refinedmods.refinedstorage.screen.grid.stack.FluidGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack;\n\nimport javax.annotation.Nonnull;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.List;\n\npublic class PortableFluidStorageCache implements IStorageCache<FluidStack> {\n    private final IPortableGrid portableGrid;\n    private final IStackList<FluidStack> list = API.instance().createFluidStackList();\n    private final List<IStorageCacheListener<FluidStack>> listeners = new LinkedList<>();\n\n    public PortableFluidStorageCache(IPortableGrid portableGrid) {\n        this.portableGrid = portableGrid;\n    }\n\n    @Override\n    public void invalidate(InvalidateCause cause) {\n        list.clear();\n\n        if (portableGrid.getFluidStorage() != null) {\n            portableGrid.getFluidStorage().getStacks().forEach(list::add);\n        }\n\n        listeners.forEach(IStorageCacheListener::onInvalidated);\n    }\n\n    @Override\n    public void add(@Nonnull FluidStack stack, int size, boolean rebuilding, boolean batched) {\n        StackListResult<FluidStack> result = list.add(stack, size);\n\n        if (!rebuilding) {\n            listeners.forEach(l -> l.onChanged(result));\n        }\n    }\n\n    @Override\n    public void remove(@Nonnull FluidStack stack, int size, boolean batched) {\n        StackListResult<FluidStack> result = list.remove(stack, size);\n\n        if (result != null) {\n            listeners.forEach(l -> l.onChanged(result));\n        }\n    }\n\n    @Override\n    public void flush() {\n        throw new UnsupportedOperationException(\"Cannot flush portable grid storage cache\");\n    }\n\n    @Override\n    public void addListener(IStorageCacheListener<FluidStack> listener) {\n        listeners.add(listener);\n\n        listener.onAttached();\n    }\n\n    @Override\n    public void removeListener(IStorageCacheListener<FluidStack> listener) {\n        listeners.remove(listener);\n    }\n\n    @Override\n    public void reAttachListeners() {\n        listeners.forEach(IStorageCacheListener::onAttached);\n    }\n\n    @Override\n    public void sort() {\n        // NO OP\n    }\n\n    @Override\n    public IStackList<FluidStack> getList() {\n        return list;\n    }\n\n    @Override\n    public IStackList<FluidStack> getCraftablesList() {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public List<? extends IGridStack> getGridStacks() {\n        return portableGrid.getFluidCache().getList().getStacks()\n            .stream()\n            .map(stack -> FluidGridStack.of(stack, portableGrid.getFluidStorageTracker(), null, false))\n            .toList();\n    }\n\n    @Override\n    public List<IStorage<FluidStack>> getStorages() {\n        return Collections.emptyList();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/cache/PortableItemStorageCache.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.cache;\n\nimport com.refinedmods.refinedstorage.api.storage.IStorage;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener;\nimport com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.api.util.StackListResult;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.blockentity.grid.portable.IPortableGrid;\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack;\n\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.world.item.ItemStack;\n\npublic class PortableItemStorageCache implements IStorageCache<ItemStack> {\n    private final IPortableGrid portableGrid;\n    private final IStackList<ItemStack> list = API.instance().createItemStackList();\n    private final List<IStorageCacheListener<ItemStack>> listeners = new LinkedList<>();\n\n    public PortableItemStorageCache(IPortableGrid portableGrid) {\n        this.portableGrid = portableGrid;\n    }\n\n    @Override\n    public void invalidate(InvalidateCause cause) {\n        list.clear();\n\n        if (portableGrid.getItemStorage() != null) {\n            portableGrid.getItemStorage().getStacks().forEach(list::add);\n        }\n\n        listeners.forEach(IStorageCacheListener::onInvalidated);\n    }\n\n    @Override\n    public void add(@Nonnull ItemStack stack, int size, boolean rebuilding, boolean batched) {\n        StackListResult<ItemStack> result = list.add(stack, size);\n\n        if (!rebuilding) {\n            listeners.forEach(l -> l.onChanged(result));\n        }\n    }\n\n    @Override\n    public void remove(@Nonnull ItemStack stack, int size, boolean batched) {\n        StackListResult<ItemStack> result = list.remove(stack, size);\n\n        if (result != null) {\n            listeners.forEach(l -> l.onChanged(result));\n        }\n    }\n\n    @Override\n    public void flush() {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public void addListener(IStorageCacheListener<ItemStack> listener) {\n        listeners.add(listener);\n\n        listener.onAttached();\n    }\n\n    @Override\n    public void removeListener(IStorageCacheListener<ItemStack> listener) {\n        listeners.remove(listener);\n    }\n\n    @Override\n    public void reAttachListeners() {\n        listeners.forEach(IStorageCacheListener::onAttached);\n    }\n\n    @Override\n    public void sort() {\n        // NO OP\n    }\n\n    @Override\n    public IStackList<ItemStack> getList() {\n        return list;\n    }\n\n    @Override\n    public IStackList<ItemStack> getCraftablesList() {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public List<? extends IGridStack> getGridStacks() {\n        return portableGrid.getItemCache().getList().getStacks()\n            .stream()\n            .map(stack -> ItemGridStack.of(stack, portableGrid.getItemStorageTracker(), null, false))\n            .toList();\n    }\n\n    @Override\n    public List<IStorage<ItemStack>> getStorages() {\n        return Collections.emptyList();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/cache/listener/FluidGridStorageCacheListener.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.cache.listener;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener;\nimport com.refinedmods.refinedstorage.api.util.StackListResult;\nimport com.refinedmods.refinedstorage.network.grid.GridFluidDeltaMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridFluidUpdateMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridItemDeltaMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridStackDelta;\nimport com.refinedmods.refinedstorage.screen.grid.stack.FluidGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.minecraft.server.level.ServerPlayer;\nimport net.neoforged.neoforge.fluids.FluidStack;\n\npublic class FluidGridStorageCacheListener implements IStorageCacheListener<FluidStack> {\n    private final ServerPlayer player;\n    private final INetwork network;\n\n    public FluidGridStorageCacheListener(ServerPlayer player, INetwork network) {\n        this.player = player;\n        this.network = network;\n    }\n\n    @Override\n    public void onAttached() {\n        RS.NETWORK_HANDLER.sendTo(player, new GridFluidUpdateMessage(\n            network.getSecurityManager().hasPermission(Permission.AUTOCRAFTING, player),\n            (List<FluidGridStack>) network.getFluidStorageCache().getGridStacks()\n        ));\n    }\n\n    @Override\n    public void onInvalidated() {\n        // NO OP\n    }\n\n    @Override\n    public void onChanged(StackListResult<FluidStack> delta) {\n        List<StackListResult<FluidStack>> deltas = new ArrayList<>();\n\n        deltas.add(delta);\n\n        onChangedBulk(deltas);\n    }\n\n    @Override\n    public void onChangedBulk(List<StackListResult<FluidStack>> deltas) {\n        final List<GridStackDelta<FluidGridStack>> syncDeltas = deltas.stream()\n            .map(delta -> new GridStackDelta<>(\n                delta.getChange(),\n                FluidGridStack.of(\n                    network.getFluidStorageCache(),\n                    network.getFluidStorageCache().getCraftablesList(),\n                    network.getFluidStorageTracker(),\n                    delta\n                )\n            )).toList();\n        RS.NETWORK_HANDLER.sendTo(player, new GridFluidDeltaMessage(syncDeltas));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/cache/listener/ItemGridStorageCacheListener.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.cache.listener;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener;\nimport com.refinedmods.refinedstorage.api.util.StackListResult;\nimport com.refinedmods.refinedstorage.network.grid.GridItemDeltaMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridItemUpdateMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridStackDelta;\nimport com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.item.ItemStack;\n\npublic class ItemGridStorageCacheListener implements IStorageCacheListener<ItemStack> {\n    private final ServerPlayer player;\n    private final INetwork network;\n\n    public ItemGridStorageCacheListener(ServerPlayer player, INetwork network) {\n        this.player = player;\n        this.network = network;\n    }\n\n    @Override\n    public void onAttached() {\n        RS.NETWORK_HANDLER.sendTo(player, new GridItemUpdateMessage(\n            network.getSecurityManager().hasPermission(Permission.AUTOCRAFTING, player),\n            (List<ItemGridStack>) network.getItemStorageCache().getGridStacks()\n        ));\n    }\n\n    @Override\n    public void onInvalidated() {\n        // NO OP\n    }\n\n    @Override\n    public void onChanged(StackListResult<ItemStack> delta) {\n        List<StackListResult<ItemStack>> deltas = new ArrayList<>();\n        deltas.add(delta);\n        onChangedBulk(deltas);\n    }\n\n    @Override\n    public void onChangedBulk(List<StackListResult<ItemStack>> deltas) {\n        final List<GridStackDelta<ItemGridStack>> syncDeltas = deltas.stream()\n            .map(delta -> new GridStackDelta<>(\n                delta.getChange(),\n                ItemGridStack.of(\n                    network.getItemStorageCache(),\n                    network.getItemStorageCache().getCraftablesList(),\n                    network.getItemStorageTracker(),\n                    delta\n                )\n            )).toList();\n        RS.NETWORK_HANDLER.sendTo(player, new GridItemDeltaMessage(syncDeltas));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/cache/listener/PortableFluidGridStorageCacheListener.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.cache.listener;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener;\nimport com.refinedmods.refinedstorage.api.util.StackListResult;\nimport com.refinedmods.refinedstorage.blockentity.grid.portable.IPortableGrid;\nimport com.refinedmods.refinedstorage.network.grid.GridFluidDeltaMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridFluidUpdateMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridItemDeltaMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridItemUpdateMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridStackDelta;\nimport com.refinedmods.refinedstorage.screen.grid.stack.FluidGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack;\n\nimport net.minecraft.server.level.ServerPlayer;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class PortableFluidGridStorageCacheListener implements IStorageCacheListener<FluidStack> {\n    private final IPortableGrid portableGrid;\n    private final ServerPlayer player;\n\n    public PortableFluidGridStorageCacheListener(IPortableGrid portableGrid, ServerPlayer player) {\n        this.portableGrid = portableGrid;\n        this.player = player;\n    }\n\n    @Override\n    public void onAttached() {\n        RS.NETWORK_HANDLER.sendTo(player, new GridFluidUpdateMessage(\n            false,\n            (List<FluidGridStack>) portableGrid.getFluidCache().getGridStacks()\n        ));\n    }\n\n    @Override\n    public void onInvalidated() {\n        // NO OP\n    }\n\n    @Override\n    public void onChanged(StackListResult<FluidStack> delta) {\n        List<StackListResult<FluidStack>> deltas = new ArrayList<>();\n\n        deltas.add(delta);\n\n        onChangedBulk(deltas);\n    }\n\n    @Override\n    public void onChangedBulk(List<StackListResult<FluidStack>> deltas) {\n        final List<GridStackDelta<FluidGridStack>> syncDeltas = deltas.stream()\n            .map(delta -> new GridStackDelta<>(\n                delta.getChange(),\n                FluidGridStack.of(\n                    portableGrid.getFluidCache(),\n                    null,\n                    portableGrid.getFluidStorageTracker(),\n                    delta\n                )\n            )).toList();\n        RS.NETWORK_HANDLER.sendTo(player, new GridFluidDeltaMessage(syncDeltas));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/cache/listener/PortableItemGridStorageCacheListener.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.cache.listener;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener;\nimport com.refinedmods.refinedstorage.api.util.StackListResult;\nimport com.refinedmods.refinedstorage.network.grid.GridItemDeltaMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridItemUpdateMessage;\nimport com.refinedmods.refinedstorage.blockentity.grid.portable.IPortableGrid;\nimport com.refinedmods.refinedstorage.network.grid.GridStackDelta;\nimport com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack;\n\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.item.ItemStack;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class PortableItemGridStorageCacheListener implements IStorageCacheListener<ItemStack> {\n    private final IPortableGrid portableGrid;\n    private final ServerPlayer player;\n\n    public PortableItemGridStorageCacheListener(IPortableGrid portableGrid, ServerPlayer player) {\n        this.portableGrid = portableGrid;\n        this.player = player;\n    }\n\n    @Override\n    public void onAttached() {\n        RS.NETWORK_HANDLER.sendTo(player, new GridItemUpdateMessage(\n            false,\n            (List<ItemGridStack>) portableGrid.getItemCache().getGridStacks()\n        ));\n    }\n\n    @Override\n    public void onInvalidated() {\n        // NO OP\n    }\n\n    @Override\n    public void onChanged(StackListResult<ItemStack> delta) {\n        List<StackListResult<ItemStack>> deltas = new ArrayList<>();\n        deltas.add(delta);\n        onChangedBulk(deltas);\n    }\n\n    @Override\n    public void onChangedBulk(List<StackListResult<ItemStack>> deltas) {\n        final List<GridStackDelta<ItemGridStack>> syncDeltas = deltas.stream()\n            .map(delta -> new GridStackDelta<>(\n                delta.getChange(),\n                ItemGridStack.of(\n                    portableGrid.getItemCache(),\n                    null,\n                    portableGrid.getItemStorageTracker(),\n                    delta\n                )\n            )).toList();\n        RS.NETWORK_HANDLER.sendTo(player, new GridItemDeltaMessage(syncDeltas));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/FluidStorageDisk.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.disk;\n\nimport com.google.common.collect.ArrayListMultimap;\nimport com.google.common.collect.Multimap;\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskListener;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.storage.disk.factory.FluidStorageDiskFactory;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.level.material.Fluid;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.Collection;\nimport java.util.UUID;\n\npublic class FluidStorageDisk implements IStorageDisk<FluidStack> {\n    public static final String NBT_VERSION = \"Version\";\n    public static final String NBT_CAPACITY = \"Capacity\";\n    public static final String NBT_FLUIDS = \"Fluids\";\n    public static final String NBT_OWNER = \"Owner\";\n    public static final int VERSION = 1;\n\n    @Nullable\n    private final ServerLevel level;\n    private final int capacity;\n    private final Multimap<Fluid, FluidStack> stacks = ArrayListMultimap.create();\n    private final UUID owner;\n\n    @Nullable\n    private IStorageDiskListener listener;\n    private IStorageDiskContainerContext context;\n\n    public FluidStorageDisk(@Nullable ServerLevel level, int capacity, @Nullable UUID owner) {\n        this.level = level;\n        this.capacity = capacity;\n        this.owner = owner;\n    }\n\n    @Override\n    public CompoundTag writeToNbt() {\n        CompoundTag tag = new CompoundTag();\n\n        ListTag list = new ListTag();\n\n        for (FluidStack stack : stacks.values()) {\n            list.add(stack.writeToNBT(new CompoundTag()));\n        }\n\n        tag.putInt(NBT_VERSION, VERSION);\n        tag.put(NBT_FLUIDS, list);\n        tag.putInt(NBT_CAPACITY, capacity);\n\n        if (owner != null) {\n            tag.putUUID(NBT_OWNER, owner);\n        }\n\n        return tag;\n    }\n\n    @Override\n    public Collection<FluidStack> getStacks() {\n        return stacks.values();\n    }\n\n    @Override\n    @Nonnull\n    public FluidStack insert(@Nonnull FluidStack stack, int size, Action action) {\n        if (stack.isEmpty()) {\n            return stack;\n        }\n\n        for (FluidStack otherStack : stacks.get(stack.getFluid())) {\n            if (otherStack.isFluidEqual(stack)) {\n                if (getCapacity() != -1 && getStored() + size > getCapacity()) {\n                    int remainingSpace = getCapacity() - getStored();\n\n                    if (remainingSpace <= 0) {\n                        return StackUtils.copy(stack, size);\n                    }\n\n                    if (action == Action.PERFORM) {\n                        otherStack.grow(remainingSpace);\n\n                        onChanged();\n                    }\n\n                    return StackUtils.copy(otherStack, size - remainingSpace);\n                } else {\n                    int maxConsumable = Math.min(size, Integer.MAX_VALUE - otherStack.getAmount());\n                    if (action == Action.PERFORM) {\n                        otherStack.grow(maxConsumable);\n\n                        onChanged();\n                    }\n\n                    return StackUtils.copy(otherStack, size - maxConsumable);\n                }\n            }\n        }\n\n        if (getCapacity() != -1 && getStored() + size > getCapacity()) {\n            int remainingSpace = getCapacity() - getStored();\n\n            if (remainingSpace <= 0) {\n                return StackUtils.copy(stack, size);\n            }\n\n            if (action == Action.PERFORM) {\n                stacks.put(stack.getFluid(), StackUtils.copy(stack, remainingSpace));\n\n                onChanged();\n            }\n\n            return StackUtils.copy(stack, size - remainingSpace);\n        } else {\n            if (action == Action.PERFORM) {\n                stacks.put(stack.getFluid(), StackUtils.copy(stack, size));\n\n                onChanged();\n            }\n\n            return FluidStack.EMPTY;\n        }\n    }\n\n    @Override\n    @Nonnull\n    public FluidStack extract(@Nonnull FluidStack stack, int size, int flags, Action action) {\n        if (stack.isEmpty()) {\n            return stack;\n        }\n\n        for (FluidStack otherStack : stacks.get(stack.getFluid())) {\n            if (API.instance().getComparer().isEqual(otherStack, stack, flags)) {\n                if (size > otherStack.getAmount()) {\n                    size = otherStack.getAmount();\n                }\n\n                if (action == Action.PERFORM) {\n                    if (otherStack.getAmount() - size == 0) {\n                        stacks.remove(otherStack.getFluid(), otherStack);\n                    } else {\n                        otherStack.shrink(size);\n                    }\n\n                    onChanged();\n                }\n\n                return StackUtils.copy(otherStack, size);\n            }\n        }\n\n        return FluidStack.EMPTY;\n    }\n\n    @Override\n    public int getStored() {\n        return stacks.values().stream().mapToInt(FluidStack::getAmount).sum();\n    }\n\n    @Override\n    public int getPriority() {\n        return 0;\n    }\n\n    @Override\n    public AccessType getAccessType() {\n        return context.getAccessType();\n    }\n\n    @Override\n    public int getCapacity() {\n        return capacity;\n    }\n\n    @Nullable\n    @Override\n    public UUID getOwner() {\n        return owner;\n    }\n\n    @Override\n    public int getCacheDelta(int storedPreInsertion, int size, @Nullable FluidStack remainder) {\n        if (getAccessType() == AccessType.INSERT) {\n            return 0;\n        }\n\n        return remainder == null ? size : (size - remainder.getAmount());\n    }\n\n    @Override\n    public void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context) {\n        this.listener = listener;\n        this.context = context;\n    }\n\n    @Override\n    public ResourceLocation getFactoryId() {\n        return FluidStorageDiskFactory.ID;\n    }\n\n    public Multimap<Fluid, FluidStack> getRawStacks() {\n        return stacks;\n    }\n\n    private void onChanged() {\n        if (listener != null) {\n            listener.onChanged();\n        }\n\n        if (level != null) {\n            API.instance().getStorageDiskManager(level).markForSaving();\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/ItemStorageDisk.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.disk;\n\nimport com.google.common.collect.ArrayListMultimap;\nimport com.google.common.collect.Multimap;\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskListener;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.storage.disk.factory.ItemStorageDiskFactory;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.Collection;\nimport java.util.UUID;\n\npublic class ItemStorageDisk implements IStorageDisk<ItemStack> {\n    public static final String NBT_VERSION = \"Version\";\n    public static final String NBT_CAPACITY = \"Capacity\";\n    public static final String NBT_ITEMS = \"Items\";\n    public static final String NBT_OWNER = \"Owner\";\n    public static final int VERSION = 1;\n\n    @Nullable\n    private final ServerLevel level;\n    private final int capacity;\n    private final Multimap<Item, ItemStack> stacks = ArrayListMultimap.create();\n    private final UUID owner;\n    private int itemCount;\n\n    @Nullable\n    private IStorageDiskListener listener;\n    private IStorageDiskContainerContext context;\n\n    public ItemStorageDisk(@Nullable ServerLevel level, int capacity, @Nullable UUID owner) {\n        this.level = level;\n        this.capacity = capacity;\n        this.owner = owner;\n    }\n\n    @Override\n    public CompoundTag writeToNbt() {\n        CompoundTag tag = new CompoundTag();\n\n        ListTag list = new ListTag();\n\n        for (ItemStack stack : stacks.values()) {\n            list.add(StackUtils.serializeStackToNbt(stack));\n        }\n\n        tag.putInt(NBT_VERSION, VERSION);\n        tag.put(NBT_ITEMS, list);\n        tag.putInt(NBT_CAPACITY, capacity);\n\n        if (owner != null) {\n            tag.putUUID(NBT_OWNER, owner);\n        }\n\n        return tag;\n    }\n\n    @Override\n    public ResourceLocation getFactoryId() {\n        return ItemStorageDiskFactory.ID;\n    }\n\n    @Override\n    public Collection<ItemStack> getStacks() {\n        return stacks.values();\n    }\n\n    @Override\n    @Nonnull\n    public ItemStack insert(@Nonnull ItemStack stack, int size, Action action) {\n        if (stack.isEmpty() || itemCount == capacity) {\n            return ItemHandlerHelper.copyStackWithSize(stack, size);\n        }\n\n        for (ItemStack otherStack : stacks.get(stack.getItem())) {\n            if (API.instance().getComparer().isEqualNoQuantity(otherStack, stack)) {\n                if (getCapacity() != -1 && getStored() + size > getCapacity()) {\n                    int remainingSpace = getCapacity() - getStored();\n\n                    if (remainingSpace <= 0) {\n                        return ItemHandlerHelper.copyStackWithSize(stack, size);\n                    }\n\n                    if (action == Action.PERFORM) {\n                        otherStack.grow(remainingSpace);\n                        itemCount += remainingSpace;\n                        onChanged();\n                    }\n\n                    return ItemHandlerHelper.copyStackWithSize(otherStack, size - remainingSpace);\n                } else {\n                    int maxConsumable = Math.min(size, Integer.MAX_VALUE - otherStack.getCount());\n                    if (action == Action.PERFORM) {\n                        otherStack.grow(maxConsumable);\n                        itemCount += maxConsumable;\n\n                        onChanged();\n                    }\n\n                    return ItemHandlerHelper.copyStackWithSize(otherStack, size - maxConsumable);\n                }\n            }\n        }\n\n        if (getCapacity() != -1 && getStored() + size > getCapacity()) {\n            int remainingSpace = getCapacity() - getStored();\n\n            if (remainingSpace <= 0) {\n                return ItemHandlerHelper.copyStackWithSize(stack, size);\n            }\n\n            if (action == Action.PERFORM) {\n                stacks.put(stack.getItem(), ItemHandlerHelper.copyStackWithSize(stack, remainingSpace));\n                itemCount += remainingSpace;\n                onChanged();\n            }\n\n            return ItemHandlerHelper.copyStackWithSize(stack, size - remainingSpace);\n        } else {\n            if (action == Action.PERFORM) {\n                stacks.put(stack.getItem(), ItemHandlerHelper.copyStackWithSize(stack, size));\n                itemCount += size;\n\n                onChanged();\n            }\n\n            return ItemStack.EMPTY;\n        }\n    }\n\n    @Override\n    @Nonnull\n    public ItemStack extract(@Nonnull ItemStack stack, int size, int flags, Action action) {\n        if (stack.isEmpty()) {\n            return stack;\n        }\n\n        for (ItemStack otherStack : stacks.get(stack.getItem())) {\n            if (API.instance().getComparer().isEqual(otherStack, stack, flags)) {\n                if (size > otherStack.getCount()) {\n                    size = otherStack.getCount();\n                }\n\n                if (action == Action.PERFORM) {\n                    if (otherStack.getCount() - size == 0) {\n                        stacks.remove(otherStack.getItem(), otherStack);\n                    } else {\n                        otherStack.shrink(size);\n                    }\n\n                    itemCount -= size;\n\n                    onChanged();\n                }\n\n                return ItemHandlerHelper.copyStackWithSize(otherStack, size);\n            }\n        }\n\n        return ItemStack.EMPTY;\n    }\n\n    @Override\n    public int getStored() {\n        return itemCount;\n    }\n\n    @Override\n    public int getPriority() {\n        return 0;\n    }\n\n    @Override\n    public AccessType getAccessType() {\n        return context.getAccessType();\n    }\n\n    @Override\n    public int getCapacity() {\n        return capacity;\n    }\n\n    @Nullable\n    @Override\n    public UUID getOwner() {\n        return owner;\n    }\n\n    @Override\n    public void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context) {\n        this.listener = listener;\n        this.context = context;\n    }\n\n    @Override\n    public int getCacheDelta(int storedPreInsertion, int size, @Nullable ItemStack remainder) {\n        if (getAccessType() == AccessType.INSERT) {\n            return 0;\n        }\n\n        return remainder == null ? size : (size - remainder.getCount());\n    }\n\n    public Multimap<Item, ItemStack> getRawStacks() {\n        return stacks;\n    }\n\n    private void onChanged() {\n        if (listener != null) {\n            listener.onChanged();\n        }\n\n        if (level != null) {\n            API.instance().getStorageDiskManager(level).markForSaving();\n        }\n    }\n\n    public void updateItemCount() {\n        itemCount = stacks.values().stream().mapToInt(ItemStack::getCount).sum();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/PortableFluidStorageDisk.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.disk;\n\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskListener;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.blockentity.grid.portable.IPortableGrid;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.Collection;\nimport java.util.UUID;\n\npublic class PortableFluidStorageDisk implements IStorageDisk<FluidStack> {\n    private final IStorageDisk<FluidStack> parent;\n    private final IPortableGrid portableGrid;\n\n    public PortableFluidStorageDisk(IStorageDisk<FluidStack> parent, IPortableGrid portableGrid) {\n        this.parent = parent;\n        this.portableGrid = portableGrid;\n    }\n\n    @Override\n    public int getCapacity() {\n        return parent.getCapacity();\n    }\n\n    @Nullable\n    @Override\n    public UUID getOwner() {\n        return parent.getOwner();\n    }\n\n    @Override\n    public void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context) {\n        parent.setSettings(listener, context);\n    }\n\n    @Override\n    public CompoundTag writeToNbt() {\n        return parent.writeToNbt();\n    }\n\n    @Override\n    public Collection<FluidStack> getStacks() {\n        return parent.getStacks();\n    }\n\n    @Override\n    @Nonnull\n    public FluidStack insert(@Nonnull FluidStack stack, int size, Action action) {\n        int storedPre = parent.getStored();\n\n        FluidStack remainder = parent.insert(stack, size, action);\n\n        if (action == Action.PERFORM) {\n            int inserted = parent.getCacheDelta(storedPre, size, remainder);\n\n            if (inserted > 0) {\n                portableGrid.getFluidCache().add(stack, inserted, false, false);\n            }\n        }\n\n        return remainder;\n    }\n\n    @Override\n    @Nonnull\n    public FluidStack extract(@Nonnull FluidStack stack, int size, int flags, Action action) {\n        FluidStack extracted = parent.extract(stack, size, flags, action);\n\n        if (action == Action.PERFORM && !extracted.isEmpty()) {\n            portableGrid.getFluidCache().remove(extracted, extracted.getAmount(), false);\n        }\n\n        return extracted;\n    }\n\n    @Override\n    public int getStored() {\n        return parent.getStored();\n    }\n\n    @Override\n    public int getPriority() {\n        return parent.getPriority();\n    }\n\n    @Override\n    public AccessType getAccessType() {\n        return parent.getAccessType();\n    }\n\n    @Override\n    public int getCacheDelta(int storedPreInsertion, int size, @Nullable FluidStack remainder) {\n        return parent.getCacheDelta(storedPreInsertion, size, remainder);\n    }\n\n    @Override\n    public ResourceLocation getFactoryId() {\n        return parent.getFactoryId();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/PortableItemStorageDisk.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.disk;\n\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskListener;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.blockentity.grid.portable.IPortableGrid;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.Collection;\nimport java.util.UUID;\n\npublic class PortableItemStorageDisk implements IStorageDisk<ItemStack> {\n    private final IStorageDisk<ItemStack> parent;\n    private final IPortableGrid portableGrid;\n\n    public PortableItemStorageDisk(IStorageDisk<ItemStack> parent, IPortableGrid portableGrid) {\n        this.parent = parent;\n        this.portableGrid = portableGrid;\n    }\n\n    @Override\n    public int getCapacity() {\n        return parent.getCapacity();\n    }\n\n    @Nullable\n    @Override\n    public UUID getOwner() {\n        return parent.getOwner();\n    }\n\n    @Override\n    public void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context) {\n        parent.setSettings(listener, context);\n    }\n\n    @Override\n    public CompoundTag writeToNbt() {\n        return parent.writeToNbt();\n    }\n\n    @Override\n    public Collection<ItemStack> getStacks() {\n        return parent.getStacks();\n    }\n\n    @Override\n    @Nonnull\n    public ItemStack insert(@Nonnull ItemStack stack, int size, Action action) {\n        int storedPre = parent.getStored();\n\n        ItemStack remainder = parent.insert(stack, size, action);\n\n        if (action == Action.PERFORM) {\n            int inserted = parent.getCacheDelta(storedPre, size, remainder);\n\n            if (inserted > 0) {\n                portableGrid.getItemCache().add(stack, inserted, false, false);\n            }\n        }\n\n        return remainder;\n    }\n\n    @Override\n    @Nonnull\n    public ItemStack extract(@Nonnull ItemStack stack, int size, int flags, Action action) {\n        ItemStack extracted = parent.extract(stack, size, flags, action);\n\n        if (action == Action.PERFORM && !extracted.isEmpty()) {\n            portableGrid.getItemCache().remove(extracted, extracted.getCount(), false);\n        }\n\n        return extracted;\n    }\n\n    @Override\n    public int getStored() {\n        return parent.getStored();\n    }\n\n    @Override\n    public int getPriority() {\n        return parent.getPriority();\n    }\n\n    @Override\n    public AccessType getAccessType() {\n        return parent.getAccessType();\n    }\n\n    @Override\n    public int getCacheDelta(int storedPreInsertion, int size, @Nullable ItemStack remainder) {\n        return parent.getCacheDelta(storedPreInsertion, size, remainder);\n    }\n\n    @Override\n    public ResourceLocation getFactoryId() {\n        return parent.getFactoryId();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/StorageDiskManager.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.disk;\n\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskFactory;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskManager;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskProvider;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.util.RSSavedData;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.nbt.Tag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.item.ItemStack;\n\nimport javax.annotation.Nullable;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.UUID;\n\npublic class StorageDiskManager extends RSSavedData implements IStorageDiskManager {\n    public static final String NAME = \"refinedstorage_disks\";\n\n    private static final String NBT_DISKS = \"Disks\";\n    private static final String NBT_DISK_ID = \"Id\";\n    private static final String NBT_DISK_TYPE = \"Type\";\n    private static final String NBT_DISK_DATA = \"Data\";\n\n    private final Map<UUID, IStorageDisk> disks = new HashMap<>();\n    private final ServerLevel level;\n\n    public StorageDiskManager(ServerLevel level) {\n        this.level = level;\n    }\n\n    @Override\n    @Nullable\n    public IStorageDisk get(UUID id) {\n        return disks.get(id);\n    }\n\n    @Nullable\n    @Override\n    public IStorageDisk getByStack(ItemStack disk) {\n        if (!(disk.getItem() instanceof IStorageDiskProvider)) {\n            return null;\n        }\n\n        IStorageDiskProvider provider = (IStorageDiskProvider) disk.getItem();\n\n        if (!provider.isValid(disk)) {\n            return null;\n        }\n\n        return get(provider.getId(disk));\n    }\n\n    @Override\n    public Map<UUID, IStorageDisk> getAll() {\n        return disks;\n    }\n\n    @Override\n    public void set(UUID id, IStorageDisk disk) {\n        if (id == null) {\n            throw new IllegalArgumentException(\"Id cannot be null\");\n        }\n\n        if (disk == null) {\n            throw new IllegalArgumentException(\"Disk cannot be null\");\n        }\n\n        if (disks.containsKey(id)) {\n            throw new IllegalArgumentException(\"Disks already contains id '\" + id + \"'\");\n        }\n\n        disks.put(id, disk);\n    }\n\n    @Override\n    public void remove(UUID id) {\n        if (id == null) {\n            throw new IllegalArgumentException(\"Id cannot be null\");\n        }\n\n        disks.remove(id);\n    }\n\n    @Override\n    public void markForSaving() {\n        setDirty();\n    }\n\n    @Override\n    public void load(CompoundTag tag) {\n        if (tag.contains(NBT_DISKS)) {\n            ListTag disksTag = tag.getList(NBT_DISKS, Tag.TAG_COMPOUND);\n\n            for (int i = 0; i < disksTag.size(); ++i) {\n                CompoundTag diskTag = disksTag.getCompound(i);\n\n                UUID id = diskTag.getUUID(NBT_DISK_ID);\n                CompoundTag data = diskTag.getCompound(NBT_DISK_DATA);\n                String type = diskTag.getString(NBT_DISK_TYPE);\n\n                IStorageDiskFactory factory = API.instance().getStorageDiskRegistry().get(new ResourceLocation(type));\n                if (factory != null) {\n                    disks.put(id, factory.createFromNbt(level, data));\n                }\n            }\n        }\n    }\n\n    @Override\n    public CompoundTag save(CompoundTag tag) {\n        ListTag disksTag = new ListTag();\n\n        for (Map.Entry<UUID, IStorageDisk> entry : disks.entrySet()) {\n            CompoundTag diskTag = new CompoundTag();\n\n            diskTag.putUUID(NBT_DISK_ID, entry.getKey());\n            diskTag.put(NBT_DISK_DATA, entry.getValue().writeToNbt());\n            diskTag.putString(NBT_DISK_TYPE, entry.getValue().getFactoryId().toString());\n\n            disksTag.add(diskTag);\n        }\n\n        tag.put(NBT_DISKS, disksTag);\n\n        return tag;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/StorageDiskRegistry.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.disk;\n\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskFactory;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskRegistry;\nimport net.minecraft.resources.ResourceLocation;\n\nimport javax.annotation.Nullable;\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class StorageDiskRegistry implements IStorageDiskRegistry {\n    private final Map<ResourceLocation, IStorageDiskFactory> factories = new HashMap<>();\n\n    @Override\n    public void add(ResourceLocation id, IStorageDiskFactory factory) {\n        factories.put(id, factory);\n    }\n\n    @Override\n    @Nullable\n    public IStorageDiskFactory get(ResourceLocation id) {\n        return factories.get(id);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/StorageDiskSync.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.disk;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskSync;\nimport com.refinedmods.refinedstorage.api.storage.disk.StorageDiskSyncData;\nimport com.refinedmods.refinedstorage.network.disk.StorageDiskSizeRequestMessage;\n\nimport javax.annotation.Nullable;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.UUID;\n\npublic class StorageDiskSync implements IStorageDiskSync {\n    private static final int THROTTLE_MS = 500;\n\n    private final Map<UUID, StorageDiskSyncData> data = new HashMap<>();\n    private final Map<UUID, Long> syncTime = new HashMap<>();\n\n    @Nullable\n    @Override\n    public StorageDiskSyncData getData(UUID id) {\n        return data.get(id);\n    }\n\n    public void setData(UUID id, StorageDiskSyncData data) {\n        this.data.put(id, data);\n    }\n\n    @Override\n    public void sendRequest(UUID id) {\n        long lastSync = syncTime.getOrDefault(id, 0L);\n\n        if (System.currentTimeMillis() - lastSync > THROTTLE_MS) {\n            RS.NETWORK_HANDLER.sendToServer(new StorageDiskSizeRequestMessage(id));\n\n            syncTime.put(id, System.currentTimeMillis());\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/factory/FluidStorageDiskFactory.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.disk.factory;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskFactory;\nimport com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType;\nimport com.refinedmods.refinedstorage.apiimpl.storage.disk.FluidStorageDisk;\nimport com.refinedmods.refinedstorage.item.FluidStorageDiskItem;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.nbt.Tag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nullable;\nimport java.util.UUID;\n\npublic class FluidStorageDiskFactory implements IStorageDiskFactory<FluidStack> {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"fluid\");\n\n    @Override\n    public IStorageDisk<FluidStack> createFromNbt(ServerLevel level, CompoundTag tag) {\n        FluidStorageDisk disk = new FluidStorageDisk(\n            level,\n            tag.getInt(FluidStorageDisk.NBT_CAPACITY),\n            tag.contains(FluidStorageDisk.NBT_OWNER) ? tag.getUUID(FluidStorageDisk.NBT_OWNER) : null\n        );\n\n        ListTag list = tag.getList(FluidStorageDisk.NBT_FLUIDS, Tag.TAG_COMPOUND);\n\n        for (int i = 0; i < list.size(); ++i) {\n            FluidStack stack = FluidStack.loadFluidStackFromNBT(list.getCompound(i));\n\n            if (!stack.isEmpty()) {\n                disk.getRawStacks().put(stack.getRawFluid(), stack);\n            }\n        }\n\n        return disk;\n    }\n\n    @Override\n    public ItemStack createDiskItem(IStorageDisk<FluidStack> disk, UUID id) {\n        FluidStorageDiskItem item;\n        switch (disk.getCapacity()) {\n            case 64_000:\n                item = RSItems.FLUID_STORAGE_DISKS.get(FluidStorageType.SIXTY_FOUR_K).get();\n                break;\n            case 256_000:\n                item = RSItems.FLUID_STORAGE_DISKS.get(FluidStorageType.TWO_HUNDRED_FIFTY_SIX_K).get();\n                break;\n            case 1024_000:\n                item = RSItems.FLUID_STORAGE_DISKS.get(FluidStorageType.THOUSAND_TWENTY_FOUR_K).get();\n                break;\n            case 4096_000:\n                item = RSItems.FLUID_STORAGE_DISKS.get(FluidStorageType.FOUR_THOUSAND_NINETY_SIX_K).get();\n                break;\n            default:\n                item = RSItems.FLUID_STORAGE_DISKS.get(FluidStorageType.CREATIVE).get();\n                break;\n        }\n\n        ItemStack stack = new ItemStack(item);\n        item.setId(stack, id);\n        return stack;\n    }\n\n    @Override\n    public IStorageDisk<FluidStack> create(ServerLevel level, int capacity, @Nullable UUID owner) {\n        return new FluidStorageDisk(level, capacity, owner);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/factory/ItemStorageDiskFactory.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.disk.factory;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskFactory;\nimport com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType;\nimport com.refinedmods.refinedstorage.apiimpl.storage.disk.ItemStorageDisk;\nimport com.refinedmods.refinedstorage.item.StorageDiskItem;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.nbt.Tag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.item.ItemStack;\n\nimport javax.annotation.Nullable;\nimport java.util.UUID;\n\npublic class ItemStorageDiskFactory implements IStorageDiskFactory<ItemStack> {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"item\");\n\n    @Override\n    public IStorageDisk<ItemStack> createFromNbt(ServerLevel level, CompoundTag tag) {\n        ItemStorageDisk disk = new ItemStorageDisk(\n            level,\n            tag.getInt(ItemStorageDisk.NBT_CAPACITY),\n            tag.contains(ItemStorageDisk.NBT_OWNER) ? tag.getUUID(ItemStorageDisk.NBT_OWNER) : null\n        );\n\n        ListTag list = tag.getList(ItemStorageDisk.NBT_ITEMS, Tag.TAG_COMPOUND);\n\n        for (int i = 0; i < list.size(); ++i) {\n            ItemStack stack = StackUtils.deserializeStackFromNbt(list.getCompound(i));\n\n            if (!stack.isEmpty()) {\n                disk.getRawStacks().put(stack.getItem(), stack);\n            }\n        }\n\n        disk.updateItemCount();\n\n        return disk;\n    }\n\n    @Override\n    public ItemStack createDiskItem(IStorageDisk<ItemStack> disk, UUID id) {\n        StorageDiskItem item;\n        switch (disk.getCapacity()) {\n            case 1_000:\n                item = RSItems.ITEM_STORAGE_DISKS.get(ItemStorageType.ONE_K).get();\n                break;\n            case 4_000:\n                item = RSItems.ITEM_STORAGE_DISKS.get(ItemStorageType.FOUR_K).get();\n                break;\n            case 16_000:\n                item = RSItems.ITEM_STORAGE_DISKS.get(ItemStorageType.SIXTEEN_K).get();\n                break;\n            case 64_000:\n                item = RSItems.ITEM_STORAGE_DISKS.get(ItemStorageType.SIXTY_FOUR_K).get();\n                break;\n            default:\n                item = RSItems.ITEM_STORAGE_DISKS.get(ItemStorageType.CREATIVE).get();\n                break;\n        }\n\n        ItemStack stack = new ItemStack(item);\n        item.setId(stack, id);\n        return stack;\n    }\n\n    @Override\n    public IStorageDisk<ItemStack> create(ServerLevel level, int capacity, @Nullable UUID owner) {\n        return new ItemStorageDisk(level, capacity, owner);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/externalstorage/FluidExternalStorage.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.externalstorage;\n\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorage;\nimport com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorageContext;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.fluids.capability.IFluidHandler;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.function.Supplier;\n\npublic class FluidExternalStorage implements IExternalStorage<FluidStack> {\n    private final IExternalStorageContext context;\n    private final Supplier<IFluidHandler> handlerSupplier;\n    private final boolean connectedToInterface;\n    private final FluidExternalStorageCache cache = new FluidExternalStorageCache();\n\n    public FluidExternalStorage(IExternalStorageContext context, Supplier<IFluidHandler> handlerSupplier, boolean connectedToInterface) {\n        this.context = context;\n        this.handlerSupplier = handlerSupplier;\n        this.connectedToInterface = connectedToInterface;\n    }\n\n    public boolean isConnectedToInterface() {\n        return connectedToInterface;\n    }\n\n    @Override\n    public void update(INetwork network) {\n        if (getAccessType() == AccessType.INSERT) {\n            return;\n        }\n\n        cache.update(network, handlerSupplier.get());\n    }\n\n    @Override\n    public long getCapacity() {\n        IFluidHandler fluidHandler = handlerSupplier.get();\n\n        if (fluidHandler != null) {\n            long cap = 0;\n\n            for (int i = 0; i < fluidHandler.getTanks(); ++i) {\n                cap += fluidHandler.getTankCapacity(i);\n            }\n\n            return cap;\n        }\n\n        return 0;\n    }\n\n    @Override\n    public Collection<FluidStack> getStacks() {\n        IFluidHandler fluidHandler = handlerSupplier.get();\n\n        if (fluidHandler != null) {\n            cache.initCache(fluidHandler);\n\n            List<FluidStack> fluids = new ArrayList<>();\n\n            for (int i = 0; i < fluidHandler.getTanks(); ++i) {\n                fluids.add(fluidHandler.getFluidInTank(i));\n            }\n\n            return fluids;\n        }\n\n        return Collections.emptyList();\n    }\n\n    @Override\n    @Nonnull\n    public FluidStack insert(@Nonnull FluidStack stack, int size, Action action) {\n        if (stack.isEmpty()) {\n            return stack;\n        }\n\n        IFluidHandler handler = handlerSupplier.get();\n\n        if (context.acceptsFluid(stack) && handler != null) {\n\n            int filled = handler.fill(StackUtils.copy(stack, size), action == Action.PERFORM ? IFluidHandler.FluidAction.EXECUTE : IFluidHandler.FluidAction.SIMULATE);\n\n            if (filled == size) {\n                return FluidStack.EMPTY;\n            }\n\n            return StackUtils.copy(stack, size - filled);\n        }\n\n        return StackUtils.copy(stack, size);\n    }\n\n    @Override\n    @Nonnull\n    public FluidStack extract(@Nonnull FluidStack stack, int size, int flags, Action action) {\n        if (stack.isEmpty()) {\n            return stack;\n        }\n\n        IFluidHandler handler = handlerSupplier.get();\n\n        if (handler == null) {\n            return FluidStack.EMPTY;\n        }\n\n        return handler.drain(StackUtils.copy(stack, size), action == Action.PERFORM ? IFluidHandler.FluidAction.EXECUTE : IFluidHandler.FluidAction.SIMULATE);\n    }\n\n    @Override\n    public int getStored() {\n        return cache.getStored();\n    }\n\n    @Override\n    public int getPriority() {\n        return context.getPriority();\n    }\n\n    @Override\n    public AccessType getAccessType() {\n        return context.getAccessType();\n    }\n\n    @Override\n    public int getCacheDelta(int storedPreInsertion, int size, @Nullable FluidStack remainder) {\n        if (getAccessType() == AccessType.INSERT) {\n            return 0;\n        }\n\n        return remainder == null ? size : (size - remainder.getAmount());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/externalstorage/FluidExternalStorageCache.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.externalstorage;\n\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport javax.annotation.Nullable;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.fluids.capability.IFluidHandler;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class FluidExternalStorageCache {\n    private List<FluidStack> cache;\n    private int stored = 0;\n\n    public int getStored() {\n        return stored;\n    }\n\n    public boolean initCache(IFluidHandler handler) {\n        if (cache != null) {\n            return false;\n        }\n\n        cache = new ArrayList<>();\n\n        int stored = 0;\n        for (int i = 0; i < handler.getTanks(); ++i) {\n            FluidStack stack = handler.getFluidInTank(i).copy();\n            cache.add(stack);\n            stored += stack.getAmount();\n        }\n        this.stored = stored;\n\n        return true;\n    }\n\n    public void update(INetwork network, @Nullable IFluidHandler handler) {\n        if (handler == null) {\n            stored = 0;\n            return;\n        }\n\n        if (initCache(handler)) {\n            return;\n        }\n\n        int stored = 0;\n        for (int i = 0; i < handler.getTanks(); ++i) {\n            FluidStack actual = handler.getFluidInTank(i);\n            stored += actual.getAmount();\n\n            if (i >= cache.size()) { // ENLARGED\n                if (!actual.isEmpty()) {\n                    network.getFluidStorageCache().add(actual, actual.getAmount(), false, true);\n\n                    cache.add(actual.copy());\n                }\n\n                continue;\n            }\n\n            FluidStack cached = cache.get(i);\n\n            if (actual.isEmpty() && cached.isEmpty()) { // NONE\n                continue;\n            }\n\n            if (actual.isEmpty() && !cached.isEmpty()) { // REMOVED\n                network.getFluidStorageCache().remove(cached, cached.getAmount(), true);\n\n                cache.set(i, FluidStack.EMPTY);\n            } else if (!actual.isEmpty() && cached.isEmpty()) { // ADDED\n                network.getFluidStorageCache().add(actual, actual.getAmount(), false, true);\n\n                cache.set(i, actual.copy());\n            } else if (!API.instance().getComparer().isEqual(actual, cached, IComparer.COMPARE_NBT)) { // CHANGED\n                network.getFluidStorageCache().remove(cached, cached.getAmount(), true);\n                network.getFluidStorageCache().add(actual, actual.getAmount(), false, true);\n\n                cache.set(i, actual.copy());\n            } else if (actual.getAmount() > cached.getAmount()) { // COUNT_CHANGED\n                network.getFluidStorageCache().add(actual, actual.getAmount() - cached.getAmount(), false, true);\n\n                cached.setAmount(actual.getAmount());\n            } else if (actual.getAmount() < cached.getAmount()) { // COUNT_CHANGED\n                network.getFluidStorageCache().remove(actual, cached.getAmount() - actual.getAmount(), true);\n\n                cached.setAmount(actual.getAmount());\n            }\n        }\n        this.stored = stored;\n\n        if (cache.size() > handler.getTanks()) { // SHRUNK\n            for (int i = cache.size() - 1; i >= handler.getTanks(); --i) { // Reverse order for the remove call.\n                FluidStack cached = cache.get(i);\n\n                if (!cached.isEmpty()) {\n                    network.getFluidStorageCache().remove(cached, cached.getAmount(), true);\n                }\n\n                cache.remove(i);\n            }\n        }\n\n        network.getFluidStorageCache().flush();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/externalstorage/FluidExternalStorageProvider.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.externalstorage;\n\nimport com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorage;\nimport com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorageContext;\nimport com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorageProvider;\nimport com.refinedmods.refinedstorage.blockentity.FluidInterfaceBlockEntity;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nonnull;\n\npublic class FluidExternalStorageProvider implements IExternalStorageProvider<FluidStack> {\n    @Override\n    public boolean canProvide(Level level, BlockPos pos, Direction direction) {\n        return LevelUtils.getFluidHandler(level, pos, direction.getOpposite()) != null;\n    }\n\n    @Nonnull\n    @Override\n    public IExternalStorage<FluidStack> provide(IExternalStorageContext context, BlockEntity blockEntity, Direction direction) {\n        return new FluidExternalStorage(context, () -> {\n            Level level = blockEntity.getLevel();\n            if (level == null) {\n                return null;\n            }\n            return LevelUtils.getFluidHandler(level, blockEntity.getBlockPos(), direction.getOpposite());\n        }, blockEntity instanceof FluidInterfaceBlockEntity);\n    }\n\n    @Override\n    public int getPriority() {\n        return 0;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/externalstorage/ItemExternalStorage.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.externalstorage;\n\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorage;\nimport com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorageContext;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.function.Supplier;\n\npublic class ItemExternalStorage implements IExternalStorage<ItemStack> {\n    private final IExternalStorageContext context;\n    private final Supplier<IItemHandler> handlerSupplier;\n    private final boolean connectedToInterface;\n    private final ItemExternalStorageCache cache = new ItemExternalStorageCache();\n\n    public ItemExternalStorage(IExternalStorageContext context, Supplier<IItemHandler> handlerSupplier, boolean connectedToInterface) {\n        this.context = context;\n        this.handlerSupplier = handlerSupplier;\n        this.connectedToInterface = connectedToInterface;\n    }\n\n    public boolean isConnectedToInterface() {\n        return connectedToInterface;\n    }\n\n    @Override\n    public void update(INetwork network) {\n        if (getAccessType() == AccessType.INSERT) {\n            return;\n        }\n\n        cache.update(network, handlerSupplier.get());\n    }\n\n    @Override\n    public long getCapacity() {\n        IItemHandler handler = handlerSupplier.get();\n\n        if (handler == null) {\n            return 0;\n        }\n\n        long capacity = 0;\n\n        for (int i = 0; i < handler.getSlots(); ++i) {\n            capacity += handler.getSlotLimit(i);\n        }\n\n        return capacity;\n    }\n\n    @Override\n    public Collection<ItemStack> getStacks() {\n        IItemHandler handler = handlerSupplier.get();\n\n        if (handler == null) {\n            return Collections.emptyList();\n        }\n\n        cache.initCache(handler);\n\n        List<ItemStack> stacks = new ArrayList<>();\n\n        for (int i = 0; i < handler.getSlots(); ++i) {\n            stacks.add(handler.getStackInSlot(i));\n        }\n\n        return stacks;\n    }\n\n    @Override\n    @Nonnull\n    public ItemStack insert(@Nonnull ItemStack stack, int size, Action action) {\n        if (stack.isEmpty()) {\n            return stack;\n        }\n\n        IItemHandler handler = handlerSupplier.get();\n\n        if (handler != null && context.acceptsItem(stack)) {\n            return ItemHandlerHelper.insertItem(handler, ItemHandlerHelper.copyStackWithSize(stack, size), action == Action.SIMULATE);\n        }\n\n        return ItemHandlerHelper.copyStackWithSize(stack, size);\n    }\n\n    @Override\n    @Nonnull\n    public ItemStack extract(@Nonnull ItemStack stack, int size, int flags, Action action) {\n        if (stack.isEmpty()) {\n            return stack;\n        }\n\n        IItemHandler handler = handlerSupplier.get();\n\n        if (handler == null) {\n            return ItemStack.EMPTY;\n        }\n\n        int remaining = size;\n\n        ItemStack received = ItemStack.EMPTY;\n\n        for (int i = 0; i < handler.getSlots(); ++i) {\n            ItemStack slot = handler.getStackInSlot(i);\n\n            if (!slot.isEmpty() && API.instance().getComparer().isEqual(slot, stack, flags)) {\n                ItemStack got = handler.extractItem(i, remaining, action == Action.SIMULATE);\n\n                if (!got.isEmpty()) {\n                    if (received.isEmpty()) {\n                        received = got.copy();\n                    } else {\n                        received.grow(got.getCount());\n                    }\n\n                    remaining -= got.getCount();\n\n                    if (remaining == 0) {\n                        break;\n                    }\n                }\n            }\n        }\n\n        return received;\n    }\n\n    @Override\n    public int getStored() {\n        return cache.getStored();\n    }\n\n    @Override\n    public int getPriority() {\n        return context.getPriority();\n    }\n\n    @Override\n    public AccessType getAccessType() {\n        return context.getAccessType();\n    }\n\n    @Override\n    public int getCacheDelta(int storedPreInsertion, int size, @Nullable ItemStack remainder) {\n        if (getAccessType() == AccessType.INSERT) {\n            return 0;\n        }\n\n        return remainder == null ? size : (size - remainder.getCount());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/externalstorage/ItemExternalStorageCache.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.externalstorage;\n\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class ItemExternalStorageCache {\n    private List<ItemStack> cache;\n    private int stored = 0;\n\n    public int getStored() {\n        return stored;\n    }\n\n    public boolean initCache(IItemHandler handler) {\n        if (cache != null) {\n            return false;\n        }\n\n        cache = new ArrayList<>();\n\n        int stored = 0;\n        for (int i = 0; i < handler.getSlots(); ++i) {\n            ItemStack stack = handler.getStackInSlot(i).copy();\n            cache.add(stack);\n            stored += stack.getCount();\n        }\n        this.stored = stored;\n\n        return true;\n    }\n\n    public void update(INetwork network, @Nullable IItemHandler handler) {\n        if (handler == null) {\n            stored = 0;\n            return;\n        }\n\n        if (initCache(handler)) {\n            return;\n        }\n\n        int stored = 0;\n        for (int i = 0; i < handler.getSlots(); ++i) {\n            ItemStack actual = handler.getStackInSlot(i);\n            stored += actual.getCount();\n\n            if (i >= cache.size()) { // ENLARGED\n                if (!actual.isEmpty()) {\n                    network.getItemStorageCache().add(actual, actual.getCount(), false, true);\n\n                    cache.add(actual.copy());\n                }\n\n                continue;\n            }\n\n            ItemStack cached = cache.get(i);\n\n            //ItemStack.EMPTY can be accidentally modified by other mods on any thread. This makes sure we ignore that.\n            if (actual == ItemStack.EMPTY && actual == cached)\n                continue;\n\n            if (!cached.isEmpty() && actual.isEmpty()) { // REMOVED\n                network.getItemStorageCache().remove(cached, cached.getCount(), true);\n\n                cache.set(i, ItemStack.EMPTY);\n            } else if (cached.isEmpty() && !actual.isEmpty()) { // ADDED\n                network.getItemStorageCache().add(actual, actual.getCount(), false, true);\n\n                cache.set(i, actual.copy());\n            } else if (!API.instance().getComparer().isEqualNoQuantity(cached, actual)) { // CHANGED\n                network.getItemStorageCache().remove(cached, cached.getCount(), true);\n                network.getItemStorageCache().add(actual, actual.getCount(), false, true);\n\n                cache.set(i, actual.copy());\n            } else if (cached.getCount() != actual.getCount()) { // COUNT_CHANGED\n                int delta = actual.getCount() - cached.getCount();\n\n                if (delta > 0) {\n                    network.getItemStorageCache().add(actual, delta, false, true);\n\n                    cached.grow(delta);\n                } else {\n                    network.getItemStorageCache().remove(actual, Math.abs(delta), true);\n\n                    cached.shrink(Math.abs(delta));\n                }\n            }\n        }\n        this.stored = stored;\n\n        if (cache.size() > handler.getSlots()) { // SHRUNK\n            for (int i = cache.size() - 1; i >= handler.getSlots(); --i) { // Reverse order for the remove call.\n                ItemStack cached = cache.get(i);\n\n                if (!cached.isEmpty()) {\n                    network.getItemStorageCache().remove(cached, cached.getCount(), true);\n                }\n\n                cache.remove(i);\n            }\n        }\n\n        network.getItemStorageCache().flush();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/externalstorage/ItemExternalStorageProvider.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.externalstorage;\n\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport com.refinedmods.refinedstorage.api.storage.IStorageProvider;\nimport com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorage;\nimport com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorageContext;\nimport com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorageProvider;\nimport com.refinedmods.refinedstorage.blockentity.InterfaceBlockEntity;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\n\nimport javax.annotation.Nonnull;\n\npublic class ItemExternalStorageProvider implements IExternalStorageProvider<ItemStack> {\n    @Override\n    public boolean canProvide(Level level, BlockPos pos, Direction direction) {\n        INetworkNode node = NetworkUtils.getNodeFromBlockEntity(level.getBlockEntity(pos));\n        if (node instanceof IStorageProvider) {\n            return false;\n        }\n        return LevelUtils.getItemHandler(level, pos, direction.getOpposite()) != null;\n    }\n\n    @Nonnull\n    @Override\n    public IExternalStorage<ItemStack> provide(IExternalStorageContext context, BlockEntity blockEntity, Direction direction) {\n        return new ItemExternalStorage(context, () -> {\n            Level level = blockEntity.getLevel();\n            if (level == null) {\n                return null;\n            }\n            return LevelUtils.getItemHandler(level, blockEntity.getBlockPos(), direction.getOpposite());\n        }, blockEntity instanceof InterfaceBlockEntity);\n    }\n\n    @Override\n    public int getPriority() {\n        return 0;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/tracker/FluidStorageTracker.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.tracker;\n\nimport com.refinedmods.refinedstorage.api.storage.tracker.IStorageTracker;\nimport com.refinedmods.refinedstorage.api.storage.tracker.StorageTrackerEntry;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.world.entity.player.Player;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class FluidStorageTracker implements IStorageTracker<FluidStack> {\n    private static final String NBT_STACK = \"Stack\";\n    private static final String NBT_NAME = \"Name\";\n    private static final String NBT_TIME = \"Time\";\n\n    private final Map<Key, StorageTrackerEntry> changes = new HashMap<>();\n    private final Runnable listener;\n\n    public FluidStorageTracker(Runnable listener) {\n        this.listener = listener;\n    }\n\n    @Override\n    public void changed(Player player, FluidStack stack) {\n        changes.put(new Key(stack), new StorageTrackerEntry(System.currentTimeMillis(), player.getName().getString()));\n\n        listener.run();\n    }\n\n    @Override\n    public StorageTrackerEntry get(FluidStack stack) {\n        return changes.get(new Key(stack));\n    }\n\n    @Override\n    public void readFromNbt(ListTag list) {\n        for (int i = 0; i < list.size(); ++i) {\n            CompoundTag tag = list.getCompound(i);\n\n            FluidStack stack = FluidStack.loadFluidStackFromNBT(tag.getCompound(NBT_STACK));\n\n            if (!stack.isEmpty()) {\n                changes.put(new Key(stack), new StorageTrackerEntry(tag.getLong(NBT_TIME), tag.getString(NBT_NAME)));\n            }\n        }\n    }\n\n    @Override\n    public ListTag serializeNbt() {\n        ListTag list = new ListTag();\n\n        for (Map.Entry<Key, StorageTrackerEntry> entry : changes.entrySet()) {\n            CompoundTag tag = new CompoundTag();\n\n            tag.putLong(NBT_TIME, entry.getValue().getTime());\n            tag.putString(NBT_NAME, entry.getValue().getName());\n            tag.put(NBT_STACK, entry.getKey().stack.writeToNBT(new CompoundTag()));\n\n            list.add(tag);\n        }\n\n        return list;\n    }\n\n    private static class Key {\n        private final FluidStack stack;\n\n        public Key(FluidStack stack) {\n            this.stack = stack;\n        }\n\n        @Override\n        public boolean equals(Object other) {\n            return other instanceof Key && API.instance().getComparer().isEqual(stack, ((Key) other).stack, IComparer.COMPARE_NBT);\n        }\n\n        @Override\n        public int hashCode() {\n            return API.instance().getFluidStackHashCode(stack);\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/tracker/ItemStorageTracker.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.tracker;\n\nimport com.refinedmods.refinedstorage.api.storage.tracker.IStorageTracker;\nimport com.refinedmods.refinedstorage.api.storage.tracker.StorageTrackerEntry;\nimport com.refinedmods.refinedstorage.util.ItemStackKey;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class ItemStorageTracker implements IStorageTracker<ItemStack> {\n    private static final String NBT_STACK = \"Stack\";\n    private static final String NBT_NAME = \"Name\";\n    private static final String NBT_TIME = \"Time\";\n\n    private final Map<ItemStackKey, StorageTrackerEntry> changes = new HashMap<>();\n    private final Runnable listener;\n\n    public ItemStorageTracker(Runnable listener) {\n        this.listener = listener;\n    }\n\n    @Override\n    public void changed(Player player, ItemStack stack) {\n        changes.put(new ItemStackKey(stack), new StorageTrackerEntry(System.currentTimeMillis(), player.getName().getString()));\n\n        listener.run();\n    }\n\n    @Override\n    public StorageTrackerEntry get(ItemStack stack) {\n        return changes.get(new ItemStackKey(stack));\n    }\n\n    @Override\n    public void readFromNbt(ListTag list) {\n        for (int i = 0; i < list.size(); ++i) {\n            CompoundTag tag = list.getCompound(i);\n\n            ItemStack stack = StackUtils.deserializeStackFromNbt(tag.getCompound(NBT_STACK));\n\n            if (!stack.isEmpty()) {\n                changes.put(new ItemStackKey(stack), new StorageTrackerEntry(tag.getLong(NBT_TIME), tag.getString(NBT_NAME)));\n            }\n        }\n    }\n\n    @Override\n    public ListTag serializeNbt() {\n        ListTag list = new ListTag();\n\n        for (Map.Entry<ItemStackKey, StorageTrackerEntry> entry : changes.entrySet()) {\n            CompoundTag tag = new CompoundTag();\n\n            tag.putLong(NBT_TIME, entry.getValue().getTime());\n            tag.putString(NBT_NAME, entry.getValue().getName());\n            tag.put(NBT_STACK, StackUtils.serializeStackToNbt(entry.getKey().getStack()));\n\n            list.add(tag);\n        }\n\n        return list;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/tracker/StorageTrackerManager.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.storage.tracker;\n\nimport com.refinedmods.refinedstorage.api.storage.StorageType;\nimport com.refinedmods.refinedstorage.api.storage.tracker.IStorageTracker;\nimport com.refinedmods.refinedstorage.api.storage.tracker.IStorageTrackerManager;\nimport com.refinedmods.refinedstorage.apiimpl.util.RSSavedData;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.nbt.Tag;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.UUID;\n\npublic class StorageTrackerManager extends RSSavedData implements IStorageTrackerManager {\n    public static final String NAME = \"refinedstorage_tracker\";\n\n    private static final String NBT_TRACKERS = \"Tracker\";\n    private static final String NBT_TRACKER_ID = \"Id\";\n    private static final String NBT_TRACKER_DATA = \"Data\";\n    private static final String NBT_TRACKER_TYPE = \"Type\";\n\n    private final Map<UUID, IStorageTracker<?>> trackers = new HashMap<>();\n\n    @Override\n    public void markForSaving() {\n        this.setDirty();\n    }\n\n    @Override\n    public IStorageTracker<?> getOrCreate(UUID uuid, StorageType type) {\n        IStorageTracker<?> tracker = trackers.get(uuid);\n\n        if (tracker == null) {\n            if (type == StorageType.ITEM) {\n                tracker = new ItemStorageTracker(this::markForSaving);\n            } else if (type == StorageType.FLUID) {\n                tracker = new FluidStorageTracker(this::markForSaving);\n            }\n\n            trackers.put(uuid, tracker);\n        }\n\n        return tracker;\n    }\n\n    @Override\n    public void remove(UUID id) {\n        trackers.remove(id);\n    }\n\n    @Override\n    public void load(CompoundTag nbt) {\n        if (nbt.contains(NBT_TRACKERS)) {\n            ListTag trackerTags = nbt.getList(NBT_TRACKERS, Tag.TAG_COMPOUND);\n\n            for (int i = 0; i < trackerTags.size(); ++i) {\n                CompoundTag trackerTag = trackerTags.getCompound(i);\n\n                UUID id = trackerTag.getUUID(NBT_TRACKER_ID);\n                ListTag data = trackerTag.getList(NBT_TRACKER_DATA, Tag.TAG_COMPOUND);\n                StorageType type = StorageType.values()[trackerTag.getInt(NBT_TRACKER_TYPE)];\n\n                IStorageTracker<?> tracker = getOrCreate(id, type);\n                tracker.readFromNbt(data);\n            }\n        }\n    }\n\n    @Override\n    public CompoundTag save(CompoundTag compound) {\n        ListTag trackerListTag = new ListTag();\n\n        for (Map.Entry<UUID, IStorageTracker<?>> entry : trackers.entrySet()) {\n            CompoundTag trackerTag = new CompoundTag();\n\n            trackerTag.putUUID(NBT_TRACKER_ID, entry.getKey());\n            trackerTag.put(NBT_TRACKER_DATA, entry.getValue().serializeNbt());\n            trackerTag.putInt(NBT_TRACKER_TYPE, entry.getValue() instanceof ItemStorageTracker ? StorageType.ITEM.ordinal() : StorageType.FLUID.ordinal());\n\n            trackerListTag.add(trackerTag);\n        }\n\n        compound.put(NBT_TRACKERS, trackerListTag);\n\n        return compound;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/util/Comparer.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.util;\n\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nonnull;\n\npublic class Comparer implements IComparer {\n    @Override\n    public boolean isEqual(@Nonnull ItemStack left, @Nonnull ItemStack right, int flags) {\n        if (left.isEmpty() && right.isEmpty()) {\n            return true;\n        }\n\n        if (!ItemStack.isSameItem(left, right)) {\n            return false;\n        }\n\n        if ((flags & COMPARE_NBT) == COMPARE_NBT && !ItemStack.isSameItemSameTags(left, right)) {\n            return false;\n        }\n\n        if ((flags & COMPARE_QUANTITY) == COMPARE_QUANTITY && left.getCount() != right.getCount()) {\n            return false;\n        }\n\n        return true;\n    }\n\n    @Override\n    public boolean isEqual(@Nonnull FluidStack left, @Nonnull FluidStack right, int flags) {\n        if (left.isEmpty() && right.isEmpty()) {\n            return true;\n        }\n\n        if (left.getFluid() != right.getFluid()) {\n            return false;\n        }\n\n        if ((flags & COMPARE_NBT) == COMPARE_NBT && !FluidStack.areFluidStackTagsEqual(left, right)) {\n            return false;\n        }\n\n        if ((flags & COMPARE_QUANTITY) == COMPARE_QUANTITY && left.getAmount() != right.getAmount()) {\n            return false;\n        }\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/util/FluidFilter.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.util;\n\nimport com.refinedmods.refinedstorage.api.util.IFilter;\nimport net.neoforged.neoforge.fluids.FluidStack;\n\npublic class FluidFilter implements IFilter {\n    private final FluidStack stack;\n    private final int compare;\n    private final int mode;\n    private final boolean modFilter;\n\n    public FluidFilter(FluidStack stack, int compare, int mode, boolean modFilter) {\n        this.stack = stack;\n        this.compare = compare;\n        this.mode = mode;\n        this.modFilter = modFilter;\n    }\n\n    @Override\n    public Object getStack() {\n        return stack;\n    }\n\n    @Override\n    public int getCompare() {\n        return compare;\n    }\n\n    @Override\n    public int getMode() {\n        return mode;\n    }\n\n    @Override\n    public boolean isModFilter() {\n        return modFilter;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/util/FluidStackList.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.util;\n\nimport com.google.common.collect.ArrayListMultimap;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.api.util.StackListEntry;\nimport com.refinedmods.refinedstorage.api.util.StackListResult;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport net.minecraft.world.level.material.Fluid;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.UUID;\n\npublic class FluidStackList implements IStackList<FluidStack> {\n    private final ArrayListMultimap<Fluid, StackListEntry<FluidStack>> stacks = ArrayListMultimap.create();\n    private final Map<UUID, FluidStack> index = new HashMap<>();\n\n    public FluidStackList() {\n    }\n\n    public FluidStackList(Iterable<FluidStack> stacks) {\n        for (FluidStack stack : stacks) {\n            add(stack);\n        }\n    }\n\n    @Override\n    public StackListResult<FluidStack> add(@Nonnull FluidStack stack, int size) {\n        if (stack.isEmpty() || size <= 0) {\n            throw new IllegalArgumentException(\"Cannot accept empty stack\");\n        }\n\n        for (StackListEntry<FluidStack> entry : stacks.get(stack.getFluid())) {\n            FluidStack otherStack = entry.getStack();\n\n            if (stack.isFluidEqual(otherStack)) {\n                if ((long) otherStack.getAmount() + (long) size > Integer.MAX_VALUE) {\n                    otherStack.setAmount(Integer.MAX_VALUE);\n                } else {\n                    otherStack.grow(size);\n                }\n\n                return new StackListResult<>(otherStack, entry.getId(), size);\n            }\n        }\n\n        FluidStack newStack = stack.copy();\n        newStack.setAmount(size);\n\n        StackListEntry<FluidStack> newEntry = new StackListEntry<>(newStack);\n\n        stacks.put(newStack.getFluid(), newEntry);\n        index.put(newEntry.getId(), newEntry.getStack());\n\n        return new StackListResult<>(newStack, newEntry.getId(), size);\n    }\n\n    @Override\n    public StackListResult<FluidStack> add(@Nonnull FluidStack stack) {\n        return add(stack, stack.getAmount());\n    }\n\n    @Override\n    public StackListResult<FluidStack> remove(@Nonnull FluidStack stack, int size) {\n        for (StackListEntry<FluidStack> entry : stacks.get(stack.getFluid())) {\n            FluidStack otherStack = entry.getStack();\n\n            if (stack.isFluidEqual(otherStack)) {\n                if (otherStack.getAmount() - size <= 0) {\n                    stacks.remove(otherStack.getFluid(), entry);\n                    index.remove(entry.getId());\n\n                    return new StackListResult<>(otherStack, entry.getId(), -otherStack.getAmount());\n                } else {\n                    otherStack.shrink(size);\n\n                    return new StackListResult<>(otherStack, entry.getId(), -size);\n                }\n            }\n        }\n\n        return null;\n    }\n\n    @Override\n    public StackListResult<FluidStack> remove(@Nonnull FluidStack stack) {\n        return remove(stack, stack.getAmount());\n    }\n\n    @Override\n    public int getCount(@Nonnull FluidStack stack, int flags) {\n        FluidStack found = get(stack, flags);\n        if (found == null) {\n            return 0;\n        }\n\n        return found.getAmount();\n    }\n\n    @Override\n    @Nullable\n    public FluidStack get(@Nonnull FluidStack stack, int flags) {\n        for (StackListEntry<FluidStack> entry : stacks.get(stack.getFluid())) {\n            FluidStack otherStack = entry.getStack();\n\n            if (API.instance().getComparer().isEqual(otherStack, stack, flags)) {\n                return otherStack;\n            }\n        }\n\n        return null;\n    }\n\n    @Nullable\n    @Override\n    public StackListEntry<FluidStack> getEntry(@Nonnull FluidStack stack, int flags) {\n        for (StackListEntry<FluidStack> entry : stacks.get(stack.getFluid())) {\n            FluidStack otherStack = entry.getStack();\n\n            if (API.instance().getComparer().isEqual(otherStack, stack, flags)) {\n                return entry;\n            }\n        }\n\n        return null;\n    }\n\n    @Override\n    @Nullable\n    public FluidStack get(UUID id) {\n        return index.get(id);\n    }\n\n    @Override\n    public void clear() {\n        stacks.clear();\n        index.clear();\n    }\n\n    @Override\n    public boolean isEmpty() {\n        return stacks.isEmpty();\n    }\n\n    @Nonnull\n    @Override\n    public Collection<StackListEntry<FluidStack>> getStacks() {\n        return stacks.values();\n    }\n\n    @Override\n    @Nonnull\n    public Collection<StackListEntry<FluidStack>> getStacks(@Nonnull FluidStack stack) {\n        return stacks.get(stack.getFluid());\n    }\n\n    @Override\n    @Nonnull\n    public IStackList<FluidStack> copy() {\n        FluidStackList list = new FluidStackList();\n\n        for (StackListEntry<FluidStack> entry : stacks.values()) {\n            FluidStack newStack = entry.getStack().copy();\n\n            list.stacks.put(entry.getStack().getFluid(), new StackListEntry<>(entry.getId(), newStack));\n            list.index.put(entry.getId(), newStack);\n        }\n\n        return list;\n    }\n\n    @Override\n    public int size() {\n        return stacks.size();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/util/ItemFilter.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.util;\n\nimport com.refinedmods.refinedstorage.api.util.IFilter;\nimport net.minecraft.world.item.ItemStack;\n\npublic class ItemFilter implements IFilter {\n    private final ItemStack stack;\n    private final int compare;\n    private final int mode;\n    private final boolean modFilter;\n\n    public ItemFilter(ItemStack stack, int compare, int mode, boolean modFilter) {\n        this.stack = stack;\n        this.compare = compare;\n        this.mode = mode;\n        this.modFilter = modFilter;\n    }\n\n    @Override\n    public Object getStack() {\n        return stack;\n    }\n\n    @Override\n    public int getCompare() {\n        return compare;\n    }\n\n    @Override\n    public int getMode() {\n        return mode;\n    }\n\n    @Override\n    public boolean isModFilter() {\n        return modFilter;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/util/ItemStackList.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.util;\n\nimport com.google.common.collect.ArrayListMultimap;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.api.util.StackListEntry;\nimport com.refinedmods.refinedstorage.api.util.StackListResult;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.UUID;\n\npublic class ItemStackList implements IStackList<ItemStack> {\n    private final ArrayListMultimap<Item, StackListEntry<ItemStack>> stacks = ArrayListMultimap.create();\n    private final Map<UUID, ItemStack> index = new HashMap<>();\n\n    public ItemStackList() {\n    }\n\n    public ItemStackList(Iterable<ItemStack> stacks) {\n        for (ItemStack stack : stacks) {\n            add(stack);\n        }\n    }\n\n    @Override\n    public StackListResult<ItemStack> add(@Nonnull ItemStack stack, int size) {\n        if (stack.isEmpty() || size <= 0) {\n            throw new IllegalArgumentException(\"Cannot accept empty stack\");\n        }\n\n        for (StackListEntry<ItemStack> entry : stacks.get(stack.getItem())) {\n            ItemStack otherStack = entry.getStack();\n\n            if (API.instance().getComparer().isEqualNoQuantity(otherStack, stack)) {\n                if ((long) otherStack.getCount() + (long) size > Integer.MAX_VALUE) {\n                    otherStack.setCount(Integer.MAX_VALUE);\n                } else {\n                    otherStack.grow(size);\n                }\n\n                return new StackListResult<>(otherStack, entry.getId(), size);\n            }\n        }\n\n        StackListEntry<ItemStack> newEntry = new StackListEntry<>(ItemHandlerHelper.copyStackWithSize(stack, size));\n\n        stacks.put(stack.getItem(), newEntry);\n        index.put(newEntry.getId(), newEntry.getStack());\n\n        return new StackListResult<>(newEntry.getStack(), newEntry.getId(), size);\n    }\n\n    @Override\n    public StackListResult<ItemStack> add(@Nonnull ItemStack stack) {\n        return add(stack, stack.getCount());\n    }\n\n    @Override\n    public StackListResult<ItemStack> remove(@Nonnull ItemStack stack, int size) {\n        for (StackListEntry<ItemStack> entry : stacks.get(stack.getItem())) {\n            ItemStack otherStack = entry.getStack();\n\n            if (API.instance().getComparer().isEqualNoQuantity(otherStack, stack)) {\n                if (otherStack.getCount() - size <= 0) {\n                    stacks.remove(otherStack.getItem(), entry);\n                    index.remove(entry.getId());\n\n                    return new StackListResult<>(otherStack, entry.getId(), -otherStack.getCount());\n                } else {\n                    otherStack.shrink(size);\n\n                    return new StackListResult<>(otherStack, entry.getId(), -size);\n                }\n            }\n        }\n\n        return null;\n    }\n\n    @Override\n    public StackListResult<ItemStack> remove(@Nonnull ItemStack stack) {\n        return remove(stack, stack.getCount());\n    }\n\n    @Override\n    public int getCount(@Nonnull ItemStack stack, int flags) {\n        ItemStack found = get(stack, flags);\n        if (found == null) {\n            return 0;\n        }\n\n        return found.getCount();\n    }\n\n    @Override\n    @Nullable\n    public ItemStack get(@Nonnull ItemStack stack, int flags) {\n        for (StackListEntry<ItemStack> entry : stacks.get(stack.getItem())) {\n            ItemStack otherStack = entry.getStack();\n\n            if (API.instance().getComparer().isEqual(otherStack, stack, flags)) {\n                return otherStack;\n            }\n        }\n\n        return null;\n    }\n\n    @Nullable\n    @Override\n    public StackListEntry<ItemStack> getEntry(@Nonnull ItemStack stack, int flags) {\n        for (StackListEntry<ItemStack> entry : stacks.get(stack.getItem())) {\n            ItemStack otherStack = entry.getStack();\n\n            if (API.instance().getComparer().isEqual(otherStack, stack, flags)) {\n                return entry;\n            }\n        }\n\n        return null;\n    }\n\n    @Override\n    @Nullable\n    public ItemStack get(UUID id) {\n        return index.get(id);\n    }\n\n    @Override\n    public void clear() {\n        stacks.clear();\n        index.clear();\n    }\n\n    @Override\n    public boolean isEmpty() {\n        return stacks.isEmpty();\n    }\n\n    @Nonnull\n    @Override\n    public Collection<StackListEntry<ItemStack>> getStacks() {\n        return stacks.values();\n    }\n\n    @Override\n    @Nonnull\n    public Collection<StackListEntry<ItemStack>> getStacks(@Nonnull ItemStack stack) {\n        return stacks.get(stack.getItem());\n    }\n\n    @Override\n    @Nonnull\n    public IStackList<ItemStack> copy() {\n        ItemStackList list = new ItemStackList();\n\n        for (StackListEntry<ItemStack> entry : stacks.values()) {\n            ItemStack newStack = entry.getStack().copy();\n\n            list.stacks.put(entry.getStack().getItem(), new StackListEntry<>(entry.getId(), newStack));\n            list.index.put(entry.getId(), newStack);\n        }\n\n        return list;\n    }\n\n    @Override\n    public int size() {\n        return stacks.size();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/util/QuantityFormatter.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.util;\n\nimport com.refinedmods.refinedstorage.api.util.IQuantityFormatter;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport java.math.RoundingMode;\nimport java.text.DecimalFormat;\nimport java.text.DecimalFormatSymbols;\nimport java.util.Locale;\nimport net.neoforged.neoforge.fluids.FluidType;\n\npublic class QuantityFormatter implements IQuantityFormatter {\n    private final DecimalFormat formatterWithUnits = new DecimalFormat(\"####0.#\", DecimalFormatSymbols.getInstance(Locale.US));\n    private final DecimalFormat formatter = new DecimalFormat(\"#,###\", DecimalFormatSymbols.getInstance(Locale.US));\n    private final DecimalFormat bucketFormatter = new DecimalFormat(\"####0.###\", DecimalFormatSymbols.getInstance(Locale.US));\n\n    public QuantityFormatter() {\n        formatterWithUnits.setRoundingMode(RoundingMode.DOWN);\n    }\n\n    @Override\n    public String formatWithUnits(int qty) {\n        return formatWithUnits((long) qty);\n    }\n\n    @Override\n    public String formatWithUnits(long qty) {\n        if (qty >= 1_000_000_000) {\n            return formatterWithUnits.format(Math.round((float) qty / 1_000_000_000)) + \"B\";\n        } else if (qty >= 1_000_000) {\n            float qtyShort = (float) qty / 1_000_000F;\n\n            if (qty >= 100_000_000) {\n                qtyShort = Math.round(qtyShort); // XXX.XM looks weird.\n            }\n\n            return formatterWithUnits.format(qtyShort) + \"M\";\n        } else if (qty >= 1000) {\n            float qtyShort = (float) qty / 1000F;\n\n            if (qty >= 100_000) {\n                qtyShort = Math.round(qtyShort); // XXX.XK looks weird.\n            }\n\n            return formatterWithUnits.format(qtyShort) + \"K\";\n        }\n\n        return String.valueOf(qty);\n    }\n\n    @Override\n    public String format(int qty) {\n        return formatter.format(qty);\n    }\n\n    @Override\n    public String format(long qty) {\n        return formatter.format(qty);\n    }\n\n    @Override\n    public String formatInBucketForm(int qty) {\n        return bucketFormatter.format((float) qty / (float) FluidType.BUCKET_VOLUME) + \" B\";\n    }\n\n    @Override\n    public String formatInBucketFormWithOnlyTrailingDigitsIfZero(int qty) {\n        float amountRaw = ((float) qty / (float) FluidType.BUCKET_VOLUME);\n        int amount = (int) amountRaw;\n\n        if (amount >= 1) {\n            return API.instance().getQuantityFormatter().formatWithUnits(amount);\n        } else {\n            return String.format(\"%.1f\", amountRaw);\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/apiimpl/util/RSSavedData.java",
    "content": "package com.refinedmods.refinedstorage.apiimpl.util;\n\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.NbtIo;\nimport net.minecraft.nbt.NbtUtils;\nimport net.minecraft.world.level.saveddata.SavedData;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\n\nimport java.io.File;\nimport java.io.IOException;\n\n\npublic abstract class RSSavedData extends SavedData {\n    private final Logger LOGGER = LogManager.getLogger(RSSavedData.class);\n\n    public abstract void load(CompoundTag nbt);\n\n    @Override\n    public abstract CompoundTag save(CompoundTag compound);\n\n    @Override\n    public void save(File file) {\n        // @Volatile Mostly Copied from SavedData\n        if (this.isDirty()) {\n            File tempFile = file.toPath().getParent().resolve(file.getName() + \".temp\").toFile();\n\n            CompoundTag tag = new CompoundTag();\n            tag.put(\"data\", this.save(new CompoundTag()));\n            NbtUtils.addCurrentDataVersion(tag);\n\n            try {\n                NbtIo.writeCompressed(tag, tempFile.toPath());\n                if (file.exists()) {\n                    if (!file.delete()) {\n                        LOGGER.error(\"Failed to delete \" + file.getName());\n                    }\n                }\n                if (!tempFile.renameTo(file)) {\n                    LOGGER.error(\"Failed to rename \" + tempFile.getName());\n                }\n            } catch (IOException e) {\n                LOGGER.error(\"Could not save data {}\", this, e);\n            }\n            this.setDirty(false);\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/BaseBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.Block;\nimport net.minecraft.world.level.block.Rotation;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.level.block.state.StateDefinition;\n\npublic abstract class BaseBlock extends Block {\n    protected BaseBlock(Properties properties) {\n        super(properties);\n    }\n\n    public BlockDirection getDirection() {\n        return BlockDirection.NONE;\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public BlockState rotate(BlockState state, Rotation rot) {\n        BlockDirection dir = getDirection();\n        if (dir != BlockDirection.NONE) {\n            Direction newDirection = dir.cycle(state.getValue(dir.getProperty()));\n\n            return state.setValue(dir.getProperty(), newDirection);\n        }\n\n        return super.rotate(state, rot);\n    }\n\n    protected void onDirectionChanged(Level level, BlockPos pos, Direction newDirection) {\n        // NO OP\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {\n        super.onRemove(state, level, pos, newState, isMoving);\n\n        checkIfDirectionHasChanged(state, level, pos, newState);\n    }\n\n    protected void checkIfDirectionHasChanged(BlockState state, Level level, BlockPos pos, BlockState newState) {\n        if (getDirection() != BlockDirection.NONE &&\n            state.getBlock() == newState.getBlock() &&\n            state.getValue(getDirection().getProperty()) != newState.getValue(getDirection().getProperty())) {\n            onDirectionChanged(level, pos, newState.getValue(getDirection().getProperty()));\n        }\n    }\n\n    @Override\n    protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {\n        super.createBlockStateDefinition(builder);\n\n        BlockDirection dir = getDirection();\n        if (dir != BlockDirection.NONE) {\n            builder.add(dir.getProperty());\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/BlockDirection.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.util.DirectionUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.world.entity.LivingEntity;\nimport net.minecraft.world.level.block.state.properties.DirectionProperty;\n\nimport java.util.Arrays;\n\npublic enum BlockDirection {\n    NONE(),\n    ANY(Direction.values()),\n    ANY_FACE_PLAYER(Direction.values()),\n    HORIZONTAL(Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST);\n\n    private final DirectionProperty property;\n\n    BlockDirection(Direction... allowed) {\n        this.property = DirectionProperty.create(\"direction\", Arrays.asList(allowed));\n    }\n\n    public DirectionProperty getProperty() {\n        return property;\n    }\n\n    public Direction getFrom(Direction facing, BlockPos pos, LivingEntity entity) {\n        switch (this) {\n            case ANY:\n                return facing.getOpposite();\n            case ANY_FACE_PLAYER:\n                return DirectionUtils.getFacingFromEntity(pos, entity);\n            case HORIZONTAL:\n                return entity.getDirection().getOpposite();\n            default:\n                throw new IllegalStateException(\"Unknown direction type\");\n        }\n    }\n\n    public Direction cycle(Direction previous) {\n        switch (this) {\n            case ANY:\n            case ANY_FACE_PLAYER:\n                return previous.ordinal() + 1 >= Direction.values().length ? Direction.values()[0] : Direction.values()[previous.ordinal() + 1];\n            case HORIZONTAL:\n                return previous.getCounterClockWise();\n            default:\n                throw new IllegalStateException(\"Unknown direction type\");\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/BlockListener.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport net.neoforged.bus.api.SubscribeEvent;\nimport net.neoforged.neoforge.event.entity.player.PlayerEvent;\n\npublic class BlockListener {\n    // Allow break without tool\n    @SubscribeEvent\n    public void onHarvestCheck(PlayerEvent.HarvestCheck e) {\n        if (e.getTargetBlock().getBlock() instanceof BaseBlock) {\n            e.setCanHarvest(true);\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/CableBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.api.network.node.ICoverable;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.Cover;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverType;\nimport com.refinedmods.refinedstorage.block.shape.ShapeCache;\nimport com.refinedmods.refinedstorage.blockentity.CableBlockEntity;\nimport com.refinedmods.refinedstorage.render.ConstantsCable;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.context.BlockPlaceContext;\nimport net.minecraft.world.level.BlockGetter;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.LevelAccessor;\nimport net.minecraft.world.level.block.Block;\nimport net.minecraft.world.level.block.Rotation;\nimport net.minecraft.world.level.block.SimpleWaterloggedBlock;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.level.block.state.StateDefinition;\nimport net.minecraft.world.level.block.state.properties.BooleanProperty;\nimport net.minecraft.world.level.material.Fluid;\nimport net.minecraft.world.level.material.FluidState;\nimport net.minecraft.world.level.material.Fluids;\nimport net.minecraft.world.level.pathfinder.PathComputationType;\nimport net.minecraft.world.phys.shapes.CollisionContext;\nimport net.minecraft.world.phys.shapes.Shapes;\nimport net.minecraft.world.phys.shapes.VoxelShape;\n\nimport javax.annotation.Nullable;\nimport java.util.Optional;\n\npublic class CableBlock extends NetworkNodeBlock implements SimpleWaterloggedBlock {\n    protected static final VoxelShape HOLDER_NORTH = box(7, 7, 2, 9, 9, 6);\n    protected static final VoxelShape HOLDER_EAST = box(10, 7, 7, 14, 9, 9);\n    protected static final VoxelShape HOLDER_SOUTH = box(7, 7, 10, 9, 9, 14);\n    protected static final VoxelShape HOLDER_WEST = box(2, 7, 7, 6, 9, 9);\n    protected static final VoxelShape HOLDER_UP = box(7, 10, 7, 9, 14, 9);\n    protected static final VoxelShape HOLDER_DOWN = box(7, 2, 7, 9, 6, 9);\n    private static final BooleanProperty NORTH = BooleanProperty.create(\"north\");\n    private static final BooleanProperty EAST = BooleanProperty.create(\"east\");\n    private static final BooleanProperty SOUTH = BooleanProperty.create(\"south\");\n    private static final BooleanProperty WEST = BooleanProperty.create(\"west\");\n    private static final BooleanProperty UP = BooleanProperty.create(\"up\");\n    private static final BooleanProperty DOWN = BooleanProperty.create(\"down\");\n    private static final BooleanProperty WATERLOGGED = BooleanProperty.create(\"waterlogged\");\n    private static final VoxelShape SHAPE_CORE = box(6, 6, 6, 10, 10, 10);\n    private static final VoxelShape SHAPE_NORTH = box(6, 6, 0, 10, 10, 6);\n    private static final VoxelShape SHAPE_EAST = box(10, 6, 6, 16, 10, 10);\n    private static final VoxelShape SHAPE_SOUTH = box(6, 6, 10, 10, 10, 16);\n    private static final VoxelShape SHAPE_WEST = box(0, 6, 6, 6, 10, 10);\n    private static final VoxelShape SHAPE_UP = box(6, 10, 6, 10, 16, 10);\n    private static final VoxelShape SHAPE_DOWN = box(6, 0, 6, 10, 6, 10);\n\n    protected CableBlock(Properties props) {\n        super(props);\n        this.registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false));\n    }\n\n    public CableBlock() {\n        super(BlockUtils.DEFAULT_GLASS_PROPERTIES);\n\n        this.registerDefaultState(defaultBlockState().setValue(NORTH, false).setValue(EAST, false).setValue(SOUTH, false).setValue(WEST, false).setValue(UP, false).setValue(DOWN, false).setValue(WATERLOGGED, false));\n    }\n\n    protected static VoxelShape getCableShape(BlockState state) {\n        VoxelShape shape = SHAPE_CORE;\n\n        if (Boolean.TRUE.equals(state.getValue(NORTH))) {\n            shape = Shapes.or(shape, SHAPE_NORTH);\n        }\n\n        if (Boolean.TRUE.equals(state.getValue(EAST))) {\n            shape = Shapes.or(shape, SHAPE_EAST);\n        }\n\n        if (Boolean.TRUE.equals(state.getValue(SOUTH))) {\n            shape = Shapes.or(shape, SHAPE_SOUTH);\n        }\n\n        if (Boolean.TRUE.equals(state.getValue(WEST))) {\n            shape = Shapes.or(shape, SHAPE_WEST);\n        }\n\n        if (Boolean.TRUE.equals(state.getValue(UP))) {\n            shape = Shapes.or(shape, SHAPE_UP);\n        }\n\n        if (Boolean.TRUE.equals(state.getValue(DOWN))) {\n            shape = Shapes.or(shape, SHAPE_DOWN);\n        }\n\n        return shape;\n    }\n\n    public static boolean hasVisualConnectionOnSide(BlockState state, Direction direction) {\n        switch (direction) {\n            case DOWN:\n                return state.getValue(DOWN);\n            case UP:\n                return state.getValue(UP);\n            case NORTH:\n                return state.getValue(NORTH);\n            case SOUTH:\n                return state.getValue(SOUTH);\n            case WEST:\n                return state.getValue(WEST);\n            case EAST:\n                return state.getValue(EAST);\n        }\n        return false;\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public BlockState updateShape(BlockState state, Direction dir, BlockState facingState, LevelAccessor world, BlockPos pos, BlockPos facingPos) {\n        return getState(state, world, pos);\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public boolean isPathfindable(BlockState state, BlockGetter worldIn, BlockPos pos, PathComputationType type) {\n        return false;\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext ctx) {\n        return ConstantsCable.addCoverVoxelShapes(ShapeCache.getOrCreate(state, CableBlock::getCableShape), world, pos);\n    }\n\n    @Override\n    protected void onDirectionChanged(Level level, BlockPos pos, Direction newDirection) {\n        // rotate() in BaseBlock \"stupidly\" changes the direction without checking if our cable connections are still valid.\n        // You'd expect that cable connections are not changing when simply changing the direction.\n        // But they need to. For example, when rotating a constructor to connect to a neighboring cable, the connection to that neighbor\n        // needs to be removed as otherwise the \"holder\" of the constructor will conflict with the cable connection.\n        // This is already checked in hasNode().\n        // But since rotate() doesn't invalidate that connection, we need to do it here.\n        // Ideally, this code would be in rotate(). But rotate() doesn't have any data about the position and world, so we need to do it here.\n        level.setBlockAndUpdate(pos, getState(level.getBlockState(pos), level, pos));\n\n\n        //when rotating skip rotations blocked by covers\n        BlockDirection dir = getDirection();\n        if (dir != BlockDirection.NONE) {\n            if (isSideCovered(level.getBlockEntity(pos), newDirection)) {\n                BlockState newState = rotate(level.getBlockState(pos), Rotation.CLOCKWISE_90);\n                level.setBlockAndUpdate(pos, newState);\n            }\n        }\n\n        super.onDirectionChanged(level, pos, newDirection);\n    }\n\n    @Override\n    public void neighborChanged(BlockState state, Level level, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) {\n        super.neighborChanged(state, level, pos, blockIn, fromPos, isMoving);\n        level.setBlockAndUpdate(pos, getState(level.getBlockState(pos), level, pos));\n    }\n\n    @Nullable\n    @Override\n    public BlockState getStateForPlacement(BlockPlaceContext ctx) {\n        FluidState fluidState = ctx.getLevel().getFluidState(ctx.getClickedPos());\n        return getState(defaultBlockState().setValue(WATERLOGGED, fluidState.getType() == Fluids.WATER), ctx.getLevel(), ctx.getClickedPos());\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public FluidState getFluidState(BlockState state) {\n        return Boolean.TRUE.equals(state.getValue(WATERLOGGED)) ? Fluids.WATER.getSource(false) : super.getFluidState(state);\n    }\n\n    @Override\n    public boolean placeLiquid(LevelAccessor world, BlockPos pos, BlockState state, FluidState fluidState) {\n        return SimpleWaterloggedBlock.super.placeLiquid(world, pos, state, fluidState);\n    }\n\n    @Override\n    public boolean canPlaceLiquid(Player player, BlockGetter world, BlockPos pos, BlockState state, Fluid fluid) {\n        return SimpleWaterloggedBlock.super.canPlaceLiquid(player, world, pos, state, fluid);\n    }\n\n    private boolean hasNodeConnection(LevelAccessor level, BlockPos pos, BlockState state, Direction direction) {\n        // Prevent the \"holder\" of a cable block conflicting with a cable connection.\n        if (getDirection() != BlockDirection.NONE && state.getValue(getDirection().getProperty()).getOpposite() == direction) {\n            return false;\n        }\n\n        BlockEntity blockEntity = level.getBlockEntity(pos);\n        if (blockEntity == null) {\n            return false;\n        }\n\n        return level.getBlockEntity(pos) instanceof INetworkNodeProxy\n                && !isSideCovered(blockEntity, direction)\n                && !isSideCovered(level.getBlockEntity(pos.relative(direction)), direction.getOpposite());\n    }\n\n    private boolean isSideCovered(BlockEntity blockEntity, Direction direction) {\n        if (blockEntity == null) {\n            return false;\n        }\n\n        INetworkNode node = blockEntity instanceof INetworkNodeProxy<?> proxy ? proxy.getNode() : null;\n\n        if (node instanceof ICoverable coverable) {\n            Cover cover = coverable.getCoverManager().getCover(direction);\n            if (cover == null) {\n                return false;\n            } else {\n                return cover.getType() == CoverType.NORMAL;\n            }\n        }\n\n        return false;\n    }\n\n    private BlockState getState(BlockState currentState, LevelAccessor level, BlockPos pos) {\n        boolean north = hasNodeConnection(level, pos.relative(Direction.NORTH), currentState, Direction.SOUTH);\n        boolean east = hasNodeConnection(level, pos.relative(Direction.EAST), currentState, Direction.WEST);\n        boolean south = hasNodeConnection(level, pos.relative(Direction.SOUTH), currentState, Direction.NORTH);\n        boolean west = hasNodeConnection(level, pos.relative(Direction.WEST), currentState, Direction.EAST);\n        boolean up = hasNodeConnection(level, pos.relative(Direction.UP), currentState, Direction.DOWN);\n        boolean down = hasNodeConnection(level, pos.relative(Direction.DOWN), currentState, Direction.UP);\n\n        return currentState\n                .setValue(NORTH, north)\n                .setValue(EAST, east)\n                .setValue(SOUTH, south)\n                .setValue(WEST, west)\n                .setValue(UP, up)\n                .setValue(DOWN, down);\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new CableBlockEntity(pos, state);\n    }\n\n    @Override\n    protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {\n        super.createBlockStateDefinition(builder);\n\n        builder.add(NORTH, EAST, SOUTH, WEST, UP, DOWN, WATERLOGGED);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/ColoredNetworkBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\n\npublic abstract class ColoredNetworkBlock extends NetworkNodeBlock {\n    public ColoredNetworkBlock(Properties props) {\n        super(props);\n    }\n\n    // Don't do block drops if we change the color.\n    @Override\n    public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {\n        if (state.getBlock().getClass().equals(newState.getBlock().getClass())) {\n            checkIfDirectionHasChanged(state, level, pos, newState);\n        } else {\n            super.onRemove(state, level, pos, newState, isMoving);\n        }\n    }\n}\n\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/ConstructorBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.block.shape.ShapeCache;\nimport com.refinedmods.refinedstorage.container.ConstructorContainerMenu;\nimport com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider;\nimport com.refinedmods.refinedstorage.render.ConstantsCable;\nimport com.refinedmods.refinedstorage.blockentity.ConstructorBlockEntity;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.CollisionUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\n\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.level.BlockGetter;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.BlockHitResult;\nimport net.minecraft.world.phys.shapes.CollisionContext;\nimport net.minecraft.world.phys.shapes.Shapes;\nimport net.minecraft.world.phys.shapes.VoxelShape;\n\npublic class ConstructorBlock extends CableBlock {\n    private static final VoxelShape HEAD_NORTH = Shapes.or(box(2, 2, 0, 14, 14, 2), HOLDER_NORTH);\n    private static final VoxelShape HEAD_EAST = Shapes.or(box(14, 2, 2, 16, 14, 14), HOLDER_EAST);\n    private static final VoxelShape HEAD_SOUTH = Shapes.or(box(2, 2, 14, 14, 14, 16), HOLDER_SOUTH);\n    private static final VoxelShape HEAD_WEST = Shapes.or(box(0, 2, 2, 2, 14, 14), HOLDER_WEST);\n    private static final VoxelShape HEAD_DOWN = Shapes.or(box(2, 0, 2, 14, 2, 14), HOLDER_DOWN);\n    private static final VoxelShape HEAD_UP = Shapes.or(box(2, 14, 2, 14, 16, 14), HOLDER_UP);\n\n    public ConstructorBlock() {\n        super(BlockUtils.DEFAULT_GLASS_PROPERTIES);\n    }\n\n    @Override\n    public BlockDirection getDirection() {\n        return BlockDirection.ANY;\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new ConstructorBlockEntity(pos, state);\n    }\n\n    @Override\n    public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext ctx) {\n        return ConstantsCable.addCoverVoxelShapes(ShapeCache.getOrCreate(state, s -> {\n            VoxelShape shape = getCableShape(s);\n\n            shape = Shapes.or(shape, getHeadShape(s));\n\n            return shape;\n        }), world, pos);\n    }\n\n    private VoxelShape getHeadShape(BlockState state) {\n        Direction direction = state.getValue(getDirection().getProperty());\n\n        if (direction == Direction.NORTH) {\n            return HEAD_NORTH;\n        }\n\n        if (direction == Direction.EAST) {\n            return HEAD_EAST;\n        }\n\n        if (direction == Direction.SOUTH) {\n            return HEAD_SOUTH;\n        }\n\n        if (direction == Direction.WEST) {\n            return HEAD_WEST;\n        }\n\n        if (direction == Direction.UP) {\n            return HEAD_UP;\n        }\n\n        if (direction == Direction.DOWN) {\n            return HEAD_DOWN;\n        }\n\n        return Shapes.empty();\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {\n        if (!level.isClientSide && CollisionUtils.isInBounds(getHeadShape(state), pos, hit.getLocation())) {\n            return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu(\n                new BlockEntityMenuProvider<ConstructorBlockEntity>(\n                    Component.translatable(\"gui.refinedstorage.constructor\"),\n                    (blockEntity, windowId, inventory, p) -> new ConstructorContainerMenu(blockEntity, player, windowId),\n                    pos\n                ),\n                pos\n            ));\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n\n    @Override\n    public boolean hasConnectedState() {\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/ControllerBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.NetworkType;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.Network;\nimport com.refinedmods.refinedstorage.blockentity.ControllerBlockEntity;\nimport com.refinedmods.refinedstorage.container.ControllerContainerMenu;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.ColorMap;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.util.StringRepresentable;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.MenuProvider;\nimport net.minecraft.world.entity.LivingEntity;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.minecraft.world.item.DyeColor;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.Block;\nimport net.minecraft.world.level.block.EntityBlock;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.level.block.state.StateDefinition;\nimport net.minecraft.world.level.block.state.properties.EnumProperty;\nimport net.minecraft.world.phys.BlockHitResult;\nimport net.neoforged.neoforge.capabilities.Capabilities;\nimport net.neoforged.neoforge.energy.IEnergyStorage;\n\nimport javax.annotation.Nullable;\n\npublic class ControllerBlock extends BaseBlock implements EntityBlock {\n    public static final EnumProperty<EnergyType> ENERGY_TYPE = EnumProperty.create(\"energy_type\", EnergyType.class);\n    private final NetworkType type;\n\n    public ControllerBlock(NetworkType type) {\n        super(BlockUtils.DEFAULT_ROCK_PROPERTIES);\n\n        this.type = type;\n        this.registerDefaultState(getStateDefinition().any().setValue(ENERGY_TYPE, EnergyType.OFF));\n    }\n\n    @Override\n    protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {\n        super.createBlockStateDefinition(builder);\n\n        builder.add(ENERGY_TYPE);\n    }\n\n    public NetworkType getType() {\n        return type;\n    }\n\n    @Override\n    public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity entity, ItemStack stack) {\n        super.setPlacedBy(level, pos, state, entity, stack);\n\n        if (!level.isClientSide) {\n            IEnergyStorage energyFromStack = stack.getCapability(Capabilities.EnergyStorage.ITEM);\n            if (energyFromStack != null) {\n                IEnergyStorage energyFromBlockEntity = level.getCapability(Capabilities.EnergyStorage.BLOCK, pos, Direction.NORTH);\n                if (energyFromBlockEntity != null) {\n                     energyFromBlockEntity.receiveEnergy(energyFromStack.getEnergyStored(), false);\n                }\n            }\n        }\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public void neighborChanged(BlockState state, Level level, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) {\n        super.neighborChanged(state, level, pos, blockIn, fromPos, isMoving);\n\n        if (!level.isClientSide) {\n            INetwork network = API.instance().getNetworkManager((ServerLevel) level).getNetwork(pos);\n            if (network instanceof Network) {\n                ((Network) network).setRedstonePowered(level.hasNeighborSignal(pos));\n            }\n        }\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {\n        InteractionResult result = super.use(state, level, pos, player, hand, hit);\n        if (result != InteractionResult.PASS) {\n            return result;\n        }\n\n        ColorMap<Block, ControllerBlock> colorMap = type == NetworkType.CREATIVE ? RSBlocks.CREATIVE_CONTROLLER : RSBlocks.CONTROLLER;\n        DyeColor color = DyeColor.getColor(player.getItemInHand(hand));\n\n        if (color != null && !state.getBlock().equals(colorMap.get(color).get())) {\n            BlockState newState = colorMap.get(color).get().defaultBlockState().setValue(ENERGY_TYPE, state.getValue(ENERGY_TYPE));\n\n            return RSBlocks.CONTROLLER.setBlockState(newState, player.getItemInHand(hand), level, pos, player);\n        }\n\n        if (!level.isClientSide) {\n            return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu(\n                new MenuProvider() {\n                    @Override\n                    public Component getDisplayName() {\n                        return Component.translatable(\"gui.refinedstorage.\" + (ControllerBlock.this.getType() == NetworkType.CREATIVE ? \"creative_\" : \"\") + \"controller\");\n                    }\n\n                    @Override\n                    public AbstractContainerMenu createMenu(int i, Inventory playerInventory, Player player) {\n                        return new ControllerContainerMenu((ControllerBlockEntity) level.getBlockEntity(pos), player, i);\n                    }\n                },\n                pos\n            ));\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n\n    @Override\n    public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {\n        if (newState.getBlock() instanceof ControllerBlock) {\n            return;\n        }\n        super.onRemove(state, level, pos, newState, isMoving);\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new ControllerBlockEntity(type, pos, state);\n    }\n\n    public enum EnergyType implements StringRepresentable {\n        OFF(\"off\"),\n        NEARLY_OFF(\"nearly_off\"),\n        NEARLY_ON(\"nearly_on\"),\n        ON(\"on\");\n\n        private final String name;\n\n        EnergyType(String name) {\n            this.name = name;\n        }\n\n        @Override\n        public String getSerializedName() {\n            return name;\n        }\n\n        @Override\n        public String toString() {\n            return name;\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/CrafterBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.container.CrafterContainerMenu;\nimport com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider;\nimport com.refinedmods.refinedstorage.blockentity.CrafterBlockEntity;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.LivingEntity;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.BlockHitResult;\nimport javax.annotation.Nullable;\n\npublic class CrafterBlock extends ColoredNetworkBlock {\n    public CrafterBlock() {\n        super(BlockUtils.DEFAULT_ROCK_PROPERTIES);\n    }\n\n    @Override\n    public BlockDirection getDirection() {\n        return BlockDirection.ANY_FACE_PLAYER;\n    }\n\n    @Override\n    public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {\n        super.setPlacedBy(level, pos, state, placer, stack);\n\n        if (!level.isClientSide) {\n            BlockEntity blockEntity = level.getBlockEntity(pos);\n\n            if (blockEntity instanceof CrafterBlockEntity && stack.hasCustomHoverName()) {\n                ((CrafterBlockEntity) blockEntity).getNode().setDisplayName(stack.getHoverName());\n                ((CrafterBlockEntity) blockEntity).getNode().markDirty();\n            }\n        }\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {\n        InteractionResult result = RSBlocks.CRAFTER.changeBlockColor(state, player.getItemInHand(hand), level, pos, player);\n        if (result != InteractionResult.PASS) {\n            return result;\n        }\n\n        if (!level.isClientSide) {\n            return NetworkUtils.attempt(level, pos, player, () -> player.openMenu(\n                new BlockEntityMenuProvider<CrafterBlockEntity>(\n                    ((CrafterBlockEntity) level.getBlockEntity(pos)).getNode().getName(),\n                    (blockEntity, windowId, inventory, p) -> new CrafterContainerMenu(blockEntity, player, windowId),\n                    pos\n                ),\n                pos\n            ), Permission.MODIFY, Permission.AUTOCRAFTING);\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n\n    @Override\n    public boolean hasConnectedState() {\n        return true;\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new CrafterBlockEntity(pos, state);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/CrafterManagerBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.container.factory.CrafterManagerMenuProvider;\nimport com.refinedmods.refinedstorage.blockentity.CrafterManagerBlockEntity;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.BlockHitResult;\n\npublic class CrafterManagerBlock extends ColoredNetworkBlock {\n    public CrafterManagerBlock() {\n        super(BlockUtils.DEFAULT_ROCK_PROPERTIES);\n    }\n\n    @Override\n    public BlockDirection getDirection() {\n        return BlockDirection.HORIZONTAL;\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new CrafterManagerBlockEntity(pos, state);\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {\n        InteractionResult result = RSBlocks.CRAFTER_MANAGER.changeBlockColor(state, player.getItemInHand(hand), level, pos, player);\n        if (result != InteractionResult.PASS) {\n            return result;\n        }\n\n        if (!level.isClientSide) {\n            return NetworkUtils.attempt(level, pos, player, () -> player.openMenu(\n                new CrafterManagerMenuProvider((CrafterManagerBlockEntity) level.getBlockEntity(pos)),\n                buf -> CrafterManagerMenuProvider.writeToBuffer(buf, level, pos)\n            ), Permission.MODIFY, Permission.AUTOCRAFTING);\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n\n    @Override\n    public boolean hasConnectedState() {\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/CraftingMonitorBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.container.factory.CraftingMonitorMenuProvider;\nimport com.refinedmods.refinedstorage.blockentity.craftingmonitor.CraftingMonitorBlockEntity;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.BlockHitResult;\n\npublic class CraftingMonitorBlock extends ColoredNetworkBlock {\n    public CraftingMonitorBlock() {\n        super(BlockUtils.DEFAULT_ROCK_PROPERTIES);\n    }\n\n    @Override\n    public BlockDirection getDirection() {\n        return BlockDirection.HORIZONTAL;\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new CraftingMonitorBlockEntity(pos, state);\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {\n        InteractionResult result = RSBlocks.CRAFTING_MONITOR.changeBlockColor(state, player.getItemInHand(hand), level, pos, player);\n        if (result != InteractionResult.PASS) {\n            return result;\n        }\n\n        if (!level.isClientSide) {\n            CraftingMonitorBlockEntity blockEntity = (CraftingMonitorBlockEntity) level.getBlockEntity(pos);\n\n            return NetworkUtils.attempt(level, pos, player, () -> player.openMenu(\n                new CraftingMonitorMenuProvider(RSContainerMenus.CRAFTING_MONITOR.get(), blockEntity.getNode(), blockEntity),\n                pos\n            ), Permission.MODIFY, Permission.AUTOCRAFTING);\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n\n    @Override\n    public boolean hasConnectedState() {\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/DestructorBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.block.shape.ShapeCache;\nimport com.refinedmods.refinedstorage.container.DestructorContainerMenu;\nimport com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider;\nimport com.refinedmods.refinedstorage.render.ConstantsCable;\nimport com.refinedmods.refinedstorage.blockentity.DestructorBlockEntity;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.CollisionUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\n\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.level.BlockGetter;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.BlockHitResult;\nimport net.minecraft.world.phys.shapes.CollisionContext;\nimport net.minecraft.world.phys.shapes.Shapes;\nimport net.minecraft.world.phys.shapes.VoxelShape;\n\npublic class DestructorBlock extends CableBlock {\n    private static final VoxelShape HEAD_NORTH = Shapes.or(box(2, 2, 0, 14, 14, 2), HOLDER_NORTH);\n    private static final VoxelShape HEAD_EAST = Shapes.or(box(14, 2, 2, 16, 14, 14), HOLDER_EAST);\n    private static final VoxelShape HEAD_SOUTH = Shapes.or(box(2, 2, 14, 14, 14, 16), HOLDER_SOUTH);\n    private static final VoxelShape HEAD_WEST = Shapes.or(box(0, 2, 2, 2, 14, 14), HOLDER_WEST);\n    private static final VoxelShape HEAD_DOWN = Shapes.or(box(2, 0, 2, 14, 2, 14), HOLDER_DOWN);\n    private static final VoxelShape HEAD_UP = Shapes.or(box(2, 14, 2, 14, 16, 14), HOLDER_UP);\n\n    public DestructorBlock() {\n        super(BlockUtils.DEFAULT_GLASS_PROPERTIES);\n    }\n\n    @Override\n    public BlockDirection getDirection() {\n        return BlockDirection.ANY;\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new DestructorBlockEntity(pos, state);\n    }\n\n    @Override\n    public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext ctx) {\n        return ConstantsCable.addCoverVoxelShapes(ShapeCache.getOrCreate(state, s -> {\n            VoxelShape shape = getCableShape(s);\n\n            shape = Shapes.or(shape, getHeadShape(s));\n\n            return shape;\n        }), world, pos);\n    }\n\n    private VoxelShape getHeadShape(BlockState state) {\n        Direction direction = state.getValue(getDirection().getProperty());\n\n        if (direction == Direction.NORTH) {\n            return HEAD_NORTH;\n        }\n\n        if (direction == Direction.EAST) {\n            return HEAD_EAST;\n        }\n\n        if (direction == Direction.SOUTH) {\n            return HEAD_SOUTH;\n        }\n\n        if (direction == Direction.WEST) {\n            return HEAD_WEST;\n        }\n\n        if (direction == Direction.UP) {\n            return HEAD_UP;\n        }\n\n        if (direction == Direction.DOWN) {\n            return HEAD_DOWN;\n        }\n\n        return Shapes.empty();\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit) {\n        if (!level.isClientSide && CollisionUtils.isInBounds(getHeadShape(state), pos, hit.getLocation())) {\n            return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu(\n                new BlockEntityMenuProvider<DestructorBlockEntity>(\n                    Component.translatable(\"gui.refinedstorage.destructor\"),\n                    (blockEntity, windowId, inventory, p) -> new DestructorContainerMenu(blockEntity, player, windowId),\n                    pos\n                ),\n                pos\n            ));\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n\n    @Override\n    public boolean hasConnectedState() {\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/DetectorBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.container.DetectorContainerMenu;\nimport com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider;\nimport com.refinedmods.refinedstorage.blockentity.DetectorBlockEntity;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.ColorMap;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\n\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.DyeColor;\nimport net.minecraft.world.level.BlockGetter;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.Block;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.level.block.state.StateDefinition;\nimport net.minecraft.world.level.block.state.properties.BooleanProperty;\nimport net.minecraft.world.phys.BlockHitResult;\nimport net.minecraft.world.phys.shapes.CollisionContext;\nimport net.minecraft.world.phys.shapes.VoxelShape;\n\npublic class DetectorBlock extends ColoredNetworkBlock {\n    public static final BooleanProperty POWERED = BooleanProperty.create(\"powered\");\n\n    private static final VoxelShape SHAPE = box(0, 0, 0, 16, 5, 16);\n\n    public DetectorBlock() {\n        super(BlockUtils.DEFAULT_ROCK_PROPERTIES);\n\n        this.registerDefaultState(this.getStateDefinition().any().setValue(POWERED, false));\n    }\n\n    @Override\n    protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {\n        super.createBlockStateDefinition(builder);\n\n        builder.add(POWERED);\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) {\n        return SHAPE;\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public boolean isSignalSource(BlockState state) {\n        return true;\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public int getSignal(BlockState state, BlockGetter world, BlockPos pos, Direction side) {\n        BlockEntity blockEntity = world.getBlockEntity(pos);\n\n        return (blockEntity instanceof DetectorBlockEntity && ((DetectorBlockEntity) blockEntity).getNode().isPowered()) ? 15 : 0;\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {\n        ColorMap<Block, DetectorBlock> colorMap = RSBlocks.DETECTOR;\n        DyeColor color = DyeColor.getColor(player.getItemInHand(hand));\n\n        if (color != null && !state.getBlock().equals(colorMap.get(color).get())) {\n            BlockState newState = colorMap.get(color).get().defaultBlockState().setValue(POWERED, state.getValue(POWERED));\n\n            return RSBlocks.DETECTOR.setBlockState(newState, player.getItemInHand(hand), level, pos, player);\n        }\n\n        if (!level.isClientSide) {\n            return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu(\n                new BlockEntityMenuProvider<DetectorBlockEntity>(\n                    Component.translatable(\"gui.refinedstorage.detector\"),\n                    (blockEntity, windowId, inventory, p) -> new DetectorContainerMenu(blockEntity, player, windowId),\n                    pos\n                ),\n                pos\n            ));\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new DetectorBlockEntity(pos, state);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/DiskDriveBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.container.DiskDriveContainerMenu;\nimport com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider;\nimport com.refinedmods.refinedstorage.blockentity.DiskDriveBlockEntity;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\n\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.BlockHitResult;\n\npublic class DiskDriveBlock extends NetworkNodeBlock {\n    public DiskDriveBlock() {\n        super(BlockUtils.DEFAULT_ROCK_PROPERTIES);\n    }\n\n    @Override\n    public BlockDirection getDirection() {\n        return BlockDirection.HORIZONTAL;\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new DiskDriveBlockEntity(pos, state);\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult rayTraceResult) {\n        if (!level.isClientSide) {\n            return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu(\n                new BlockEntityMenuProvider<DiskDriveBlockEntity>(\n                    Component.translatable(\"gui.refinedstorage.disk_drive\"),\n                    (blockEntity, windowId, inventory, p) -> new DiskDriveContainerMenu(blockEntity, p, windowId),\n                    pos\n                ),\n                pos\n            ));\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/DiskManipulatorBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.container.DiskManipulatorContainerMenu;\nimport com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider;\nimport com.refinedmods.refinedstorage.blockentity.DiskManipulatorBlockEntity;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\n\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.BlockHitResult;\n\npublic class DiskManipulatorBlock extends ColoredNetworkBlock {\n    public DiskManipulatorBlock() {\n        super(BlockUtils.DEFAULT_ROCK_PROPERTIES);\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new DiskManipulatorBlockEntity(pos, state);\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult rayTraceResult) {\n        InteractionResult result = RSBlocks.DISK_MANIPULATOR.changeBlockColor(state, player.getItemInHand(hand), level, pos, player);\n        if (result != InteractionResult.PASS) {\n            return result;\n        }\n\n        if (!level.isClientSide) {\n            return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu(\n                new BlockEntityMenuProvider<DiskManipulatorBlockEntity>(\n                    Component.translatable(\"gui.refinedstorage.disk_manipulator\"),\n                    (blockEntity, windowId, inventory, p) -> new DiskManipulatorContainerMenu(blockEntity, p, windowId),\n                    pos\n                ),\n                pos\n            ));\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n\n    @Override\n    public BlockDirection getDirection() {\n        return BlockDirection.HORIZONTAL;\n    }\n\n    @Override\n    public boolean hasConnectedState() {\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/ExporterBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.block.shape.ShapeCache;\nimport com.refinedmods.refinedstorage.container.ExporterContainerMenu;\nimport com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider;\nimport com.refinedmods.refinedstorage.render.ConstantsCable;\nimport com.refinedmods.refinedstorage.blockentity.ExporterBlockEntity;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.CollisionUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\n\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.level.BlockGetter;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.BlockHitResult;\nimport net.minecraft.world.phys.shapes.CollisionContext;\nimport net.minecraft.world.phys.shapes.Shapes;\nimport net.minecraft.world.phys.shapes.VoxelShape;\n\npublic class ExporterBlock extends CableBlock {\n    private static final VoxelShape LINE_NORTH_1 = box(6, 6, 0, 10, 10, 2);\n    private static final VoxelShape LINE_NORTH_2 = box(5, 5, 2, 11, 11, 4);\n    private static final VoxelShape LINE_NORTH_3 = box(3, 3, 4, 13, 13, 6);\n    private static final VoxelShape LINE_NORTH = Shapes.or(LINE_NORTH_1, LINE_NORTH_2, LINE_NORTH_3);\n\n    private static final VoxelShape LINE_EAST_1 = box(14, 6, 6, 16, 10, 10);\n    private static final VoxelShape LINE_EAST_2 = box(12, 5, 5, 14, 11, 11);\n    private static final VoxelShape LINE_EAST_3 = box(10, 3, 3, 12, 13, 13);\n    private static final VoxelShape LINE_EAST = Shapes.or(LINE_EAST_1, LINE_EAST_2, LINE_EAST_3);\n\n    private static final VoxelShape LINE_SOUTH_1 = box(6, 6, 14, 10, 10, 16);\n    private static final VoxelShape LINE_SOUTH_2 = box(5, 5, 12, 11, 11, 14);\n    private static final VoxelShape LINE_SOUTH_3 = box(3, 3, 10, 13, 13, 12);\n    private static final VoxelShape LINE_SOUTH = Shapes.or(LINE_SOUTH_1, LINE_SOUTH_2, LINE_SOUTH_3);\n\n    private static final VoxelShape LINE_WEST_1 = box(0, 6, 6, 2, 10, 10);\n    private static final VoxelShape LINE_WEST_2 = box(2, 5, 5, 4, 11, 11);\n    private static final VoxelShape LINE_WEST_3 = box(4, 3, 3, 6, 13, 13);\n    private static final VoxelShape LINE_WEST = Shapes.or(LINE_WEST_1, LINE_WEST_2, LINE_WEST_3);\n\n    private static final VoxelShape LINE_UP_1 = box(6, 14, 6, 10, 16, 10);\n    private static final VoxelShape LINE_UP_2 = box(5, 12, 5, 11, 14, 11);\n    private static final VoxelShape LINE_UP_3 = box(3, 10, 3, 13, 12, 13);\n    private static final VoxelShape LINE_UP = Shapes.or(LINE_UP_1, LINE_UP_2, LINE_UP_3);\n\n    private static final VoxelShape LINE_DOWN_1 = box(6, 0, 6, 10, 2, 10);\n    private static final VoxelShape LINE_DOWN_2 = box(5, 2, 5, 11, 4, 11);\n    private static final VoxelShape LINE_DOWN_3 = box(3, 4, 3, 13, 6, 13);\n    private static final VoxelShape LINE_DOWN = Shapes.or(LINE_DOWN_1, LINE_DOWN_2, LINE_DOWN_3);\n\n    public ExporterBlock() {\n        super(BlockUtils.DEFAULT_GLASS_PROPERTIES);\n    }\n\n    @Override\n    public BlockDirection getDirection() {\n        return BlockDirection.ANY;\n    }\n\n    @Override\n    public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext ctx) {\n        return ConstantsCable.addCoverVoxelShapes(ShapeCache.getOrCreate(state, s -> {\n            VoxelShape shape = getCableShape(s);\n\n            shape = Shapes.or(shape, getLineShape(s));\n\n            return shape;\n        }), world, pos);\n    }\n\n\n    private VoxelShape getLineShape(BlockState state) {\n        Direction direction = state.getValue(getDirection().getProperty());\n\n        if (direction == Direction.NORTH) {\n            return LINE_NORTH;\n        }\n\n        if (direction == Direction.EAST) {\n            return LINE_EAST;\n        }\n\n        if (direction == Direction.SOUTH) {\n            return LINE_SOUTH;\n        }\n\n        if (direction == Direction.WEST) {\n            return LINE_WEST;\n        }\n\n        if (direction == Direction.UP) {\n            return LINE_UP;\n        }\n\n        if (direction == Direction.DOWN) {\n            return LINE_DOWN;\n        }\n\n        return Shapes.empty();\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new ExporterBlockEntity(pos, state);\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {\n        if (!level.isClientSide && CollisionUtils.isInBounds(getLineShape(state), pos, hit.getLocation())) {\n            return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu(\n                new BlockEntityMenuProvider<ExporterBlockEntity>(\n                    Component.translatable(\"gui.refinedstorage.exporter\"),\n                    (blockEntity, windowId, inventory, p) -> new ExporterContainerMenu(blockEntity, player, windowId),\n                    pos\n                ),\n                pos\n            ));\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/ExternalStorageBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.ExternalStorageNetworkNode;\nimport com.refinedmods.refinedstorage.block.shape.ShapeCache;\nimport com.refinedmods.refinedstorage.container.ExternalStorageContainerMenu;\nimport com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider;\nimport com.refinedmods.refinedstorage.render.ConstantsCable;\nimport com.refinedmods.refinedstorage.blockentity.ExternalStorageBlockEntity;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.CollisionUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\n\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.level.BlockGetter;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.Block;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.BlockHitResult;\nimport net.minecraft.world.phys.shapes.CollisionContext;\nimport net.minecraft.world.phys.shapes.Shapes;\nimport net.minecraft.world.phys.shapes.VoxelShape;\n\npublic class ExternalStorageBlock extends CableBlock {\n    private static final VoxelShape HEAD_NORTH = Shapes.or(box(3, 3, 0, 13, 13, 2), HOLDER_NORTH);\n    private static final VoxelShape HEAD_EAST = Shapes.or(box(14, 3, 3, 16, 13, 13), HOLDER_EAST);\n    private static final VoxelShape HEAD_SOUTH = Shapes.or(box(3, 3, 14, 13, 13, 16), HOLDER_SOUTH);\n    private static final VoxelShape HEAD_WEST = Shapes.or(box(0, 3, 3, 2, 13, 13), HOLDER_WEST);\n    private static final VoxelShape HEAD_UP = Shapes.or(box(3, 14, 3, 13, 16, 13), HOLDER_UP);\n    private static final VoxelShape HEAD_DOWN = Shapes.or(box(3, 0, 3, 13, 2, 13), HOLDER_DOWN);\n\n    public ExternalStorageBlock() {\n        super(BlockUtils.DEFAULT_GLASS_PROPERTIES);\n    }\n\n    @Override\n    public BlockDirection getDirection() {\n        return BlockDirection.ANY;\n    }\n\n    @Override\n    public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext ctx) {\n        return ConstantsCable.addCoverVoxelShapes(ShapeCache.getOrCreate(state, s -> {\n            VoxelShape shape = getCableShape(s);\n\n            shape = Shapes.or(shape, getHeadShape(s));\n\n            return shape;\n        }), world, pos);\n    }\n\n    private VoxelShape getHeadShape(BlockState state) {\n        Direction direction = state.getValue(getDirection().getProperty());\n\n        if (direction == Direction.NORTH) {\n            return HEAD_NORTH;\n        }\n\n        if (direction == Direction.EAST) {\n            return HEAD_EAST;\n        }\n\n        if (direction == Direction.SOUTH) {\n            return HEAD_SOUTH;\n        }\n\n        if (direction == Direction.WEST) {\n            return HEAD_WEST;\n        }\n\n        if (direction == Direction.UP) {\n            return HEAD_UP;\n        }\n\n        if (direction == Direction.DOWN) {\n            return HEAD_DOWN;\n        }\n\n        return Shapes.empty();\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new ExternalStorageBlockEntity(pos, state);\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {\n        if (!level.isClientSide && CollisionUtils.isInBounds(getHeadShape(state), pos, hit.getLocation())) {\n            return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu(\n                new BlockEntityMenuProvider<ExternalStorageBlockEntity>(\n                    Component.translatable(\"gui.refinedstorage.external_storage\"),\n                    (blockEntity, windowId, inventory, p) -> new ExternalStorageContainerMenu(blockEntity, player, windowId),\n                    pos\n                ),\n                pos\n            ));\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) {\n        super.neighborChanged(state, level, pos, block, fromPos, isMoving);\n\n        if (!level.isClientSide) {\n            INetworkNode node = NetworkUtils.getNodeFromBlockEntity(level.getBlockEntity(pos));\n\n            if (node instanceof ExternalStorageNetworkNode &&\n                node.getNetwork() != null &&\n                fromPos.equals(pos.relative(((ExternalStorageNetworkNode) node).getDirection()))) {\n                ((ExternalStorageNetworkNode) node).updateStorage(node.getNetwork(), InvalidateCause.NEIGHBOR_CHANGED);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/FluidInterfaceBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.container.FluidInterfaceContainerMenu;\nimport com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider;\nimport com.refinedmods.refinedstorage.blockentity.FluidInterfaceBlockEntity;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\n\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.BlockHitResult;\n\npublic class FluidInterfaceBlock extends NetworkNodeBlock {\n    public FluidInterfaceBlock() {\n        super(BlockUtils.DEFAULT_ROCK_PROPERTIES);\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new FluidInterfaceBlockEntity(pos, state);\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit) {\n        if (!level.isClientSide) {\n            return NetworkUtils.attempt(level, pos, player, () -> player.openMenu(\n                new BlockEntityMenuProvider<FluidInterfaceBlockEntity>(\n                    Component.translatable(\"gui.refinedstorage.fluid_interface\"),\n                    (blockEntity, windowId, inventory, p) -> new FluidInterfaceContainerMenu(blockEntity, player, windowId),\n                    pos\n                ),\n                pos\n            ), Permission.MODIFY, Permission.INSERT, Permission.EXTRACT);\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n\n    @Override\n    public boolean hasConnectedState() {\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/FluidStorageBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.apiimpl.network.node.storage.FluidStorageNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType;\nimport com.refinedmods.refinedstorage.container.FluidStorageContainerMenu;\nimport com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider;\nimport com.refinedmods.refinedstorage.blockentity.FluidStorageBlockEntity;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.LivingEntity;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.BlockHitResult;\n\npublic class FluidStorageBlock extends NetworkNodeBlock {\n    private final FluidStorageType type;\n\n    public FluidStorageBlock(FluidStorageType type) {\n        super(BlockUtils.DEFAULT_ROCK_PROPERTIES);\n\n        this.type = type;\n    }\n\n    public FluidStorageType getType() {\n        return type;\n    }\n\n    @Override\n    public void setPlacedBy(Level level, BlockPos pos, BlockState state, LivingEntity player, ItemStack stack) {\n        if (!level.isClientSide) {\n            FluidStorageNetworkNode storage = ((FluidStorageBlockEntity) level.getBlockEntity(pos)).getNode();\n\n            if (stack.hasTag() && stack.getTag().hasUUID(FluidStorageNetworkNode.NBT_ID)) {\n                storage.setStorageId(stack.getTag().getUUID(FluidStorageNetworkNode.NBT_ID));\n            }\n\n            storage.loadStorage(player instanceof Player ? (Player) player : null);\n        }\n\n        // Call this after loading the storage, so the network discovery can use the loaded storage.\n        super.setPlacedBy(level, pos, state, player, stack);\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new FluidStorageBlockEntity(type, pos, state);\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit) {\n        if (!level.isClientSide) {\n            return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu(\n                new BlockEntityMenuProvider<FluidStorageBlockEntity>(\n                ((FluidStorageBlockEntity) level.getBlockEntity(pos)).getNode().getTitle(),\n                (blockEntity, windowId, inventory, p) -> new FluidStorageContainerMenu(blockEntity, player, windowId),\n                pos\n            ), pos));\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/GridBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.api.network.grid.GridType;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.grid.factory.GridBlockGridFactory;\nimport com.refinedmods.refinedstorage.blockentity.grid.GridBlockEntity;\nimport com.refinedmods.refinedstorage.util.BlockColorMap;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.ColorMap;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\n\nimport net.minecraft.client.color.block.BlockColor;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.Block;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.BlockHitResult;\n\npublic class GridBlock extends ColoredNetworkBlock {\n    private final GridType type;\n\n    public GridBlock(GridType type) {\n        super(BlockUtils.DEFAULT_ROCK_PROPERTIES);\n\n        this.type = type;\n    }\n\n    @Override\n    public BlockDirection getDirection() {\n        return BlockDirection.HORIZONTAL;\n    }\n\n    @Override\n    public boolean hasConnectedState() {\n        return true;\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new GridBlockEntity(type, pos, state);\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {\n        BlockColorMap<?> map;\n        switch (type) {\n            case FLUID:\n                map = RSBlocks.FLUID_GRID;\n                break;\n            case NORMAL:\n                map = RSBlocks.GRID;\n                break;\n            case CRAFTING:\n                map = RSBlocks.CRAFTING_GRID;\n                break;\n            case PATTERN:\n                map = RSBlocks.PATTERN_GRID;\n                break;\n            default:\n                throw new IllegalStateException(\"Unexpected value: \" + type);\n        }\n\n        InteractionResult result = map.changeBlockColor(state, player.getItemInHand(hand), level, pos, player);\n        if (result != InteractionResult.PASS) {\n            return result;\n        }\n\n        if (!level.isClientSide) {\n            return NetworkUtils.attemptModify(level, pos, player, () -> API.instance().getGridManager().openGrid(GridBlockGridFactory.ID, (ServerPlayer) player, pos));\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/ImporterBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.block.shape.ShapeCache;\nimport com.refinedmods.refinedstorage.container.ImporterContainerMenu;\nimport com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider;\nimport com.refinedmods.refinedstorage.render.ConstantsCable;\nimport com.refinedmods.refinedstorage.blockentity.ImporterBlockEntity;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.CollisionUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\n\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.level.BlockGetter;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.BlockHitResult;\nimport net.minecraft.world.phys.shapes.CollisionContext;\nimport net.minecraft.world.phys.shapes.Shapes;\nimport net.minecraft.world.phys.shapes.VoxelShape;\n\npublic class ImporterBlock extends CableBlock {\n    private static final VoxelShape LINE_NORTH_1 = box(6, 6, 4, 10, 10, 6);\n    private static final VoxelShape LINE_NORTH_2 = box(5, 5, 2, 11, 11, 4);\n    private static final VoxelShape LINE_NORTH_3 = box(3, 3, 0, 13, 13, 2);\n    private static final VoxelShape LINE_NORTH = Shapes.or(LINE_NORTH_1, LINE_NORTH_2, LINE_NORTH_3);\n\n    private static final VoxelShape LINE_EAST_1 = box(10, 6, 6, 12, 10, 10);\n    private static final VoxelShape LINE_EAST_2 = box(12, 5, 5, 14, 11, 11);\n    private static final VoxelShape LINE_EAST_3 = box(14, 3, 3, 16, 13, 13);\n    private static final VoxelShape LINE_EAST = Shapes.or(LINE_EAST_1, LINE_EAST_2, LINE_EAST_3);\n\n    private static final VoxelShape LINE_SOUTH_1 = box(6, 6, 10, 10, 10, 12);\n    private static final VoxelShape LINE_SOUTH_2 = box(5, 5, 12, 11, 11, 14);\n    private static final VoxelShape LINE_SOUTH_3 = box(3, 3, 14, 13, 13, 16);\n    private static final VoxelShape LINE_SOUTH = Shapes.or(LINE_SOUTH_1, LINE_SOUTH_2, LINE_SOUTH_3);\n\n    private static final VoxelShape LINE_WEST_1 = box(4, 6, 6, 6, 10, 10);\n    private static final VoxelShape LINE_WEST_2 = box(2, 5, 5, 4, 11, 11);\n    private static final VoxelShape LINE_WEST_3 = box(0, 3, 3, 2, 13, 13);\n    private static final VoxelShape LINE_WEST = Shapes.or(LINE_WEST_1, LINE_WEST_2, LINE_WEST_3);\n\n    private static final VoxelShape LINE_UP_1 = box(6, 10, 6, 10, 12, 10);\n    private static final VoxelShape LINE_UP_2 = box(5, 12, 5, 11, 14, 11);\n    private static final VoxelShape LINE_UP_3 = box(3, 14, 3, 13, 16, 13);\n    private static final VoxelShape LINE_UP = Shapes.or(LINE_UP_1, LINE_UP_2, LINE_UP_3);\n\n    private static final VoxelShape LINE_DOWN_1 = box(6, 4, 6, 10, 6, 10);\n    private static final VoxelShape LINE_DOWN_2 = box(5, 2, 5, 11, 4, 11);\n    private static final VoxelShape LINE_DOWN_3 = box(3, 0, 3, 13, 2, 13);\n    private static final VoxelShape LINE_DOWN = Shapes.or(LINE_DOWN_1, LINE_DOWN_2, LINE_DOWN_3);\n\n    public ImporterBlock() {\n        super(BlockUtils.DEFAULT_GLASS_PROPERTIES);\n    }\n\n    @Override\n    public BlockDirection getDirection() {\n        return BlockDirection.ANY;\n    }\n\n    @Override\n    public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext ctx) {\n        return ConstantsCable.addCoverVoxelShapes(ShapeCache.getOrCreate(state, s -> {\n            VoxelShape shape = getCableShape(s);\n\n            shape = Shapes.or(shape, getLineShape(s));\n\n            return shape;\n        }), world, pos);\n    }\n\n    private VoxelShape getLineShape(BlockState state) {\n        Direction direction = state.getValue(getDirection().getProperty());\n\n        if (direction == Direction.NORTH) {\n            return LINE_NORTH;\n        }\n\n        if (direction == Direction.EAST) {\n            return LINE_EAST;\n        }\n\n        if (direction == Direction.SOUTH) {\n            return LINE_SOUTH;\n        }\n\n        if (direction == Direction.WEST) {\n            return LINE_WEST;\n        }\n\n        if (direction == Direction.UP) {\n            return LINE_UP;\n        }\n\n        if (direction == Direction.DOWN) {\n            return LINE_DOWN;\n        }\n\n        return Shapes.empty();\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new ImporterBlockEntity(pos, state);\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {\n        if (!level.isClientSide && CollisionUtils.isInBounds(getLineShape(state), pos, hit.getLocation())) {\n            return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu(\n                new BlockEntityMenuProvider<ImporterBlockEntity>(\n                    Component.translatable(\"gui.refinedstorage.importer\"),\n                    (blockEntity, windowId, inventory, p) -> new ImporterContainerMenu(blockEntity, player, windowId),\n                    pos\n                ),\n                pos\n            ));\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/InterfaceBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.container.InterfaceContainerMenu;\nimport com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider;\nimport com.refinedmods.refinedstorage.blockentity.InterfaceBlockEntity;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\n\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.BlockHitResult;\n\npublic class InterfaceBlock extends NetworkNodeBlock {\n    public InterfaceBlock() {\n        super(BlockUtils.DEFAULT_ROCK_PROPERTIES);\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new InterfaceBlockEntity(pos, state);\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit) {\n        if (!level.isClientSide) {\n            return NetworkUtils.attempt(level, pos, player, () -> player.openMenu(\n                new BlockEntityMenuProvider<InterfaceBlockEntity>(\n                    Component.translatable(\"gui.refinedstorage.interface\"),\n                    (blockEntity, windowId, inventory, p) -> new InterfaceContainerMenu(blockEntity, player, windowId),\n                    pos\n                ),\n                pos\n            ), Permission.MODIFY, Permission.INSERT, Permission.EXTRACT);\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n\n    @Override\n    public boolean hasConnectedState() {\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/MachineCasingBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.util.BlockUtils;\n\npublic class MachineCasingBlock extends BaseBlock {\n    public MachineCasingBlock() {\n        super(BlockUtils.DEFAULT_ROCK_PROPERTIES);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/NetworkNodeBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.NetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.core.NonNullList;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.Containers;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.Block;\nimport net.minecraft.world.level.block.EntityBlock;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockBehaviour;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.level.block.state.StateDefinition;\nimport net.minecraft.world.level.block.state.properties.BooleanProperty;\nimport net.neoforged.neoforge.items.IItemHandler;\n\npublic abstract class NetworkNodeBlock extends BaseBlock implements EntityBlock {\n    public static final BooleanProperty CONNECTED = BooleanProperty.create(\"connected\");\n\n    protected NetworkNodeBlock(BlockBehaviour.Properties props) {\n        super(props);\n\n        if (hasConnectedState()) {\n            this.registerDefaultState(this.getStateDefinition().any().setValue(CONNECTED, false));\n        }\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public void neighborChanged(BlockState state, Level level, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) {\n        super.neighborChanged(state, level, pos, blockIn, fromPos, isMoving);\n\n        if (!level.isClientSide) {\n            INetworkNode node = API.instance().getNetworkNodeManager((ServerLevel) level).getNode(pos);\n            if (node instanceof NetworkNode) {\n                ((NetworkNode) node).setRedstonePowered(level.hasNeighborSignal(pos));\n            }\n        }\n    }\n\n    @Override\n    public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {\n        if (state.getBlock() != newState.getBlock()) {\n            BlockEntity blockEntity = level.getBlockEntity(pos);\n\n            if (blockEntity instanceof NetworkNodeBlockEntity) {\n                IItemHandler handler = ((NetworkNodeBlockEntity) blockEntity).getNode().getDrops();\n\n                if (handler != null) {\n                    NonNullList<ItemStack> drops = NonNullList.create();\n\n                    for (int i = 0; i < handler.getSlots(); ++i) {\n                        drops.add(handler.getStackInSlot(i));\n                    }\n\n                    Containers.dropContents(level, pos, drops);\n                }\n            }\n        }\n\n        // Call onReplaced after the drops check so the tile still exists\n        super.onRemove(state, level, pos, newState, isMoving);\n    }\n\n    @Override\n    protected void onDirectionChanged(Level level, BlockPos pos, Direction newDirection) {\n        super.onDirectionChanged(level, pos, newDirection);\n\n        BlockEntity blockEntity = level.getBlockEntity(pos);\n        if (blockEntity instanceof INetworkNodeProxy) {\n            INetworkNode node = ((INetworkNodeProxy) blockEntity).getNode();\n\n            if (node instanceof NetworkNode) {\n                ((NetworkNode) node).onDirectionChanged(newDirection);\n            }\n        }\n    }\n\n    @Override\n    protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {\n        super.createBlockStateDefinition(builder);\n\n        if (hasConnectedState()) {\n            builder.add(CONNECTED);\n        }\n    }\n\n    public boolean hasConnectedState() {\n        return false;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/NetworkReceiverBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.blockentity.NetworkReceiverBlockEntity;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.BlockHitResult;\n\npublic class NetworkReceiverBlock extends ColoredNetworkBlock {\n    public NetworkReceiverBlock() {\n        super(BlockUtils.DEFAULT_ROCK_PROPERTIES);\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new NetworkReceiverBlockEntity(pos, state);\n    }\n\n    @Override\n    public boolean hasConnectedState() {\n        return true;\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {\n        return RSBlocks.NETWORK_RECEIVER.changeBlockColor(state, player.getItemInHand(hand), level, pos, player);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/NetworkTransmitterBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.blockentity.NetworkTransmitterBlockEntity;\nimport com.refinedmods.refinedstorage.container.NetworkTransmitterContainerMenu;\nimport com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.BlockHitResult;\n\npublic class NetworkTransmitterBlock extends ColoredNetworkBlock {\n    public NetworkTransmitterBlock() {\n        super(BlockUtils.DEFAULT_ROCK_PROPERTIES);\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new NetworkTransmitterBlockEntity(pos, state);\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {\n        InteractionResult result = RSBlocks.NETWORK_TRANSMITTER.changeBlockColor(state, player.getItemInHand(hand), level, pos, player);\n        if (result != InteractionResult.PASS) {\n            return result;\n        }\n\n        if (!level.isClientSide) {\n            return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu(\n                new BlockEntityMenuProvider<NetworkTransmitterBlockEntity>(\n                    Component.translatable(\"gui.refinedstorage.network_transmitter\"),\n                    (blockEntity, windowId, inventory, p) -> new NetworkTransmitterContainerMenu(blockEntity, player, windowId),\n                    pos\n                ),\n                pos\n            ));\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n\n    @Override\n    public boolean hasConnectedState() {\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/PortableGridBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.grid.factory.PortableGridBlockGridFactory;\nimport com.refinedmods.refinedstorage.blockentity.grid.portable.PortableGridBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.grid.portable.PortableGridDiskState;\nimport com.refinedmods.refinedstorage.item.blockitem.PortableGridBlockItem;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.LivingEntity;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.BlockGetter;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.Block;\nimport net.minecraft.world.level.block.EntityBlock;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.entity.BlockEntityTicker;\nimport net.minecraft.world.level.block.entity.BlockEntityType;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.level.block.state.StateDefinition;\nimport net.minecraft.world.level.block.state.properties.BooleanProperty;\nimport net.minecraft.world.level.block.state.properties.EnumProperty;\nimport net.minecraft.world.phys.BlockHitResult;\nimport net.minecraft.world.phys.shapes.CollisionContext;\nimport net.minecraft.world.phys.shapes.VoxelShape;\n\nimport javax.annotation.Nullable;\n\npublic class PortableGridBlock extends BaseBlock implements EntityBlock {\n    public static final EnumProperty<PortableGridDiskState> DISK_STATE = EnumProperty.create(\"disk_state\", PortableGridDiskState.class);\n    public static final BooleanProperty ACTIVE = BooleanProperty.create(\"active\");\n\n    private static final VoxelShape SHAPE = box(0, 0, 0, 16, 13.2, 16);\n\n    private final PortableGridBlockItem.Type type;\n\n    public PortableGridBlock(PortableGridBlockItem.Type type) {\n        super(BlockUtils.DEFAULT_ROCK_PROPERTIES);\n\n        this.type = type;\n        this.registerDefaultState(defaultBlockState().setValue(DISK_STATE, PortableGridDiskState.NONE).setValue(ACTIVE, false));\n    }\n\n    @Override\n    protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {\n        super.createBlockStateDefinition(builder);\n\n        builder.add(DISK_STATE);\n        builder.add(ACTIVE);\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) {\n        return SHAPE;\n    }\n\n    @Override\n    public BlockDirection getDirection() {\n        return BlockDirection.HORIZONTAL;\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new PortableGridBlockEntity(type, pos, state);\n    }\n\n    @Override\n    public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> type) {\n        return level.isClientSide ? null : new BlockEntityTicker<T>() {\n            @Override\n            public void tick(Level level, BlockPos pos, BlockState state, T blockEntity) {\n                if (blockEntity instanceof PortableGridBlockEntity) {\n                    PortableGridBlockEntity.serverTick((PortableGridBlockEntity) blockEntity);\n                }\n            }\n        };\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {\n        if (!level.isClientSide) {\n            API.instance().getGridManager().openGrid(PortableGridBlockGridFactory.ID, (ServerPlayer) player, pos);\n\n            ((PortableGridBlockEntity) level.getBlockEntity(pos)).onOpened();\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n\n    @Override\n    public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {\n        super.setPlacedBy(level, pos, state, placer, stack);\n\n        if (!level.isClientSide) {\n            ((PortableGridBlockEntity) level.getBlockEntity(pos)).applyDataFromItemToBlockEntity(stack);\n            ((PortableGridBlockEntity) level.getBlockEntity(pos)).updateState();\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/QuartzEnrichedIronBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.util.BlockUtils;\n\npublic class QuartzEnrichedIronBlock extends BaseBlock {\n    public QuartzEnrichedIronBlock() {\n        super(BlockUtils.DEFAULT_ROCK_PROPERTIES);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/RelayBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.container.RelayContainerMenu;\nimport com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider;\nimport com.refinedmods.refinedstorage.blockentity.RelayBlockEntity;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\n\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.BlockHitResult;\n\npublic class RelayBlock extends ColoredNetworkBlock {\n    public RelayBlock() {\n        super(BlockUtils.DEFAULT_ROCK_PROPERTIES);\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new RelayBlockEntity(pos, state);\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {\n        InteractionResult result = RSBlocks.RELAY.changeBlockColor(state, player.getItemInHand(hand), level, pos, player);\n        if (result != InteractionResult.PASS) {\n            return result;\n        }\n\n        if (!level.isClientSide) {\n            return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu(\n                new BlockEntityMenuProvider<RelayBlockEntity>(\n                    Component.translatable(\"gui.refinedstorage.relay\"),\n                    (blockEntity, windowId, inventory, p) -> new RelayContainerMenu(blockEntity, player, windowId),\n                    pos\n                ),\n                pos\n            ));\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n\n    @Override\n    public boolean hasConnectedState() {\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/SecurityManagerBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.container.SecurityManagerContainerMenu;\nimport com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider;\nimport com.refinedmods.refinedstorage.blockentity.SecurityManagerBlockEntity;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\n\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.BlockHitResult;\n\npublic class SecurityManagerBlock extends ColoredNetworkBlock {\n    public SecurityManagerBlock() {\n        super(BlockUtils.DEFAULT_ROCK_PROPERTIES);\n    }\n\n    @Override\n    public BlockDirection getDirection() {\n        return BlockDirection.HORIZONTAL;\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {\n        InteractionResult result = RSBlocks.SECURITY_MANAGER.changeBlockColor(state, player.getItemInHand(hand), level, pos, player);\n        if (result != InteractionResult.PASS) {\n            return result;\n        }\n\n        if (!level.isClientSide) {\n            Runnable action = () -> player.openMenu(\n                new BlockEntityMenuProvider<SecurityManagerBlockEntity>(\n                    Component.translatable(\"gui.refinedstorage.security_manager\"),\n                    (blockEntity, windowId, inventory, p) -> new SecurityManagerContainerMenu(blockEntity, player, windowId),\n                    pos\n                ),\n                pos\n            );\n\n            if (player.getGameProfile().getId().equals(((SecurityManagerBlockEntity) level.getBlockEntity(pos)).getNode().getOwner())) {\n                action.run();\n            } else {\n                return NetworkUtils.attempt(level, pos, player, action, Permission.MODIFY, Permission.SECURITY);\n            }\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new SecurityManagerBlockEntity(pos, state);\n    }\n\n    @Override\n    public boolean hasConnectedState() {\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/StorageBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.apiimpl.network.node.storage.StorageNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType;\nimport com.refinedmods.refinedstorage.container.StorageContainerMenu;\nimport com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider;\nimport com.refinedmods.refinedstorage.blockentity.StorageBlockEntity;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.LivingEntity;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.BlockHitResult;\nimport javax.annotation.Nullable;\n\npublic class StorageBlock extends NetworkNodeBlock {\n    private final ItemStorageType type;\n\n    public StorageBlock(ItemStorageType type) {\n        super(BlockUtils.DEFAULT_ROCK_PROPERTIES);\n\n        this.type = type;\n    }\n\n    public ItemStorageType getType() {\n        return type;\n    }\n\n    @Override\n    public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity entity, ItemStack stack) {\n        if (!level.isClientSide) {\n            StorageNetworkNode storage = ((StorageBlockEntity) level.getBlockEntity(pos)).getNode();\n\n            if (stack.hasTag() && stack.getTag().hasUUID(StorageNetworkNode.NBT_ID)) {\n                storage.setStorageId(stack.getTag().getUUID(StorageNetworkNode.NBT_ID));\n            }\n\n            storage.loadStorage(entity instanceof Player ? (Player) entity : null);\n        }\n\n        // Call this after loading the storage, so the network discovery can use the loaded storage.\n        super.setPlacedBy(level, pos, state, entity, stack);\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new StorageBlockEntity(type, pos, state);\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit) {\n        if (!level.isClientSide) {\n            return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu(\n                new BlockEntityMenuProvider<StorageBlockEntity>(\n                ((StorageBlockEntity) level.getBlockEntity(pos)).getNode().getTitle(),\n                (blockEntity, windowId, inventory, p) -> new StorageContainerMenu(blockEntity, player, windowId),\n                pos\n            ), pos));\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/StorageMonitorBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.apiimpl.network.node.StorageMonitorNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.StorageMonitorBlockEntity;\nimport com.refinedmods.refinedstorage.container.StorageMonitorContainerMenu;\nimport com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\n\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.BlockHitResult;\nimport net.minecraft.world.phys.HitResult;\n\npublic class StorageMonitorBlock extends NetworkNodeBlock {\n    public StorageMonitorBlock() {\n        super(BlockUtils.DEFAULT_ROCK_PROPERTIES);\n    }\n\n    @Override\n    public BlockDirection getDirection() {\n        return BlockDirection.HORIZONTAL;\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new StorageMonitorBlockEntity(pos, state);\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit) {\n        if (!level.isClientSide) {\n            ItemStack held = player.getItemInHand(handIn);\n\n            if (player.isCrouching()) {\n                return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu(\n                    new BlockEntityMenuProvider<StorageMonitorBlockEntity>(\n                        Component.translatable(\"gui.refinedstorage.storage_monitor\"),\n                        (blockEntity, windowId, inventory, p) -> new StorageMonitorContainerMenu(blockEntity, player, windowId),\n                        pos\n                    ),\n                    pos\n                ));\n            } else {\n                StorageMonitorNetworkNode storageMonitor = ((StorageMonitorBlockEntity) level.getBlockEntity(pos)).getNode();\n\n                if (!held.isEmpty()) {\n                    return storageMonitor.deposit(player, held);\n                } else {\n                    return storageMonitor.depositAll(player);\n                }\n            }\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public void attack(BlockState state, Level level, BlockPos pos, Player player) {\n        super.attack(state, level, pos, player);\n\n        if (!level.isClientSide) {\n            HitResult result = LevelUtils.rayTracePlayer(level, player);\n\n            if (!(result instanceof BlockHitResult)) {\n                return;\n            }\n\n            ((StorageMonitorBlockEntity) level.getBlockEntity(pos)).getNode().extract(player, ((BlockHitResult) result).getDirection());\n        }\n    }\n\n    @Override\n    public boolean hasConnectedState() {\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/WirelessTransmitterBlock.java",
    "content": "package com.refinedmods.refinedstorage.block;\n\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.container.WirelessTransmitterContainerMenu;\nimport com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider;\nimport com.refinedmods.refinedstorage.blockentity.WirelessTransmitterBlockEntity;\nimport com.refinedmods.refinedstorage.util.BlockUtils;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\n\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.level.BlockGetter;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.BlockHitResult;\nimport net.minecraft.world.phys.shapes.CollisionContext;\nimport net.minecraft.world.phys.shapes.Shapes;\nimport net.minecraft.world.phys.shapes.VoxelShape;\n\npublic class WirelessTransmitterBlock extends ColoredNetworkBlock {\n    private static final VoxelShape SHAPE_DOWN = box(6.0D, 0.0D, 6.0D, 10.0D, 10.0D, 10.0D);\n    private static final VoxelShape SHAPE_UP = box(6.0D, 6.0D, 6.0D, 10.0D, 16.0D, 10.0D);\n    private static final VoxelShape SHAPE_EAST = box(6.0D, 6.0D, 6.0D, 16.0D, 10.0D, 10.0D);\n    private static final VoxelShape SHAPE_WEST = box(0.0D, 6.0D, 6.0D, 10.0D, 10.0D, 10.0D);\n    private static final VoxelShape SHAPE_NORTH = box(6.0D, 6.0D, 0.0D, 10.0D, 10.0D, 10.0D);\n    private static final VoxelShape SHAPE_SOUTH = box(6.0D, 6.0D, 6.0D, 10.0D, 10.0D, 16.0D);\n\n    public WirelessTransmitterBlock() {\n        super(BlockUtils.DEFAULT_ROCK_PROPERTIES);\n    }\n\n    @Override\n    public BlockDirection getDirection() {\n        return BlockDirection.ANY;\n    }\n\n    @Override\n    public boolean hasConnectedState() {\n        return true;\n    }\n\n    @Override\n    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {\n        return new WirelessTransmitterBlockEntity(pos, state);\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {\n        switch (state.getValue(getDirection().getProperty())) {\n            case DOWN:\n                return SHAPE_DOWN;\n            case UP:\n                return SHAPE_UP;\n            case NORTH:\n                return SHAPE_NORTH;\n            case SOUTH:\n                return SHAPE_SOUTH;\n            case WEST:\n                return SHAPE_WEST;\n            case EAST:\n                return SHAPE_EAST;\n            default:\n                return Shapes.empty();\n        }\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {\n        InteractionResult result = RSBlocks.WIRELESS_TRANSMITTER.changeBlockColor(state, player.getItemInHand(hand), level, pos, player);\n        if (result != InteractionResult.PASS) {\n            return result;\n        }\n\n        if (!level.isClientSide) {\n            return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu(\n                new BlockEntityMenuProvider<WirelessTransmitterBlockEntity>(\n                    Component.translatable(\"gui.refinedstorage.wireless_transmitter\"),\n                    (blockEntity, windowId, inventory, p) -> new WirelessTransmitterContainerMenu(blockEntity, player, windowId),\n                    pos\n                ),\n                pos\n            ));\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/block/shape/ShapeCache.java",
    "content": "package com.refinedmods.refinedstorage.block.shape;\n\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.shapes.VoxelShape;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.function.Function;\n\npublic final class ShapeCache {\n    private static final Map<BlockState, VoxelShape> CACHE = new HashMap<>();\n\n    private ShapeCache() {\n    }\n\n    public static VoxelShape getOrCreate(BlockState state, Function<BlockState, VoxelShape> shapeFactory) {\n        return CACHE.computeIfAbsent(state, shapeFactory);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/BaseBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.Connection;\nimport net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.block.entity.BlockEntityType;\nimport net.minecraft.world.level.block.state.BlockState;\n\npublic abstract class BaseBlockEntity extends BlockEntity {\n    private final BlockEntitySynchronizationManager dataManager;\n    private boolean unloaded;\n\n    protected BaseBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state, BlockEntitySynchronizationSpec syncSpec) {\n        super(type, pos, state);\n        this.dataManager = new BlockEntitySynchronizationManager(this, syncSpec);\n    }\n\n    public BlockEntitySynchronizationManager getDataManager() {\n        return dataManager;\n    }\n\n    public CompoundTag writeUpdate(CompoundTag tag) {\n        return tag;\n    }\n\n    public void readUpdate(CompoundTag tag) {\n    }\n\n    @Override\n    public final CompoundTag getUpdateTag() {\n        return writeUpdate(super.getUpdateTag());\n    }\n\n    @Override\n    public final ClientboundBlockEntityDataPacket getUpdatePacket() {\n        return ClientboundBlockEntityDataPacket.create(this, BlockEntity::getUpdateTag);\n    }\n\n    @Override\n    public final void onDataPacket(Connection net, ClientboundBlockEntityDataPacket packet) {\n        readUpdate(packet.getTag());\n    }\n\n    @Override\n    public void handleUpdateTag(CompoundTag tag) {\n        super.handleUpdateTag(tag);\n        readUpdate(tag);\n    }\n\n    @Override\n    public void setRemoved() {\n        super.setRemoved();\n        // @Volatile: MC calls setRemoved when a chunk unloads now as well (see ServerLevel#unload -> LevelChunk#clearAllBlockEntities).\n        // Since we don't want to remove network node data in that case, we need to know if it was removed due to unloading.\n        // We can use \"unloaded\" for that, it's set in #onChunkUnloaded.\n        // Since MC first calls #onChunkUnloaded and then #setRemoved, this check keeps working.\n        if (!unloaded) {\n            onRemovedNotDueToChunkUnload();\n        }\n    }\n\n    protected void onRemovedNotDueToChunkUnload() {\n        // NO OP\n    }\n\n    @Override\n    public void onChunkUnloaded() {\n        super.onChunkUnloaded();\n        unloaded = true;\n    }\n\n    // @Volatile: Copied with some changes from the super method (avoid sending neighbor updates, it's not needed)\n    @Override\n    public void setChanged() {\n        if (level != null) {\n            level.blockEntityChanged(worldPosition);\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/CableBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.CableNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.syncher.EntityDataSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.model.data.ModelData;\nimport javax.annotation.Nonnull;\n\npublic class CableBlockEntity extends NetworkNodeBlockEntity<CableNetworkNode> {\n    public static final BlockEntitySynchronizationParameter<CompoundTag, CableBlockEntity> COVER_MANAGER = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"cable_cover_manager\"), EntityDataSerializers.COMPOUND_TAG, new CompoundTag(), t -> t.getNode().getCoverManager().writeToNbt(), (t, v) -> t.getNode().getCoverManager().readFromNbt(v), (initial, p) -> {\n    });\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .addWatchedParameter(COVER_MANAGER)\n        .build();\n\n    public CableBlockEntity(BlockPos pos, BlockState state) {\n        super(RSBlockEntities.CABLE.get(), pos, state, SPEC, CableNetworkNode.class);\n    }\n\n    @Override\n    @Nonnull\n    public CableNetworkNode createNode(Level level, BlockPos pos) {\n        return new CableNetworkNode(level, pos);\n    }\n\n    @Nonnull\n    @Override\n    public ModelData getModelData() {\n        return ModelData.builder().with(CoverManager.PROPERTY, this.getNode().getCoverManager()).build();\n    }\n\n    @Override\n    public CompoundTag writeUpdate(CompoundTag tag) {\n        super.writeUpdate(tag);\n\n        tag.put(CoverManager.NBT_COVER_MANAGER, this.getNode().getCoverManager().writeToNbt());\n\n        return tag;\n    }\n\n    @Override\n    public void readUpdate(CompoundTag tag) {\n        super.readUpdate(tag);\n\n        this.getNode().getCoverManager().readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER));\n\n        requestModelDataUpdate();\n\n        LevelUtils.updateBlock(level, worldPosition);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/ClientNode.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport net.minecraft.world.item.ItemStack;\n\npublic class ClientNode {\n    private final ItemStack stack;\n    private final int energyUsage;\n    private int amount;\n\n    public ClientNode(ItemStack stack, int amount, int energyUsage) {\n        this.stack = stack;\n        this.amount = amount;\n        this.energyUsage = energyUsage;\n    }\n\n    public ItemStack getStack() {\n        return stack;\n    }\n\n    public int getAmount() {\n        return amount;\n    }\n\n    public void setAmount(int amount) {\n        this.amount = amount;\n    }\n\n    public int getEnergyUsage() {\n        return energyUsage;\n    }\n\n    @Override\n    public boolean equals(Object other) {\n        if (this == other) {\n            return true;\n        }\n\n        if (!(other instanceof ClientNode)) {\n            return false;\n        }\n\n        return energyUsage == ((ClientNode) other).energyUsage && API.instance().getComparer().isEqual(stack, ((ClientNode) other).stack);\n    }\n\n    @Override\n    public int hashCode() {\n        int result = stack.hashCode();\n        result = 31 * result + energyUsage;\n        return result;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/ConstructorBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.ConstructorNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;\nimport com.refinedmods.refinedstorage.blockentity.config.IComparable;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.syncher.EntityDataSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.model.data.ModelData;\nimport javax.annotation.Nonnull;\n\npublic class ConstructorBlockEntity extends NetworkNodeBlockEntity<ConstructorNetworkNode> {\n    public static final BlockEntitySynchronizationParameter<Integer, ConstructorBlockEntity> COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, \"constructor_compare\"));\n    public static final BlockEntitySynchronizationParameter<Integer, ConstructorBlockEntity> TYPE = IType.createParameter(new ResourceLocation(RS.ID, \"constructor_type\"));\n    public static final BlockEntitySynchronizationParameter<Boolean, ConstructorBlockEntity> DROP = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"constructor_drop\"), EntityDataSerializers.BOOLEAN, false, t -> t.getNode().isDrop(), (t, v) -> {\n        t.getNode().setDrop(v);\n        t.getNode().markDirty();\n    });\n\n    public static final BlockEntitySynchronizationParameter<CompoundTag, ConstructorBlockEntity> COVER_MANAGER = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"constructor_cover_manager\"), EntityDataSerializers.COMPOUND_TAG, new CompoundTag(),\n        t -> t.getNode().getCoverManager().writeToNbt(),\n        (t, v) -> t.getNode().getCoverManager().readFromNbt(v),\n        (initial, p) -> {\n        });\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .addWatchedParameter(COMPARE)\n        .addWatchedParameter(TYPE)\n        .addWatchedParameter(DROP)\n        .addWatchedParameter(COVER_MANAGER)\n        .build();\n\n    public ConstructorBlockEntity(BlockPos pos, BlockState state) {\n        super(RSBlockEntities.CONSTRUCTOR.get(), pos, state, SPEC, ConstructorNetworkNode.class);\n    }\n\n    @Override\n    @Nonnull\n    public ConstructorNetworkNode createNode(Level level, BlockPos pos) {\n        return new ConstructorNetworkNode(level, pos);\n    }\n\n    @Nonnull\n    @Override\n    public ModelData getModelData() {\n        return ModelData.builder().with(CoverManager.PROPERTY, this.getNode().getCoverManager()).build();\n    }\n\n    @Override\n    public CompoundTag writeUpdate(CompoundTag tag) {\n        super.writeUpdate(tag);\n\n        tag.put(CoverManager.NBT_COVER_MANAGER, this.getNode().getCoverManager().writeToNbt());\n\n        return tag;\n    }\n\n    @Override\n    public void readUpdate(CompoundTag tag) {\n        super.readUpdate(tag);\n\n        this.getNode().getCoverManager().readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER));\n\n        requestModelDataUpdate();\n\n        LevelUtils.updateBlock(level, worldPosition);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/ControllerBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.INetworkManager;\nimport com.refinedmods.refinedstorage.api.network.INetworkNodeGraphEntry;\nimport com.refinedmods.refinedstorage.api.network.NetworkType;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.Network;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.RootNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.config.IRedstoneConfigurable;\nimport com.refinedmods.refinedstorage.blockentity.config.RedstoneMode;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport com.refinedmods.refinedstorage.blockentity.data.RSSerializers;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.network.syncher.EntityDataSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.state.BlockState;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\n\nimport javax.annotation.Nonnull;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class ControllerBlockEntity extends BaseBlockEntity implements INetworkNodeProxy<RootNetworkNode>, IRedstoneConfigurable {\n    private static final Logger LOGGER = LogManager.getLogger();\n\n    public static final BlockEntitySynchronizationParameter<Integer, ControllerBlockEntity> REDSTONE_MODE = RedstoneMode.createParameter(new ResourceLocation(RS.ID, \"controller_redstone_mode\"));\n    public static final BlockEntitySynchronizationParameter<Integer, ControllerBlockEntity> ENERGY_USAGE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"controller_energy_usage\"), EntityDataSerializers.INT, 0, t -> t.getNetwork().getEnergyUsage());\n    public static final BlockEntitySynchronizationParameter<Integer, ControllerBlockEntity> ENERGY_STORED = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"controller_energy_stored\"), EntityDataSerializers.INT, 0, t -> t.getNetwork().getEnergyStorage().getEnergyStored());\n    public static final BlockEntitySynchronizationParameter<Integer, ControllerBlockEntity> ENERGY_CAPACITY = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"controller_energy_capacity\"), EntityDataSerializers.INT, 0, t -> t.getNetwork().getEnergyStorage().getMaxEnergyStored());\n    public static final BlockEntitySynchronizationParameter<List<ClientNode>, ControllerBlockEntity> NODES = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"controller_nodes\"), RSSerializers.CLIENT_NODE_SERIALIZER, new ArrayList<>(), ControllerBlockEntity::collectClientNodes);\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .addWatchedParameter(ENERGY_USAGE)\n        .addWatchedParameter(ENERGY_STORED)\n        .addParameter(ENERGY_CAPACITY)\n        .addParameter(NODES)\n        .build();\n\n    private final NetworkType type;\n    private INetwork removedNetwork;\n    private Network dummyNetwork;\n\n    public ControllerBlockEntity(NetworkType type, BlockPos pos, BlockState state) {\n        super(type == NetworkType.CREATIVE ? RSBlockEntities.CREATIVE_CONTROLLER.get() : RSBlockEntities.CONTROLLER.get(), pos, state, SPEC);\n        this.type = type;\n    }\n\n    private static List<ClientNode> collectClientNodes(ControllerBlockEntity blockEntity) {\n        List<ClientNode> nodes = new ArrayList<>();\n\n        for (INetworkNodeGraphEntry entry : blockEntity.getNetwork().getNodeGraph().all()) {\n            if (entry.getNode().isActive()) {\n                ItemStack stack = entry.getNode().getItemStack();\n\n                if (stack.isEmpty()) {\n                    continue;\n                }\n\n                ClientNode clientNode = new ClientNode(stack, 1, entry.getNode().getEnergyUsage());\n\n                if (nodes.contains(clientNode)) {\n                    ClientNode other = nodes.get(nodes.indexOf(clientNode));\n\n                    other.setAmount(other.getAmount() + 1);\n                } else {\n                    nodes.add(clientNode);\n                }\n            }\n        }\n\n        nodes.sort((a, b) -> Integer.compare(b.getEnergyUsage(), a.getEnergyUsage()));\n\n        return nodes;\n    }\n\n    public INetwork getNetwork() {\n        if (level.isClientSide) {\n            if (dummyNetwork == null) {\n                dummyNetwork = new Network(level, worldPosition, type);\n            }\n\n            return dummyNetwork;\n        }\n\n        INetworkManager manager = API.instance().getNetworkManager((ServerLevel) level);\n        INetwork network = manager.getNetwork(worldPosition);\n\n        if (network == null) {\n            LOGGER.warn(\"Expected a network @ {} but couldn't find it, creating a new one...\", worldPosition);\n            network = new Network(level, worldPosition, type);\n            manager.setNetwork(worldPosition, network);\n            manager.markForSaving();\n        }\n\n        return network;\n    }\n\n    @Override\n    public void clearRemoved() {\n        super.clearRemoved();\n\n        if (!level.isClientSide) {\n            INetworkManager manager = API.instance().getNetworkManager((ServerLevel) level);\n\n            if (manager.getNetwork(worldPosition) == null) {\n                manager.setNetwork(worldPosition, new Network(level, worldPosition, type));\n                manager.markForSaving();\n            }\n        }\n    }\n\n    @Override\n    public void onRemovedNotDueToChunkUnload() {\n        super.onRemovedNotDueToChunkUnload();\n\n        if (!level.isClientSide) {\n            INetworkManager manager = API.instance().getNetworkManager((ServerLevel) level);\n\n            INetwork network = manager.getNetwork(worldPosition);\n\n            removedNetwork = network;\n\n            manager.removeNetwork(worldPosition);\n            manager.markForSaving();\n\n            network.onRemoved();\n        }\n    }\n\n    public INetwork getRemovedNetwork() {\n        return removedNetwork;\n    }\n\n    @Override\n    @Nonnull\n    public RootNetworkNode getNode() {\n        return ((Network) getNetwork()).getRoot();\n    }\n\n    @Override\n    public RedstoneMode getRedstoneMode() {\n        return ((Network) getNetwork()).getRedstoneMode();\n    }\n\n    @Override\n    public void setRedstoneMode(RedstoneMode mode) {\n        ((Network) getNetwork()).setRedstoneMode(mode);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/CrafterBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.CrafterNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport com.refinedmods.refinedstorage.screen.CrafterBlockEntitySynchronizationClientListener;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.network.syncher.EntityDataSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.items.IItemHandler;\n\npublic class CrafterBlockEntity extends NetworkNodeBlockEntity<CrafterNetworkNode> {\n    public static final BlockEntitySynchronizationParameter<Integer, CrafterBlockEntity> MODE =\n        new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"crafter_mode\"),\n            EntityDataSerializers.INT, CrafterNetworkNode.CrafterMode.IGNORE.ordinal(),\n            t -> t.getNode().getMode().ordinal(),\n            (t, v) -> t.getNode().setMode(CrafterNetworkNode.CrafterMode.getById(v)));\n    private static final BlockEntitySynchronizationParameter<Boolean, CrafterBlockEntity> HAS_ROOT =\n        new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"crafter_has_root\"),\n            EntityDataSerializers.BOOLEAN, false, t -> t.getNode().getRootContainerNotSelf().isPresent(), null,\n            (t, v) -> new CrafterBlockEntitySynchronizationClientListener().onChanged(t, v));\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .addWatchedParameter(MODE)\n        .addParameter(HAS_ROOT)\n        .build();\n\n    public CrafterBlockEntity(BlockPos pos, BlockState state) {\n        super(RSBlockEntities.CRAFTER.get(), pos, state, SPEC, CrafterNetworkNode.class);\n    }\n\n    @Override\n    @Nonnull\n    public CrafterNetworkNode createNode(Level level, BlockPos pos) {\n        return new CrafterNetworkNode(level, pos);\n    }\n\n    public IItemHandler getPatterns(@Nullable Direction direction) {\n        if (direction != null && !direction.equals(this.getNode().getDirection())) {\n            return getNode().getPatternInventory();\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/CrafterManagerBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.CrafterManagerNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.screen.CrafterManagerScreen;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.network.syncher.EntityDataSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\n\npublic class CrafterManagerBlockEntity extends NetworkNodeBlockEntity<CrafterManagerNetworkNode> {\n    public static final BlockEntitySynchronizationParameter<Integer, CrafterManagerBlockEntity> SEARCH_BOX_MODE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"crafter_manager_search_box_mode\"), EntityDataSerializers.INT, 0, t -> t.getNode().getSearchBoxMode(), (t, v) -> {\n        if (IGrid.isValidSearchBoxMode(v)) {\n            t.getNode().setSearchBoxMode(v);\n            t.getNode().markDirty();\n        }\n    }, (initial, p) -> BaseScreen.executeLater(CrafterManagerScreen.class, crafterManager -> crafterManager.getSearchField().setMode(p)));\n    public static final BlockEntitySynchronizationParameter<Integer, CrafterManagerBlockEntity> SIZE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"crafter_manager_size\"), EntityDataSerializers.INT, IGrid.SIZE_STRETCH, t -> t.getNode().getSize(), (t, v) -> {\n        if (IGrid.isValidSize(v)) {\n            t.getNode().setSize(v);\n            t.getNode().markDirty();\n        }\n    }, (initial, p) -> BaseScreen.executeLater(CrafterManagerScreen.class, BaseScreen::init));\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .addWatchedParameter(SIZE)\n        .addWatchedParameter(SEARCH_BOX_MODE)\n        .build();\n\n    public CrafterManagerBlockEntity(BlockPos pos, BlockState state) {\n        super(RSBlockEntities.CRAFTER_MANAGER.get(), pos, state, SPEC, CrafterManagerNetworkNode.class);\n    }\n\n    @Override\n    public CrafterManagerNetworkNode createNode(Level level, BlockPos pos) {\n        return new CrafterManagerNetworkNode(level, pos);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/DestructorBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.DestructorNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;\nimport com.refinedmods.refinedstorage.blockentity.config.IComparable;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.syncher.EntityDataSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.model.data.ModelData;\nimport javax.annotation.Nonnull;\n\npublic class DestructorBlockEntity extends NetworkNodeBlockEntity<DestructorNetworkNode> {\n    public static final BlockEntitySynchronizationParameter<Integer, DestructorBlockEntity> COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, \"destructor_compare\"));\n    public static final BlockEntitySynchronizationParameter<Integer, DestructorBlockEntity> WHITELIST_BLACKLIST = IWhitelistBlacklist.createParameter(new ResourceLocation(RS.ID, \"destructor_whitelist_blacklist\"));\n    public static final BlockEntitySynchronizationParameter<Integer, DestructorBlockEntity> TYPE = IType.createParameter(new ResourceLocation(RS.ID, \"destructor_type\"));\n    public static final BlockEntitySynchronizationParameter<Boolean, DestructorBlockEntity> PICKUP = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"destructor_pickup\"), EntityDataSerializers.BOOLEAN, false, t -> t.getNode().isPickupItem(), (t, v) -> {\n        t.getNode().setPickupItem(v);\n        t.getNode().markDirty();\n    });\n\n    public static final BlockEntitySynchronizationParameter<CompoundTag, DestructorBlockEntity> COVER_MANAGER = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"destructor_cover_manager\"), EntityDataSerializers.COMPOUND_TAG, new CompoundTag(),\n        t -> t.getNode().getCoverManager().writeToNbt(),\n        (t, v) -> t.getNode().getCoverManager().readFromNbt(v),\n        (initial, p) -> {\n        });\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .addWatchedParameter(COMPARE)\n        .addWatchedParameter(WHITELIST_BLACKLIST)\n        .addWatchedParameter(TYPE)\n        .addWatchedParameter(PICKUP)\n        .addWatchedParameter(COVER_MANAGER)\n        .build();\n\n    public DestructorBlockEntity(BlockPos pos, BlockState state) {\n        super(RSBlockEntities.DESTRUCTOR.get(), pos, state, SPEC, DestructorNetworkNode.class);\n    }\n\n    @Override\n    @Nonnull\n    public DestructorNetworkNode createNode(Level level, BlockPos pos) {\n        return new DestructorNetworkNode(level, pos);\n    }\n\n    @Nonnull\n    @Override\n    public ModelData getModelData() {\n        return ModelData.builder().with(CoverManager.PROPERTY, this.getNode().getCoverManager()).build();\n    }\n\n    @Override\n    public CompoundTag writeUpdate(CompoundTag tag) {\n        super.writeUpdate(tag);\n\n        tag.put(CoverManager.NBT_COVER_MANAGER, this.getNode().getCoverManager().writeToNbt());\n\n        return tag;\n    }\n\n    @Override\n    public void readUpdate(CompoundTag tag) {\n        super.readUpdate(tag);\n\n        this.getNode().getCoverManager().readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER));\n\n        requestModelDataUpdate();\n\n        LevelUtils.updateBlock(level, worldPosition);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/DetectorBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.DetectorNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.config.IComparable;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.screen.DetectorScreen;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.syncher.EntityDataSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\n\nimport javax.annotation.Nonnull;\n\npublic class DetectorBlockEntity extends NetworkNodeBlockEntity<DetectorNetworkNode> {\n    public static final BlockEntitySynchronizationParameter<Integer, DetectorBlockEntity> COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, \"detector_compare\"));\n    public static final BlockEntitySynchronizationParameter<Integer, DetectorBlockEntity> TYPE = IType.createParameter(new ResourceLocation(RS.ID, \"detector_type\"));\n    public static final BlockEntitySynchronizationParameter<Integer, DetectorBlockEntity> MODE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"detector_mode\"), EntityDataSerializers.INT, 0, t -> t.getNode().getMode(), (t, v) -> {\n        if (v == DetectorNetworkNode.MODE_UNDER || v == DetectorNetworkNode.MODE_EQUAL || v == DetectorNetworkNode.MODE_ABOVE) {\n            t.getNode().setMode(v);\n            t.getNode().markDirty();\n        }\n    });\n    public static final BlockEntitySynchronizationParameter<Integer, DetectorBlockEntity> AMOUNT = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"detector_amount\"), EntityDataSerializers.INT, 0, t -> t.getNode().getAmount(), (t, v) -> {\n        t.getNode().setAmount(v);\n        t.getNode().markDirty();\n    }, (initial, value) -> BaseScreen.executeLater(DetectorScreen.class, detectorScreen -> detectorScreen.updateAmountField(value)));\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .addWatchedParameter(COMPARE)\n        .addWatchedParameter(TYPE)\n        .addWatchedParameter(MODE)\n        .addWatchedParameter(AMOUNT)\n        .build();\n\n    private static final String NBT_POWERED = \"Powered\";\n\n    public DetectorBlockEntity(BlockPos pos, BlockState state) {\n        super(RSBlockEntities.DETECTOR.get(), pos, state, SPEC, DetectorNetworkNode.class);\n    }\n\n    @Override\n    public void readUpdate(CompoundTag tag) {\n        getNode().setPowered(tag.getBoolean(NBT_POWERED));\n\n        super.readUpdate(tag);\n    }\n\n    @Override\n    public CompoundTag writeUpdate(CompoundTag tag) {\n        super.writeUpdate(tag);\n\n        tag.putBoolean(NBT_POWERED, getNode().isPowered());\n\n        return tag;\n    }\n\n    @Override\n    @Nonnull\n    public DetectorNetworkNode createNode(Level level, BlockPos pos) {\n        return new DetectorNetworkNode(level, pos);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/DiskDriveBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.DiskState;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.diskdrive.DiskDriveNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.config.*;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport com.refinedmods.refinedstorage.blockentity.data.RSSerializers;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.IntTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.nbt.Tag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.model.data.ModelData;\nimport net.neoforged.neoforge.client.model.data.ModelProperty;\nimport javax.annotation.Nonnull;\nimport java.util.Arrays;\n\npublic class DiskDriveBlockEntity extends NetworkNodeBlockEntity<DiskDriveNetworkNode> {\n    public static final BlockEntitySynchronizationParameter<Integer, DiskDriveBlockEntity> PRIORITY = IPrioritizable.createParameter(new ResourceLocation(RS.ID, \"disk_drive_priority\"));\n    public static final BlockEntitySynchronizationParameter<Integer, DiskDriveBlockEntity> COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, \"disk_drive_compare\"));\n    public static final BlockEntitySynchronizationParameter<Integer, DiskDriveBlockEntity> WHITELIST_BLACKLIST = IWhitelistBlacklist.createParameter(new ResourceLocation(RS.ID, \"disk_drive_whitelist_blacklist\"));\n    public static final BlockEntitySynchronizationParameter<Integer, DiskDriveBlockEntity> TYPE = IType.createParameter(new ResourceLocation(RS.ID, \"disk_drive_type\"));\n    public static final BlockEntitySynchronizationParameter<AccessType, DiskDriveBlockEntity> ACCESS_TYPE = IAccessType.createParameter(new ResourceLocation(RS.ID, \"disk_drive_access_type\"));\n    public static final BlockEntitySynchronizationParameter<Long, DiskDriveBlockEntity> STORED = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"disk_drive_stored\"), RSSerializers.LONG_SERIALIZER, 0L, t -> {\n        long stored = 0;\n\n        for (IStorageDisk storage : t.getNode().getItemDisks()) {\n            if (storage != null) {\n                stored += storage.getStored();\n            }\n        }\n\n        for (IStorageDisk storage : t.getNode().getFluidDisks()) {\n            if (storage != null) {\n                stored += storage.getStored();\n            }\n        }\n\n        return stored;\n    });\n    public static final BlockEntitySynchronizationParameter<Long, DiskDriveBlockEntity> CAPACITY = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"disk_drive_capacity\"), RSSerializers.LONG_SERIALIZER, 0L, t -> {\n        long capacity = 0;\n\n        for (IStorageDisk storage : t.getNode().getItemDisks()) {\n            if (storage != null) {\n                if (storage.getCapacity() == -1) {\n                    return -1L;\n                }\n\n                capacity += storage.getCapacity();\n            }\n        }\n\n        for (IStorageDisk storage : t.getNode().getFluidDisks()) {\n            if (storage != null) {\n                if (storage.getCapacity() == -1) {\n                    return -1L;\n                }\n\n                capacity += storage.getCapacity();\n            }\n        }\n\n        return capacity;\n    });\n    public static final ModelProperty<DiskState[]> DISK_STATE_PROPERTY = new ModelProperty<>();\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .addWatchedParameter(PRIORITY)\n        .addWatchedParameter(COMPARE)\n        .addWatchedParameter(WHITELIST_BLACKLIST)\n        .addWatchedParameter(TYPE)\n        .addWatchedParameter(ACCESS_TYPE)\n        .addWatchedParameter(STORED)\n        .addWatchedParameter(CAPACITY)\n        .build();\n\n    private static final String NBT_DISK_STATE = \"DiskStates\";\n\n    private final DiskState[] diskState = new DiskState[8];\n\n    public DiskDriveBlockEntity(BlockPos pos, BlockState state) {\n        super(RSBlockEntities.DISK_DRIVE.get(), pos, state, SPEC, DiskDriveNetworkNode.class);\n        Arrays.fill(diskState, DiskState.NONE);\n    }\n\n    @Override\n    public CompoundTag writeUpdate(CompoundTag tag) {\n        super.writeUpdate(tag);\n\n        ListTag list = new ListTag();\n\n        for (DiskState state : getNode().getDiskState()) {\n            list.add(IntTag.valueOf(state.ordinal()));\n        }\n\n        tag.put(NBT_DISK_STATE, list);\n\n        return tag;\n    }\n\n    @Override\n    public void readUpdate(CompoundTag tag) {\n        super.readUpdate(tag);\n\n        ListTag list = tag.getList(NBT_DISK_STATE, Tag.TAG_INT);\n\n        for (int i = 0; i < list.size(); ++i) {\n            diskState[i] = DiskState.values()[list.getInt(i)];\n        }\n\n        requestModelDataUpdate();\n\n        LevelUtils.updateBlock(level, worldPosition);\n    }\n\n    @Nonnull\n    @Override\n    public ModelData getModelData() {\n        return ModelData.builder().with(DISK_STATE_PROPERTY, diskState).build();\n    }\n\n    @Override\n    @Nonnull\n    public DiskDriveNetworkNode createNode(Level level, BlockPos pos) {\n        return new DiskDriveNetworkNode(level, pos);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/DiskManipulatorBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.DiskState;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.diskmanipulator.DiskManipulatorNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.config.IComparable;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.IntTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.nbt.Tag;\nimport net.minecraft.network.syncher.EntityDataSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.model.data.ModelData;\nimport net.neoforged.neoforge.client.model.data.ModelProperty;\nimport javax.annotation.Nonnull;\nimport java.util.Arrays;\n\npublic class DiskManipulatorBlockEntity extends NetworkNodeBlockEntity<DiskManipulatorNetworkNode> {\n    public static final BlockEntitySynchronizationParameter<Integer, DiskManipulatorBlockEntity> COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, \"disk_manipulator_compare\"));\n    public static final BlockEntitySynchronizationParameter<Integer, DiskManipulatorBlockEntity> WHITELIST_BLACKLIST = IWhitelistBlacklist.createParameter(new ResourceLocation(RS.ID, \"disk_manipulator_whitelist_blacklist\"));\n    public static final BlockEntitySynchronizationParameter<Integer, DiskManipulatorBlockEntity> TYPE = IType.createParameter(new ResourceLocation(RS.ID, \"disk_manipulator_type\"));\n    public static final BlockEntitySynchronizationParameter<Integer, DiskManipulatorBlockEntity> IO_MODE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"disk_manipulator_mode\"), EntityDataSerializers.INT, DiskManipulatorNetworkNode.IO_MODE_INSERT, t -> t.getNode().getIoMode(), (t, v) -> {\n        t.getNode().setIoMode(v);\n        t.getNode().markDirty();\n    });\n\n    public static final ModelProperty<DiskState[]> DISK_STATE_PROPERTY = new ModelProperty<>();\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .addWatchedParameter(COMPARE)\n        .addWatchedParameter(WHITELIST_BLACKLIST)\n        .addWatchedParameter(TYPE)\n        .addWatchedParameter(IO_MODE)\n        .build();\n\n    private static final String NBT_DISK_STATE = \"DiskStates\";\n\n    private final DiskState[] diskState = new DiskState[6];\n\n    public DiskManipulatorBlockEntity(BlockPos pos, BlockState state) {\n        super(RSBlockEntities.DISK_MANIPULATOR.get(), pos, state, SPEC, DiskManipulatorNetworkNode.class);\n        Arrays.fill(diskState, DiskState.NONE);\n    }\n\n    @Override\n    public CompoundTag writeUpdate(CompoundTag tag) {\n        super.writeUpdate(tag);\n\n        ListTag list = new ListTag();\n\n        for (DiskState state : getNode().getDiskState()) {\n            list.add(IntTag.valueOf(state.ordinal()));\n        }\n\n        tag.put(NBT_DISK_STATE, list);\n\n        return tag;\n    }\n\n    @Override\n    public void readUpdate(CompoundTag tag) {\n        super.readUpdate(tag);\n\n        ListTag list = tag.getList(NBT_DISK_STATE, Tag.TAG_INT);\n\n        for (int i = 0; i < list.size(); ++i) {\n            diskState[i] = DiskState.values()[list.getInt(i)];\n        }\n\n        requestModelDataUpdate();\n\n        LevelUtils.updateBlock(level, worldPosition);\n    }\n\n    @Nonnull\n    @Override\n    public ModelData getModelData() {\n        return ModelData.builder().with(DISK_STATE_PROPERTY, diskState).build();\n    }\n\n    @Override\n    @Nonnull\n    public DiskManipulatorNetworkNode createNode(Level level, BlockPos pos) {\n        return new DiskManipulatorNetworkNode(level, pos);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/ExporterBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.ExporterNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;\nimport com.refinedmods.refinedstorage.blockentity.config.IComparable;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.syncher.EntityDataSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.model.data.ModelData;\nimport javax.annotation.Nonnull;\n\npublic class ExporterBlockEntity extends NetworkNodeBlockEntity<ExporterNetworkNode> {\n\n    public static final BlockEntitySynchronizationParameter<CompoundTag, ExporterBlockEntity> COVER_MANAGER = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"exporter_cover_manager\"), EntityDataSerializers.COMPOUND_TAG, new CompoundTag(),\n        t -> t.getNode().getCoverManager().writeToNbt(),\n        (t, v) -> t.getNode().getCoverManager().readFromNbt(v),\n        (initial, p) -> {\n        });\n\n    public static final BlockEntitySynchronizationParameter<Integer, ExporterBlockEntity> COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, \"exporter_compare\"));\n    public static final BlockEntitySynchronizationParameter<Integer, ExporterBlockEntity> TYPE = IType.createParameter(new ResourceLocation(RS.ID, \"exporter_type\"));\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .addWatchedParameter(COMPARE)\n        .addWatchedParameter(TYPE)\n        .addWatchedParameter(COVER_MANAGER)\n        .build();\n\n    public ExporterBlockEntity(BlockPos pos, BlockState state) {\n        super(RSBlockEntities.EXPORTER.get(), pos, state, SPEC, ExporterNetworkNode.class);\n    }\n\n    @Override\n    @Nonnull\n    public ExporterNetworkNode createNode(Level level, BlockPos pos) {\n        return new ExporterNetworkNode(level, pos);\n    }\n\n    @Nonnull\n    @Override\n    public ModelData getModelData() {\n        return ModelData.builder().with(CoverManager.PROPERTY, this.getNode().getCoverManager()).build();\n    }\n\n    @Override\n    public CompoundTag writeUpdate(CompoundTag tag) {\n        super.writeUpdate(tag);\n\n        tag.put(CoverManager.NBT_COVER_MANAGER, this.getNode().getCoverManager().writeToNbt());\n\n        return tag;\n    }\n\n    @Override\n    public void readUpdate(CompoundTag tag) {\n        super.readUpdate(tag);\n\n        this.getNode().getCoverManager().readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER));\n\n        requestModelDataUpdate();\n\n        LevelUtils.updateBlock(level, worldPosition);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/ExternalStorageBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorage;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.ExternalStorageNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;\nimport com.refinedmods.refinedstorage.blockentity.config.*;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport com.refinedmods.refinedstorage.blockentity.data.RSSerializers;\nimport com.refinedmods.refinedstorage.config.ServerConfig;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.syncher.EntityDataSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.model.data.ModelData;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nonnull;\n\npublic class ExternalStorageBlockEntity extends NetworkNodeBlockEntity<ExternalStorageNetworkNode> {\n    public static final BlockEntitySynchronizationParameter<Integer, ExternalStorageBlockEntity> PRIORITY = IPrioritizable.createParameter(new ResourceLocation(RS.ID, \"external_storage_priority\"));\n    public static final BlockEntitySynchronizationParameter<Integer, ExternalStorageBlockEntity> COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, \"external_storage_compare\"));\n    public static final BlockEntitySynchronizationParameter<Integer, ExternalStorageBlockEntity> WHITELIST_BLACKLIST = IWhitelistBlacklist.createParameter(new ResourceLocation(RS.ID, \"external_storage_whitelist_blacklist\"));\n    public static final BlockEntitySynchronizationParameter<Integer, ExternalStorageBlockEntity> TYPE = IType.createParameter(new ResourceLocation(RS.ID, \"external_storage_type\"));\n    public static final BlockEntitySynchronizationParameter<AccessType, ExternalStorageBlockEntity> ACCESS_TYPE = IAccessType.createParameter(new ResourceLocation(RS.ID, \"external_storage_access_type\"));\n    public static final BlockEntitySynchronizationParameter<Long, ExternalStorageBlockEntity> STORED = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"external_storage_stored\"), RSSerializers.LONG_SERIALIZER, 0L, t -> {\n        long stored = 0;\n\n        for (IExternalStorage<ItemStack> storage : t.getNode().getItemStorages()) {\n            stored += storage.getStored();\n        }\n\n        for (IExternalStorage<FluidStack> storage : t.getNode().getFluidStorages()) {\n            stored += storage.getStored();\n        }\n\n        return stored;\n    });\n    public static final BlockEntitySynchronizationParameter<Long, ExternalStorageBlockEntity> CAPACITY = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"external_storage_capacity\"), RSSerializers.LONG_SERIALIZER, 0L, t -> {\n        long capacity = 0;\n\n        for (IExternalStorage<ItemStack> storage : t.getNode().getItemStorages()) {\n            capacity += storage.getCapacity();\n        }\n\n        for (IExternalStorage<FluidStack> storage : t.getNode().getFluidStorages()) {\n            capacity += storage.getCapacity();\n        }\n\n        return capacity;\n    });\n\n    public static final BlockEntitySynchronizationParameter<CompoundTag, ExternalStorageBlockEntity> COVER_MANAGER = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"external_storage_cover_manager\"), EntityDataSerializers.COMPOUND_TAG, new CompoundTag(), t -> t.getNode().getCoverManager().writeToNbt(), (t, v) -> t.getNode().getCoverManager().readFromNbt(v), (initial, p) -> {\n    });\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .addWatchedParameter(PRIORITY)\n        .addWatchedParameter(COMPARE)\n        .addWatchedParameter(WHITELIST_BLACKLIST)\n        .addWatchedParameter(STORED)\n        .addWatchedParameter(CAPACITY)\n        .addWatchedParameter(TYPE)\n        .addWatchedParameter(ACCESS_TYPE)\n        .addWatchedParameter(COVER_MANAGER)\n        .build();\n\n    public ExternalStorageBlockEntity(BlockPos pos, BlockState state) {\n        super(RSBlockEntities.EXTERNAL_STORAGE.get(), pos, state, SPEC, ExternalStorageNetworkNode.class);\n    }\n\n    @Override\n    @Nonnull\n    public ExternalStorageNetworkNode createNode(Level level, BlockPos pos) {\n        return new ExternalStorageNetworkNode(level, pos);\n    }\n\n    @Nonnull\n    @Override\n    public ModelData getModelData() {\n        return ModelData.builder().with(CoverManager.PROPERTY, this.getNode().getCoverManager()).build();\n    }\n\n    @Override\n    public CompoundTag writeUpdate(CompoundTag tag) {\n        super.writeUpdate(tag);\n\n        tag.put(CoverManager.NBT_COVER_MANAGER, this.getNode().getCoverManager().writeToNbt());\n\n        return tag;\n    }\n\n    @Override\n    public void readUpdate(CompoundTag tag) {\n        super.readUpdate(tag);\n\n        this.getNode().getCoverManager().readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER));\n\n        requestModelDataUpdate();\n\n        LevelUtils.updateBlock(level, worldPosition);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/FluidInterfaceBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.FluidInterfaceNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport com.refinedmods.refinedstorage.blockentity.data.RSSerializers;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nonnull;\n\npublic class FluidInterfaceBlockEntity extends NetworkNodeBlockEntity<FluidInterfaceNetworkNode> {\n    public static final BlockEntitySynchronizationParameter<FluidStack, FluidInterfaceBlockEntity> TANK_IN = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"fluid_interface_in\"), RSSerializers.FLUID_STACK_SERIALIZER, FluidStack.EMPTY, t -> t.getNode().getTankIn().getFluid());\n    public static final BlockEntitySynchronizationParameter<FluidStack, FluidInterfaceBlockEntity> TANK_OUT = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"fluid_interface_out\"), RSSerializers.FLUID_STACK_SERIALIZER, FluidStack.EMPTY, t -> t.getNode().getTankOut().getFluid());\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n            .addWatchedParameter(REDSTONE_MODE)\n            .addParameter(TANK_IN)\n            .addParameter(TANK_OUT)\n            .build();\n\n    public FluidInterfaceBlockEntity(BlockPos pos, BlockState state) {\n        super(RSBlockEntities.FLUID_INTERFACE.get(), pos, state, SPEC, FluidInterfaceNetworkNode.class);\n    }\n\n    @Override\n    @Nonnull\n    public FluidInterfaceNetworkNode createNode(Level level, BlockPos pos) {\n        return new FluidInterfaceNetworkNode(level, pos);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/FluidStorageBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.storage.FluidStorageNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType;\nimport com.refinedmods.refinedstorage.blockentity.config.IAccessType;\nimport com.refinedmods.refinedstorage.blockentity.config.IComparable;\nimport com.refinedmods.refinedstorage.blockentity.config.IPrioritizable;\nimport com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport com.refinedmods.refinedstorage.blockentity.data.RSSerializers;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntityType;\nimport net.minecraft.world.level.block.state.BlockState;\n\nimport javax.annotation.Nonnull;\n\npublic class FluidStorageBlockEntity extends NetworkNodeBlockEntity<FluidStorageNetworkNode> {\n    public static final BlockEntitySynchronizationParameter<Integer, FluidStorageBlockEntity> PRIORITY = IPrioritizable.createParameter(new ResourceLocation(RS.ID, \"fluid_storage_priority\"));\n    public static final BlockEntitySynchronizationParameter<Integer, FluidStorageBlockEntity> COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, \"fluid_storage_compare\"));\n    public static final BlockEntitySynchronizationParameter<Integer, FluidStorageBlockEntity> WHITELIST_BLACKLIST = IWhitelistBlacklist.createParameter(new ResourceLocation(RS.ID, \"fluid_storage_whitelist_blacklist\"));\n    public static final BlockEntitySynchronizationParameter<AccessType, FluidStorageBlockEntity> ACCESS_TYPE = IAccessType.createParameter(new ResourceLocation(RS.ID, \"fluid_storage_access_type\"));\n    public static final BlockEntitySynchronizationParameter<Long, FluidStorageBlockEntity> STORED = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"fluid_storage_stored\"), RSSerializers.LONG_SERIALIZER, 0L, t -> t.getNode().getStorage() != null ? (long) t.getNode().getStorage().getStored() : 0);\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .addWatchedParameter(PRIORITY)\n        .addWatchedParameter(COMPARE)\n        .addWatchedParameter(WHITELIST_BLACKLIST)\n        .addWatchedParameter(STORED)\n        .addWatchedParameter(ACCESS_TYPE)\n        .build();\n\n    private final FluidStorageType type;\n\n    public FluidStorageBlockEntity(FluidStorageType type, BlockPos pos, BlockState state) {\n        super(getType(type), pos, state, SPEC, FluidStorageNetworkNode.class);\n        this.type = type;\n    }\n\n    public static BlockEntityType<FluidStorageBlockEntity> getType(FluidStorageType type) {\n        return switch (type) {\n            case SIXTY_FOUR_K -> RSBlockEntities.SIXTY_FOUR_K_FLUID_STORAGE_BLOCK.get();\n            case TWO_HUNDRED_FIFTY_SIX_K -> RSBlockEntities.TWO_HUNDRED_FIFTY_SIX_K_FLUID_STORAGE_BLOCK.get();\n            case THOUSAND_TWENTY_FOUR_K -> RSBlockEntities.THOUSAND_TWENTY_FOUR_K_FLUID_STORAGE_BLOCK.get();\n            case FOUR_THOUSAND_NINETY_SIX_K -> RSBlockEntities.FOUR_THOUSAND_NINETY_SIX_K_FLUID_STORAGE_BLOCK.get();\n            case CREATIVE -> RSBlockEntities.CREATIVE_FLUID_STORAGE_BLOCK.get();\n        };\n    }\n\n    public FluidStorageType getFluidStorageType() {\n        return type;\n    }\n\n    @Override\n    @Nonnull\n    public FluidStorageNetworkNode createNode(Level level, BlockPos pos) {\n        return new FluidStorageNetworkNode(level, pos, type);\n    }\n}\n\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/ImporterBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.ImporterNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;\nimport com.refinedmods.refinedstorage.blockentity.config.IComparable;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.syncher.EntityDataSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.model.data.ModelData;\nimport javax.annotation.Nonnull;\n\npublic class ImporterBlockEntity extends NetworkNodeBlockEntity<ImporterNetworkNode> {\n    public static final BlockEntitySynchronizationParameter<Integer, ImporterBlockEntity> COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, \"importer_compare\"));\n    public static final BlockEntitySynchronizationParameter<Integer, ImporterBlockEntity> WHITELIST_BLACKLIST = IWhitelistBlacklist.createParameter(new ResourceLocation(RS.ID, \"importer_whitelist_blacklist\"));\n    public static final BlockEntitySynchronizationParameter<Integer, ImporterBlockEntity> TYPE = IType.createParameter(new ResourceLocation(RS.ID, \"importer_type\"));\n    public static final BlockEntitySynchronizationParameter<CompoundTag, ImporterBlockEntity> COVER_MANAGER = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"importer_cover_manager\"), EntityDataSerializers.COMPOUND_TAG, new CompoundTag(), t -> t.getNode().getCoverManager().writeToNbt(), (t, v) -> t.getNode().getCoverManager().readFromNbt(v), (initial, p) -> {\n    });\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .addWatchedParameter(COMPARE)\n        .addWatchedParameter(WHITELIST_BLACKLIST)\n        .addWatchedParameter(TYPE)\n        .addWatchedParameter(COVER_MANAGER)\n        .build();\n\n    public ImporterBlockEntity(BlockPos pos, BlockState state) {\n        super(RSBlockEntities.IMPORTER.get(), pos, state, SPEC, ImporterNetworkNode.class);\n    }\n\n    @Override\n    @Nonnull\n    public ImporterNetworkNode createNode(Level level, BlockPos pos) {\n        return new ImporterNetworkNode(level, pos);\n    }\n\n    @Nonnull\n    @Override\n    public ModelData getModelData() {\n        return ModelData.builder().with(CoverManager.PROPERTY, this.getNode().getCoverManager()).build();\n    }\n\n    @Override\n    public CompoundTag writeUpdate(CompoundTag tag) {\n        super.writeUpdate(tag);\n\n        tag.put(CoverManager.NBT_COVER_MANAGER, this.getNode().getCoverManager().writeToNbt());\n\n        return tag;\n    }\n\n    @Override\n    public void readUpdate(CompoundTag tag) {\n        super.readUpdate(tag);\n\n        this.getNode().getCoverManager().readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER));\n\n        requestModelDataUpdate();\n\n        LevelUtils.updateBlock(level, worldPosition);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/InterfaceBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.InterfaceNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.config.IComparable;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\nimport javax.annotation.Nonnull;\n\npublic class InterfaceBlockEntity extends NetworkNodeBlockEntity<InterfaceNetworkNode> {\n    public static final BlockEntitySynchronizationParameter<Integer, InterfaceBlockEntity> COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, \"interface_compare\"));\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .addWatchedParameter(COMPARE)\n        .build();\n\n    public InterfaceBlockEntity(BlockPos pos, BlockState state) {\n        super(RSBlockEntities.INTERFACE.get(), pos, state, SPEC, InterfaceNetworkNode.class);\n    }\n\n    @Override\n    @Nonnull\n    public InterfaceNetworkNode createNode(Level level, BlockPos pos) {\n        return new InterfaceNetworkNode(level, pos);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/NetworkNodeBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNodeManager;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.NetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.config.IRedstoneConfigurable;\nimport com.refinedmods.refinedstorage.blockentity.config.RedstoneMode;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntityType;\nimport net.minecraft.world.level.block.state.BlockState;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\npublic abstract class NetworkNodeBlockEntity<N extends NetworkNode> extends BaseBlockEntity implements INetworkNodeProxy<N>, IRedstoneConfigurable {\n    public static final BlockEntitySynchronizationParameter<Integer, NetworkNodeBlockEntity<?>> REDSTONE_MODE = RedstoneMode.createParameter(new ResourceLocation(RS.ID, \"redstone_mode\"));\n\n    private final Class<N> networkNodeClass;\n    private N clientNode;\n    private N removedNode;\n\n    private static final Logger LOGGER = LogManager.getLogger();\n\n    protected NetworkNodeBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state, BlockEntitySynchronizationSpec syncSpec,\n                                     Class<N> networkNodeClass) {\n        super(type, pos, state, syncSpec);\n        this.networkNodeClass = networkNodeClass;\n    }\n\n    @Override\n    public RedstoneMode getRedstoneMode() {\n        return getNode().getRedstoneMode();\n    }\n\n    @Override\n    public void setRedstoneMode(RedstoneMode mode) {\n        getNode().setRedstoneMode(mode);\n    }\n\n    @Override\n    @Nonnull\n    @SuppressWarnings(\"unchecked\")\n    public N getNode() {\n        if (level.isClientSide) {\n            if (clientNode == null) {\n                clientNode = createNode(level, worldPosition);\n            }\n\n            return clientNode;\n        }\n\n        INetworkNodeManager manager = API.instance().getNetworkNodeManager((ServerLevel) level);\n\n        try {\n            INetworkNode node = manager.getNode(worldPosition);\n\n            if (node == null) {\n                LOGGER.warn(\"Expected a node @ {} but couldn't find it, creating a new one...\", worldPosition);\n                node = createAndSetNode(manager);\n            }\n\n            return doCast(node);\n        } catch (ClassCastException e) {\n            LOGGER.warn(\"Node @ {} got desynced with it's block entity container, recreating\", worldPosition, e);\n            return (N) createAndSetNode(manager);\n        }\n    }\n\n    private N doCast(INetworkNode node) {\n        if (networkNodeClass == null) {\n            return (N) node;\n        }\n        return networkNodeClass.cast(node);\n    }\n\n    private INetworkNode createAndSetNode(INetworkNodeManager manager) {\n        INetworkNode node = createNode(level, worldPosition);\n        manager.setNode(worldPosition, node);\n        manager.markForSaving();\n        return node;\n    }\n\n    @Override\n    public void clearRemoved() {\n        super.clearRemoved();\n\n        if (!level.isClientSide) {\n            INetworkNodeManager manager = API.instance().getNetworkNodeManager((ServerLevel) level);\n\n            if (manager.getNode(worldPosition) == null) {\n                manager.setNode(worldPosition, createNode(level, worldPosition));\n                manager.markForSaving();\n            }\n        }\n    }\n\n    @Override\n    public void onRemovedNotDueToChunkUnload() {\n        super.onRemovedNotDueToChunkUnload();\n\n        if (!level.isClientSide) {\n            INetworkNodeManager manager = API.instance().getNetworkNodeManager((ServerLevel) level);\n\n            INetworkNode node = manager.getNode(worldPosition);\n\n            if (node != null) {\n                try {\n                    removedNode = doCast(node);\n                } catch (ClassCastException e) {\n                    removedNode = null;\n                }\n            }\n\n            manager.removeNode(worldPosition);\n            manager.markForSaving();\n\n            if (node != null && node.getNetwork() != null) {\n                node.getNetwork().getNodeGraph().invalidate(Action.PERFORM, node.getNetwork().getLevel(), node.getNetwork().getPosition());\n            }\n        }\n    }\n\n    public N getRemovedNode() {\n        return removedNode;\n    }\n\n    public abstract N createNode(Level level, BlockPos pos);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/NetworkReceiverBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.NetworkReceiverNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\n\nimport javax.annotation.Nonnull;\n\npublic class NetworkReceiverBlockEntity extends NetworkNodeBlockEntity<NetworkReceiverNetworkNode> {\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .build();\n\n    public NetworkReceiverBlockEntity(BlockPos pos, BlockState state) {\n        super(RSBlockEntities.NETWORK_RECEIVER.get(), pos, state, SPEC, NetworkReceiverNetworkNode.class);\n    }\n\n    @Override\n    @Nonnull\n    public NetworkReceiverNetworkNode createNode(Level level, BlockPos pos) {\n        return new NetworkReceiverNetworkNode(level, pos);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/NetworkTransmitterBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.NetworkTransmitterNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport com.refinedmods.refinedstorage.blockentity.data.RSSerializers;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.network.syncher.EntityDataSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\nimport javax.annotation.Nonnull;\nimport java.util.Optional;\n\npublic class NetworkTransmitterBlockEntity extends NetworkNodeBlockEntity<NetworkTransmitterNetworkNode> {\n    public static final BlockEntitySynchronizationParameter<Integer, NetworkTransmitterBlockEntity> DISTANCE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"network_transmitter_distance\"), EntityDataSerializers.INT, 0, t -> t.getNode().getDistance());\n    public static final BlockEntitySynchronizationParameter<Optional<ResourceLocation>, NetworkTransmitterBlockEntity> RECEIVER_DIMENSION = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"network_transmitter_receiver_dimension\"), RSSerializers.OPTIONAL_RESOURCE_LOCATION_SERIALIZER, Optional.empty(), t -> {\n        if (t.getNode().getReceiverDimension() != null) {\n            return Optional.of(t.getNode().getReceiverDimension().location());\n        }\n\n        return Optional.empty();\n    });\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .addWatchedParameter(DISTANCE)\n        .addWatchedParameter(RECEIVER_DIMENSION)\n        .build();\n\n    public NetworkTransmitterBlockEntity(BlockPos pos, BlockState state) {\n        super(RSBlockEntities.NETWORK_TRANSMITTER.get(), pos, state, SPEC, NetworkTransmitterNetworkNode.class);\n    }\n\n    @Override\n    @Nonnull\n    public NetworkTransmitterNetworkNode createNode(Level level, BlockPos pos) {\n        return new NetworkTransmitterNetworkNode(level, pos);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/RelayBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.RelayNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\n\nimport javax.annotation.Nonnull;\n\npublic class RelayBlockEntity extends NetworkNodeBlockEntity<RelayNetworkNode> {\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .build();\n\n    public RelayBlockEntity(BlockPos pos, BlockState state) {\n        super(RSBlockEntities.RELAY.get(), pos, state, SPEC, RelayNetworkNode.class);\n    }\n\n    @Override\n    @Nonnull\n    public RelayNetworkNode createNode(Level level, BlockPos pos) {\n        return new RelayNetworkNode(level, pos);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/SecurityManagerBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.SecurityManagerNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\n\nimport javax.annotation.Nonnull;\n\npublic class SecurityManagerBlockEntity extends NetworkNodeBlockEntity<SecurityManagerNetworkNode> {\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .build();\n\n    public SecurityManagerBlockEntity(BlockPos pos, BlockState state) {\n        super(RSBlockEntities.SECURITY_MANAGER.get(), pos, state, SPEC, SecurityManagerNetworkNode.class);\n    }\n\n    @Override\n    @Nonnull\n    public SecurityManagerNetworkNode createNode(Level level, BlockPos pos) {\n        return new SecurityManagerNetworkNode(level, pos);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/StorageBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.storage.StorageNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType;\nimport com.refinedmods.refinedstorage.blockentity.config.IAccessType;\nimport com.refinedmods.refinedstorage.blockentity.config.IComparable;\nimport com.refinedmods.refinedstorage.blockentity.config.IPrioritizable;\nimport com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport com.refinedmods.refinedstorage.blockentity.data.RSSerializers;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntityType;\nimport net.minecraft.world.level.block.state.BlockState;\n\nimport javax.annotation.Nonnull;\n\npublic class StorageBlockEntity extends NetworkNodeBlockEntity<StorageNetworkNode> {\n    public static final BlockEntitySynchronizationParameter<Integer, StorageBlockEntity> PRIORITY = IPrioritizable.createParameter(new ResourceLocation(RS.ID, \"storage_priority\"));\n    public static final BlockEntitySynchronizationParameter<Integer, StorageBlockEntity> COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, \"storage_compare\"));\n    public static final BlockEntitySynchronizationParameter<Integer, StorageBlockEntity> WHITELIST_BLACKLIST = IWhitelistBlacklist.createParameter(new ResourceLocation(RS.ID, \"storage_whitelist_blacklist\"));\n    public static final BlockEntitySynchronizationParameter<AccessType, StorageBlockEntity> ACCESS_TYPE = IAccessType.createParameter(new ResourceLocation(RS.ID, \"storage_access_type\"));\n    public static final BlockEntitySynchronizationParameter<Long, StorageBlockEntity> STORED = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"storage_stored\"), RSSerializers.LONG_SERIALIZER, 0L, t -> t.getNode().getStorage() != null ? (long) t.getNode().getStorage().getStored() : 0);\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .addWatchedParameter(PRIORITY)\n        .addWatchedParameter(COMPARE)\n        .addWatchedParameter(WHITELIST_BLACKLIST)\n        .addWatchedParameter(STORED)\n        .addWatchedParameter(ACCESS_TYPE)\n        .build();\n\n    private final ItemStorageType type;\n\n    public StorageBlockEntity(ItemStorageType type, BlockPos pos, BlockState state) {\n        super(getType(type), pos, state, SPEC, StorageNetworkNode.class);\n        this.type = type;\n    }\n\n    public static BlockEntityType<StorageBlockEntity> getType(ItemStorageType type) {\n        return switch (type) {\n            case ONE_K -> RSBlockEntities.ONE_K_STORAGE_BLOCK.get();\n            case FOUR_K -> RSBlockEntities.FOUR_K_STORAGE_BLOCK.get();\n            case SIXTEEN_K -> RSBlockEntities.SIXTEEN_K_STORAGE_BLOCK.get();\n            case SIXTY_FOUR_K -> RSBlockEntities.SIXTY_FOUR_K_STORAGE_BLOCK.get();\n            case CREATIVE -> RSBlockEntities.CREATIVE_STORAGE_BLOCK.get();\n        };\n    }\n\n    public ItemStorageType getItemStorageType() {\n        return type;\n    }\n\n    @Override\n    @Nonnull\n    public StorageNetworkNode createNode(Level level, BlockPos pos) {\n        return new StorageNetworkNode(level, pos, type);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/StorageMonitorBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.StorageMonitorNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.config.IComparable;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport com.refinedmods.refinedstorage.config.ServerConfig;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nullable;\n\npublic class StorageMonitorBlockEntity extends NetworkNodeBlockEntity<StorageMonitorNetworkNode> {\n    public static final BlockEntitySynchronizationParameter<Integer, StorageMonitorBlockEntity> COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, \"storage_monitor_compare\"));\n    public static final BlockEntitySynchronizationParameter<Integer, StorageMonitorBlockEntity> TYPE = IType.createParameter(new ResourceLocation(RS.ID, \"storage_monitor_type\"));\n\n    private static final String NBT_TYPE = \"Type\";\n    private static final String NBT_FLUIDSTACK = \"FluidStack\";\n    private static final String NBT_STACK = \"Stack\";\n    private static final String NBT_AMOUNT = \"Amount\";\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .addWatchedParameter(COMPARE)\n        .addWatchedParameter(TYPE)\n        .build();\n\n    private int type;\n    private int amount;\n    @Nullable\n    private ItemStack itemStack = ItemStack.EMPTY;\n    @Nullable\n    private FluidStack fluidStack = FluidStack.EMPTY;\n\n    public StorageMonitorBlockEntity(BlockPos pos, BlockState state) {\n        super(RSBlockEntities.STORAGE_MONITOR.get(), pos, state, SPEC, StorageMonitorNetworkNode.class);\n    }\n\n    @Override\n    public StorageMonitorNetworkNode createNode(Level level, BlockPos pos) {\n        return new StorageMonitorNetworkNode(level, pos);\n    }\n\n    @Override\n    public CompoundTag writeUpdate(CompoundTag tag) {\n        super.writeUpdate(tag);\n\n        ItemStack stack = getNode().getItemFilters().getStackInSlot(0);\n\n        if (!stack.isEmpty()) {\n            tag.put(NBT_STACK, stack.save(new CompoundTag()));\n        }\n\n        FluidStack fluid = getNode().getFluidFilters().getFluid(0);\n        if (!fluid.isEmpty()) {\n            tag.put(NBT_FLUIDSTACK, fluid.writeToNBT(new CompoundTag()));\n        }\n\n        tag.putInt(NBT_TYPE, getNode().getType());\n        tag.putInt(NBT_AMOUNT, getNode().getAmount());\n\n        return tag;\n    }\n\n    @Override\n    public void readUpdate(CompoundTag tag) {\n        super.readUpdate(tag);\n        fluidStack = tag.contains(NBT_FLUIDSTACK) ? FluidStack.loadFluidStackFromNBT(tag.getCompound(NBT_FLUIDSTACK)) : FluidStack.EMPTY;\n        itemStack = tag.contains(NBT_STACK) ? ItemStack.of(tag.getCompound(NBT_STACK)) : ItemStack.EMPTY;\n        type = tag.contains(NBT_TYPE) ? tag.getInt(NBT_TYPE) : IType.ITEMS;\n        amount = tag.getInt(NBT_AMOUNT);\n    }\n\n    public int getAmount() {\n        return amount;\n    }\n\n    public int getStackType() {\n        return type;\n    }\n\n    @Nullable\n    public ItemStack getItemStack() {\n        return itemStack;\n    }\n\n    @Nullable\n    public FluidStack getFluidStack() {\n        return fluidStack;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/WirelessTransmitterBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.WirelessTransmitterNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.network.syncher.EntityDataSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\n\nimport javax.annotation.Nonnull;\n\npublic class WirelessTransmitterBlockEntity extends NetworkNodeBlockEntity<WirelessTransmitterNetworkNode> {\n    public static final BlockEntitySynchronizationParameter<Integer, WirelessTransmitterBlockEntity> RANGE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"wireless_transmitter_range\"), EntityDataSerializers.INT, 0, t -> t.getNode().getRange());\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .addWatchedParameter(RANGE)\n        .build();\n\n    public WirelessTransmitterBlockEntity(BlockPos pos, BlockState state) {\n        super(RSBlockEntities.WIRELESS_TRANSMITTER.get(), pos, state, SPEC, WirelessTransmitterNetworkNode.class);\n    }\n\n    @Override\n    @Nonnull\n    public WirelessTransmitterNetworkNode createNode(Level level, BlockPos pos) {\n        return new WirelessTransmitterNetworkNode(level, pos);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/config/IAccessType.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.config;\n\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy;\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.RSSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.block.entity.BlockEntity;\n\npublic interface IAccessType {\n    static <T extends BlockEntity & INetworkNodeProxy<?>> BlockEntitySynchronizationParameter<AccessType, T> createParameter(ResourceLocation id) {\n        return new BlockEntitySynchronizationParameter<>(id, RSSerializers.ACCESS_TYPE_SERIALIZER, AccessType.INSERT_EXTRACT, t -> ((IAccessType) t.getNode()).getAccessType(), (t, v) -> ((IAccessType) t.getNode()).setAccessType(v));\n    }\n\n    AccessType getAccessType();\n\n    void setAccessType(AccessType accessType);\n}"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/config/IComparable.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.config;\n\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport net.minecraft.network.syncher.EntityDataSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.block.entity.BlockEntity;\n\npublic interface IComparable {\n    static <T extends BlockEntity & INetworkNodeProxy<?>> BlockEntitySynchronizationParameter<Integer, T> createParameter(ResourceLocation id) {\n        return new BlockEntitySynchronizationParameter<>(id, EntityDataSerializers.INT, 0, t -> ((IComparable) t.getNode()).getCompare(), (t, v) -> ((IComparable) t.getNode()).setCompare(v));\n    }\n\n    int getCompare();\n\n    void setCompare(int compare);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/config/IPrioritizable.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.config;\n\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport net.minecraft.network.syncher.EntityDataSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.block.entity.BlockEntity;\n\npublic interface IPrioritizable {\n    static <T extends BlockEntity & INetworkNodeProxy<?>> BlockEntitySynchronizationParameter<Integer, T> createParameter(ResourceLocation id) {\n        return new BlockEntitySynchronizationParameter<>(id, EntityDataSerializers.INT, 0, t -> ((IPrioritizable) t.getNode()).getPriority(), (t, v) -> ((IPrioritizable) t.getNode()).setPriority(v));\n    }\n\n    int getPriority();\n\n    void setPriority(int priority);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/config/IRedstoneConfigurable.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.config;\n\npublic interface IRedstoneConfigurable {\n    RedstoneMode getRedstoneMode();\n\n    void setRedstoneMode(RedstoneMode mode);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/config/IType.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.config;\n\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationClientListener;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport net.minecraft.network.syncher.EntityDataSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport javax.annotation.Nullable;\n\npublic interface IType {\n    int ITEMS = 0;\n    int FLUIDS = 1;\n\n    static <T extends BlockEntity & INetworkNodeProxy<?>> BlockEntitySynchronizationParameter<Integer, T> createParameter(ResourceLocation id, @Nullable BlockEntitySynchronizationClientListener<Integer> clientListener) {\n        return new BlockEntitySynchronizationParameter<>(id, EntityDataSerializers.INT, ITEMS, t -> ((IType) t.getNode()).getType(), (t, v) -> {\n            if (v == IType.ITEMS || v == IType.FLUIDS) {\n                ((IType) t.getNode()).setType(v);\n            }\n        }, clientListener);\n    }\n\n    static <T extends BlockEntity & INetworkNodeProxy<?>> BlockEntitySynchronizationParameter<Integer, T> createParameter(ResourceLocation id) {\n        return createParameter(id, null);\n    }\n\n    int getType();\n\n    void setType(int type);\n\n    IItemHandlerModifiable getItemFilters();\n\n    FluidInventory getFluidFilters();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/config/IWhitelistBlacklist.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.config;\n\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport net.minecraft.network.syncher.EntityDataSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.items.IItemHandler;\n\npublic interface IWhitelistBlacklist {\n    int WHITELIST = 0;\n    int BLACKLIST = 1;\n\n    static <T extends BlockEntity & INetworkNodeProxy<?>> BlockEntitySynchronizationParameter<Integer, T> createParameter(ResourceLocation id) {\n        return new BlockEntitySynchronizationParameter<>(id, EntityDataSerializers.INT, 0, t -> ((IWhitelistBlacklist) t.getNode()).getWhitelistBlacklistMode(), (t, v) -> {\n            if (v == WHITELIST || v == BLACKLIST) {\n                ((IWhitelistBlacklist) t.getNode()).setWhitelistBlacklistMode(v);\n            }\n        });\n    }\n\n    static boolean acceptsItem(IItemHandler filters, int mode, int compare, ItemStack stack) {\n        if (mode == WHITELIST) {\n            for (int i = 0; i < filters.getSlots(); ++i) {\n                ItemStack slot = filters.getStackInSlot(i);\n\n                if (API.instance().getComparer().isEqual(slot, stack, compare)) {\n                    return true;\n                }\n            }\n\n            return false;\n        } else if (mode == BLACKLIST) {\n            for (int i = 0; i < filters.getSlots(); ++i) {\n                ItemStack slot = filters.getStackInSlot(i);\n\n                if (API.instance().getComparer().isEqual(slot, stack, compare)) {\n                    return false;\n                }\n            }\n\n            return true;\n        }\n\n        return false;\n    }\n\n    static boolean acceptsFluid(FluidInventory filters, int mode, int compare, FluidStack stack) {\n        if (mode == WHITELIST) {\n            for (int i = 0; i < filters.getSlots(); ++i) {\n                FluidStack slot = filters.getFluid(i);\n\n                if (!slot.isEmpty() && API.instance().getComparer().isEqual(slot, stack, compare)) {\n                    return true;\n                }\n            }\n\n            return false;\n        } else if (mode == BLACKLIST) {\n            for (int i = 0; i < filters.getSlots(); ++i) {\n                FluidStack slot = filters.getFluid(i);\n\n                if (!slot.isEmpty() && API.instance().getComparer().isEqual(slot, stack, compare)) {\n                    return false;\n                }\n            }\n\n            return true;\n        }\n\n        return false;\n    }\n\n    int getWhitelistBlacklistMode();\n\n    void setWhitelistBlacklistMode(int mode);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/config/RedstoneMode.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.config;\n\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.syncher.EntityDataSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.block.entity.BlockEntity;\n\npublic enum RedstoneMode {\n    IGNORE, HIGH, LOW;\n\n    private static final String NBT = \"RedstoneMode\";\n\n    public static RedstoneMode read(CompoundTag tag) {\n        if (tag.contains(RedstoneMode.NBT)) {\n            return getById(tag.getInt(NBT));\n        }\n\n        return IGNORE;\n    }\n\n    public static RedstoneMode getById(int id) {\n        return id < 0 || id >= values().length ? IGNORE : values()[id];\n    }\n\n    public static <T extends BlockEntity & IRedstoneConfigurable> BlockEntitySynchronizationParameter<Integer, T> createParameter(ResourceLocation id) {\n        return new BlockEntitySynchronizationParameter<>(id, EntityDataSerializers.INT, IGNORE.ordinal(), t -> t.getRedstoneMode().ordinal(), (t, v) -> t.setRedstoneMode(RedstoneMode.getById(v)));\n    }\n\n    public boolean isEnabled(boolean powered) {\n        switch (this) {\n            case IGNORE:\n                return true;\n            case HIGH:\n                return powered;\n            case LOW:\n                return !powered;\n            default:\n                return false;\n        }\n    }\n\n    public void write(CompoundTag tag) {\n        tag.putInt(NBT, ordinal());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/craftingmonitor/CraftingMonitorBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.craftingmonitor;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.CraftingMonitorNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.network.syncher.EntityDataSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\n\nimport javax.annotation.Nonnull;\nimport java.util.Optional;\nimport java.util.UUID;\n\npublic class CraftingMonitorBlockEntity extends NetworkNodeBlockEntity<CraftingMonitorNetworkNode> {\n    public static final BlockEntitySynchronizationParameter<Optional<UUID>, CraftingMonitorBlockEntity> TAB_SELECTED = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"crafting_monitor_tab_selected\"), EntityDataSerializers.OPTIONAL_UUID, Optional.empty(), t -> t.getNode().getTabSelected(), (t, v) -> {\n        if (v.isPresent() && t.getNode().getTabSelected().isPresent() && v.get().equals(t.getNode().getTabSelected().get())) {\n            t.getNode().setTabSelected(Optional.empty());\n        } else {\n            t.getNode().setTabSelected(v);\n        }\n\n        t.getNode().markDirty();\n    });\n\n    public static final BlockEntitySynchronizationParameter<Integer, CraftingMonitorBlockEntity> TAB_PAGE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"crafting_monitor_tab_page\"), EntityDataSerializers.INT, 0, t -> t.getNode().getTabPage(), (t, v) -> {\n        if (v >= 0) {\n            t.getNode().setTabPage(v);\n            t.getNode().markDirty();\n        }\n    });\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .addWatchedParameter(TAB_SELECTED)\n        .addWatchedParameter(TAB_PAGE)\n        .build();\n\n    public CraftingMonitorBlockEntity(BlockPos pos, BlockState state) {\n        super(RSBlockEntities.CRAFTING_MONITOR.get(), pos, state, SPEC, CraftingMonitorNetworkNode.class);\n    }\n\n    @Override\n    @Nonnull\n    public CraftingMonitorNetworkNode createNode(Level level, BlockPos pos) {\n        return new CraftingMonitorNetworkNode(level, pos);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/craftingmonitor/ICraftingMonitor.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.craftingmonitor;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.entity.player.Player;\n\nimport javax.annotation.Nullable;\nimport java.util.Collection;\nimport java.util.Optional;\nimport java.util.UUID;\n\npublic interface ICraftingMonitor {\n    int TABS_PER_PAGE = 7;\n\n    Component getTitle();\n\n    void onCancelled(ServerPlayer player, @Nullable UUID id);\n\n    BlockEntitySynchronizationParameter<Integer, ?> getRedstoneModeParameter();\n\n    Collection<ICraftingTask> getTasks();\n\n    @Nullable\n    ICraftingManager getCraftingManager();\n\n    boolean isActiveOnClient();\n\n    void onClosed(Player player);\n\n    Optional<UUID> getTabSelected();\n\n    int getTabPage();\n\n    void onTabSelectionChanged(Optional<UUID> taskId);\n\n    void onTabPageChanged(int page);\n\n    int getSlotId();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/craftingmonitor/WirelessCraftingMonitor.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.craftingmonitor;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport com.refinedmods.refinedstorage.item.NetworkItem;\nimport com.refinedmods.refinedstorage.item.WirelessCraftingMonitorItem;\nimport com.refinedmods.refinedstorage.network.craftingmonitor.WirelessCraftingMonitorSettingsUpdateMessage;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceKey;\nimport net.minecraft.server.MinecraftServer;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\n\nimport javax.annotation.Nullable;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Optional;\nimport java.util.UUID;\n\npublic class WirelessCraftingMonitor implements ICraftingMonitor {\n    private final ItemStack stack;\n    @Nullable\n    private final MinecraftServer server;\n    private final ResourceKey<Level> nodeDimension;\n    private final BlockPos nodePos;\n    private final PlayerSlot slot;\n    private int tabPage;\n    private Optional<UUID> tabSelected;\n\n    public WirelessCraftingMonitor(ItemStack stack, @Nullable MinecraftServer server, PlayerSlot slot) {\n        this.stack = stack;\n        this.server = server;\n        this.slot = slot;\n\n        this.nodeDimension = NetworkItem.getDimension(stack);\n        this.nodePos = new BlockPos(NetworkItem.getX(stack), NetworkItem.getY(stack), NetworkItem.getZ(stack));\n        this.tabPage = WirelessCraftingMonitorItem.getTabPage(stack);\n        this.tabSelected = WirelessCraftingMonitorItem.getTabSelected(stack);\n    }\n\n    public void setSettings(Optional<UUID> tabSelected, int tabPage) {\n        this.tabSelected = tabSelected;\n        this.tabPage = tabPage;\n\n        WirelessCraftingMonitorItem.setTabSelected(stack, tabSelected);\n        WirelessCraftingMonitorItem.setTabPage(stack, tabPage);\n    }\n\n    @Override\n    public Component getTitle() {\n        return Component.translatable(\"gui.refinedstorage.wireless_crafting_monitor\");\n    }\n\n    @Override\n    public void onCancelled(ServerPlayer player, @Nullable UUID id) {\n        INetwork network = getNetwork();\n\n        if (network != null) {\n            network.getItemGridHandler().onCraftingCancelRequested(player, id);\n        }\n    }\n\n    @Override\n    public BlockEntitySynchronizationParameter<Integer, ?> getRedstoneModeParameter() {\n        return null;\n    }\n\n    @Override\n    public Collection<ICraftingTask> getTasks() {\n        INetwork network = getNetwork();\n\n        if (network != null) {\n            return network.getCraftingManager().getTasks();\n        }\n\n        return Collections.emptyList();\n    }\n\n    @Nullable\n    @Override\n    public ICraftingManager getCraftingManager() {\n        INetwork network = getNetwork();\n\n        if (network != null) {\n            return network.getCraftingManager();\n        }\n\n        return null;\n    }\n\n    private INetwork getNetwork() {\n        Level level = server.getLevel(nodeDimension);\n        if (level == null) {\n            return null;\n        }\n        if (!level.isLoaded(nodePos)) {\n            return null;\n        }\n        return NetworkUtils.getNetworkFromNode(NetworkUtils.getNodeFromBlockEntity(level.getBlockEntity(nodePos)));\n    }\n\n    public ItemStack getStack() {\n        return stack;\n    }\n\n    @Override\n    public boolean isActiveOnClient() {\n        return true;\n    }\n\n    @Override\n    public void onClosed(Player player) {\n        INetwork network = getNetwork();\n\n        if (network != null) {\n            network.getNetworkItemManager().close(player);\n        }\n    }\n\n    @Override\n    public Optional<UUID> getTabSelected() {\n        return tabSelected;\n    }\n\n    @Override\n    public int getTabPage() {\n        return tabPage;\n    }\n\n    @Override\n    public void onTabSelectionChanged(Optional<UUID> taskId) {\n        if (taskId.isPresent() && tabSelected.isPresent() && taskId.get().equals(tabSelected.get())) {\n            this.tabSelected = Optional.empty();\n        } else {\n            this.tabSelected = taskId;\n        }\n\n        RS.NETWORK_HANDLER.sendToServer(new WirelessCraftingMonitorSettingsUpdateMessage(tabSelected, tabPage));\n    }\n\n    @Override\n    public void onTabPageChanged(int page) {\n        if (page >= 0) {\n            this.tabPage = page;\n\n            RS.NETWORK_HANDLER.sendToServer(new WirelessCraftingMonitorSettingsUpdateMessage(tabSelected, tabPage));\n        }\n    }\n\n    @Override\n    public int getSlotId() {\n        return slot.getSlotIdInPlayerInventory();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/data/BlockEntitySynchronizationClientListener.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.data;\n\npublic interface BlockEntitySynchronizationClientListener<T> {\n    void onChanged(boolean initial, T value);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/data/BlockEntitySynchronizationManager.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.data;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.network.sync.BlockEntitySynchronizationParameterUpdateMessage;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.block.entity.BlockEntity;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.CopyOnWriteArrayList;\n\npublic class BlockEntitySynchronizationManager {\n    private static final Map<ResourceLocation, BlockEntitySynchronizationParameter> REGISTRY = new HashMap<>();\n\n    private final BlockEntity blockEntity;\n    private final List<BlockEntitySynchronizationParameter> parameters;\n    private final List<BlockEntitySynchronizationParameter> watchedParameters;\n    private final List<BlockEntitySynchronizationWatcher> watchers = new CopyOnWriteArrayList<>();\n\n    public BlockEntitySynchronizationManager(BlockEntity blockEntity, BlockEntitySynchronizationSpec spec) {\n        this.blockEntity = blockEntity;\n        this.parameters = spec.getParameters();\n        this.watchedParameters = spec.getWatchedParameters();\n    }\n\n    public BlockEntity getBlockEntity() {\n        return blockEntity;\n    }\n\n    public List<BlockEntitySynchronizationParameter> getParameters() {\n        return parameters;\n    }\n\n    public List<BlockEntitySynchronizationParameter> getWatchedParameters() {\n        return watchedParameters;\n    }\n\n    public void addWatcher(BlockEntitySynchronizationWatcher listener) {\n        watchers.add(listener);\n    }\n\n    public void removeWatcher(BlockEntitySynchronizationWatcher listener) {\n        watchers.remove(listener);\n    }\n\n    public void sendParameterToWatchers(BlockEntitySynchronizationParameter parameter) {\n        watchers.forEach(l -> l.sendParameter(false, parameter));\n    }\n\n    // Synchronized so we don't conflict with addons that reuse this register method in parallel.\n    public synchronized static void registerParameter(BlockEntitySynchronizationParameter parameter) {\n        REGISTRY.put(parameter.getId(), parameter);\n    }\n\n    public static BlockEntitySynchronizationParameter getParameter(ResourceLocation id) {\n        return REGISTRY.get(id);\n    }\n\n    public static void setParameter(BlockEntitySynchronizationParameter parameter, Object value) {\n        RS.NETWORK_HANDLER.sendToServer(new BlockEntitySynchronizationParameterUpdateMessage(parameter, value));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/data/BlockEntitySynchronizationParameter.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.data;\n\nimport net.minecraft.network.syncher.EntityDataSerializer;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.block.entity.BlockEntity;\n\nimport javax.annotation.Nullable;\nimport java.util.HashSet;\nimport java.util.Set;\nimport java.util.function.BiConsumer;\nimport java.util.function.Function;\n\npublic class BlockEntitySynchronizationParameter<T, E extends BlockEntity> {\n    private static final Set<ResourceLocation> HAD = new HashSet<>();\n\n    private final ResourceLocation id;\n    private final EntityDataSerializer<T> serializer;\n    private final Function<E, T> valueProducer;\n    @Nullable\n    private final BiConsumer<E, T> valueConsumer;\n    @Nullable\n    private final BlockEntitySynchronizationClientListener<T> listener;\n    private T value;\n\n    public BlockEntitySynchronizationParameter(ResourceLocation id, EntityDataSerializer<T> serializer, T defaultValue, Function<E, T> producer) {\n        this(id, serializer, defaultValue, producer, null);\n    }\n\n    public BlockEntitySynchronizationParameter(ResourceLocation id, EntityDataSerializer<T> serializer, T defaultValue, Function<E, T> producer, @Nullable BiConsumer<E, T> consumer) {\n        this(id, serializer, defaultValue, producer, consumer, null);\n    }\n\n    public BlockEntitySynchronizationParameter(ResourceLocation id, EntityDataSerializer<T> serializer, T defaultValue, Function<E, T> producer, @Nullable BiConsumer<E, T> consumer, @Nullable BlockEntitySynchronizationClientListener<T> listener) {\n        if (!HAD.add(id)) {\n            throw new IllegalArgumentException(\"Duplicate BlockEntitySynchronizationParameter: \" + id);\n        }\n        this.id = id;\n        this.value = defaultValue;\n        this.serializer = serializer;\n        this.valueProducer = producer;\n        this.valueConsumer = consumer;\n        this.listener = listener;\n    }\n\n    public ResourceLocation getId() {\n        return id;\n    }\n\n    public EntityDataSerializer<T> getSerializer() {\n        return serializer;\n    }\n\n    public Function<E, T> getValueProducer() {\n        return valueProducer;\n    }\n\n    @Nullable\n    public BiConsumer<E, T> getValueConsumer() {\n        return valueConsumer;\n    }\n\n    public void setValue(boolean initial, T value) {\n        this.value = value;\n\n        if (listener != null) {\n            listener.onChanged(initial, value);\n        }\n    }\n\n    public T getValue() {\n        return value;\n    }\n}"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/data/BlockEntitySynchronizationSpec.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.data;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\npublic final class BlockEntitySynchronizationSpec {\n    private final List<BlockEntitySynchronizationParameter> parameters;\n    private final List<BlockEntitySynchronizationParameter> watchedParameters;\n\n    public BlockEntitySynchronizationSpec(List<BlockEntitySynchronizationParameter> parameters, List<BlockEntitySynchronizationParameter> watchedParameters) {\n        this.parameters = Collections.unmodifiableList(parameters);\n        this.watchedParameters = Collections.unmodifiableList(watchedParameters);\n    }\n\n    public List<BlockEntitySynchronizationParameter> getParameters() {\n        return parameters;\n    }\n\n    public List<BlockEntitySynchronizationParameter> getWatchedParameters() {\n        return watchedParameters;\n    }\n\n    public static Builder builder() {\n        return new Builder();\n    }\n\n    public static class Builder {\n        private final List<BlockEntitySynchronizationParameter> parameters = new ArrayList<>();\n        private final List<BlockEntitySynchronizationParameter> watchedParameters = new ArrayList<>();\n\n        public Builder addParameter(BlockEntitySynchronizationParameter parameter) {\n            parameters.add(parameter);\n            return this;\n        }\n\n        public Builder addWatchedParameter(BlockEntitySynchronizationParameter parameter) {\n            addParameter(parameter);\n            watchedParameters.add(parameter);\n            return this;\n        }\n\n        public BlockEntitySynchronizationSpec build() {\n            return new BlockEntitySynchronizationSpec(parameters, watchedParameters);\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/data/BlockEntitySynchronizationWatcher.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.data;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.network.sync.BlockEntitySynchronizationParameterMessage;\nimport net.minecraft.server.level.ServerPlayer;\n\npublic class BlockEntitySynchronizationWatcher {\n    private final ServerPlayer player;\n    private final BlockEntitySynchronizationManager manager;\n    private boolean sentInitial;\n    private Object[] cache;\n\n    public BlockEntitySynchronizationWatcher(ServerPlayer player, BlockEntitySynchronizationManager manager) {\n        this.player = player;\n        this.manager = manager;\n\n        if (manager != null) {\n            this.manager.addWatcher(this);\n            this.cache = new Object[manager.getWatchedParameters().size()];\n        }\n    }\n\n    public ServerPlayer getPlayer() {\n        return player;\n    }\n\n    public void onClosed() {\n        this.manager.removeWatcher(this);\n    }\n\n    public void detectAndSendChanges() {\n        if (!sentInitial) {\n            manager.getParameters().forEach(p -> sendParameter(true, p));\n\n            sentInitial = true;\n        } else {\n            for (int i = 0; i < manager.getWatchedParameters().size(); ++i) {\n                BlockEntitySynchronizationParameter parameter = manager.getWatchedParameters().get(i);\n\n                Object real = parameter.getValueProducer().apply(manager.getBlockEntity());\n                Object cached = cache[i];\n\n                if (!real.equals(cached)) {\n                    cache[i] = real;\n\n                    // Avoid sending watched parameter twice (after initial packet)\n                    if (cached != null) {\n                        sendParameter(false, parameter);\n                    }\n                }\n            }\n        }\n    }\n\n    public void sendParameter(boolean initial, BlockEntitySynchronizationParameter parameter) {\n        RS.NETWORK_HANDLER.sendTo(player, new BlockEntitySynchronizationParameterMessage(\n            parameter,\n            parameter.getValueProducer().apply(manager.getBlockEntity()),\n            initial\n        ));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/data/RSSerializers.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.data;\n\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.blockentity.ClientNode;\nimport com.refinedmods.refinedstorage.util.AccessTypeUtils;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.syncher.EntityDataAccessor;\nimport net.minecraft.network.syncher.EntityDataSerializer;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport java.util.*;\n\npublic final class RSSerializers {\n    public static final EntityDataSerializer<List<ClientNode>> CLIENT_NODE_SERIALIZER = new EntityDataSerializer<List<ClientNode>>() {\n        @Override\n        public void write(FriendlyByteBuf buf, List<ClientNode> nodes) {\n            buf.writeInt(nodes.size());\n\n            for (ClientNode node : nodes) {\n                buf.writeItem(node.getStack());\n                buf.writeInt(node.getAmount());\n                buf.writeInt(node.getEnergyUsage());\n            }\n        }\n\n        @Override\n        public List<ClientNode> read(FriendlyByteBuf buf) {\n            List<ClientNode> nodes = new ArrayList<>();\n\n            int size = buf.readInt();\n\n            for (int i = 0; i < size; ++i) {\n                nodes.add(new ClientNode(buf.readItem(), buf.readInt(), buf.readInt()));\n            }\n\n            return nodes;\n        }\n\n        @Override\n        public EntityDataAccessor<List<ClientNode>> createAccessor(int id) {\n            return null;\n        }\n\n        @Override\n        public List<ClientNode> copy(List<ClientNode> value) {\n            return value;\n        }\n    };\n    public static final EntityDataSerializer<FluidStack> FLUID_STACK_SERIALIZER = new EntityDataSerializer<FluidStack>() {\n        @Override\n        public void write(FriendlyByteBuf buf, FluidStack value) {\n            value.writeToPacket(buf);\n        }\n\n        @Override\n        public FluidStack read(FriendlyByteBuf buf) {\n            return FluidStack.readFromPacket(buf);\n        }\n\n        @Override\n        public EntityDataAccessor<FluidStack> createAccessor(int id) {\n            return null;\n        }\n\n        @Override\n        public FluidStack copy(FluidStack value) {\n            return value;\n        }\n    };\n    public static final EntityDataSerializer<AccessType> ACCESS_TYPE_SERIALIZER = new EntityDataSerializer<AccessType>() {\n        @Override\n        public void write(FriendlyByteBuf buf, AccessType value) {\n            buf.writeInt(value.getId());\n        }\n\n        @Override\n        public AccessType read(FriendlyByteBuf buf) {\n            return AccessTypeUtils.getAccessType(buf.readInt());\n        }\n\n        @Override\n        public EntityDataAccessor<AccessType> createAccessor(int id) {\n            return null;\n        }\n\n        @Override\n        public AccessType copy(AccessType value) {\n            return value;\n        }\n    };\n    public static final EntityDataSerializer<Long> LONG_SERIALIZER = new EntityDataSerializer<Long>() {\n        @Override\n        public void write(FriendlyByteBuf buf, Long value) {\n            buf.writeLong(value);\n        }\n\n        @Override\n        public Long read(FriendlyByteBuf buf) {\n            return buf.readLong();\n        }\n\n        @Override\n        public EntityDataAccessor<Long> createAccessor(int id) {\n            return null;\n        }\n\n        @Override\n        public Long copy(Long value) {\n            return value;\n        }\n    };\n    public static final EntityDataSerializer<Optional<ResourceLocation>> OPTIONAL_RESOURCE_LOCATION_SERIALIZER = new EntityDataSerializer<Optional<ResourceLocation>>() {\n        @Override\n        public void write(FriendlyByteBuf buf, Optional<ResourceLocation> value) {\n            buf.writeBoolean(value.isPresent());\n\n            value.ifPresent(buf::writeResourceLocation);\n        }\n\n        @Override\n        public Optional<ResourceLocation> read(FriendlyByteBuf buf) {\n            if (!buf.readBoolean()) {\n                return Optional.empty();\n            }\n\n            return Optional.of(buf.readResourceLocation());\n        }\n\n        @Override\n        public EntityDataAccessor<Optional<ResourceLocation>> createAccessor(int id) {\n            return null;\n        }\n\n        @Override\n        public Optional<ResourceLocation> copy(Optional<ResourceLocation> value) {\n            return value;\n        }\n    };\n    public static final EntityDataSerializer<List<Set<ResourceLocation>>> LIST_OF_SET_SERIALIZER = new EntityDataSerializer<List<Set<ResourceLocation>>>() {\n        @Override\n        public void write(FriendlyByteBuf buf, List<Set<ResourceLocation>> value) {\n            buf.writeInt(value.size());\n\n            for (Set<ResourceLocation> values : value) {\n                buf.writeInt(values.size());\n\n                values.forEach(buf::writeResourceLocation);\n            }\n        }\n\n        @Override\n        public List<Set<ResourceLocation>> read(FriendlyByteBuf buf) {\n            List<Set<ResourceLocation>> value = new ArrayList<>();\n\n            int size = buf.readInt();\n            for (int i = 0; i < size; ++i) {\n                int setSize = buf.readInt();\n\n                Set<ResourceLocation> values = new HashSet<>();\n\n                for (int j = 0; j < setSize; ++j) {\n                    values.add(buf.readResourceLocation());\n                }\n\n                value.add(values);\n            }\n\n            return value;\n        }\n\n        @Override\n        public EntityDataAccessor<List<Set<ResourceLocation>>> createAccessor(int id) {\n            return null;\n        }\n\n        @Override\n        public List<Set<ResourceLocation>> copy(List<Set<ResourceLocation>> value) {\n            return value;\n        }\n    };\n\n    private RSSerializers() {\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/grid/GridBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.api.network.grid.GridType;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport com.refinedmods.refinedstorage.blockentity.data.RSSerializers;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.screen.grid.GridScreen;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.network.syncher.EntityDataSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntityType;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.energy.IEnergyStorage;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Set;\n\npublic class GridBlockEntity extends NetworkNodeBlockEntity<GridNetworkNode> {\n    public static final BlockEntitySynchronizationParameter<Boolean, GridBlockEntity> EXACT_PATTERN = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"grid_exact_mode\"), EntityDataSerializers.BOOLEAN, true, t -> t.getNode().isExactPattern(), (t, v) -> {\n        t.getNode().setExactPattern(v);\n        t.getNode().markDirty();\n    }, (initial, p) -> BaseScreen.executeLater(GridScreen.class, grid -> grid.updateExactPattern(p)));\n    public static final BlockEntitySynchronizationParameter<Integer, GridBlockEntity> PROCESSING_TYPE = IType.createParameter(new ResourceLocation(RS.ID, \"grid_processing_type\"), (initial, p) -> BaseScreen.executeLater(GridScreen.class, BaseScreen::init));\n    public static final BlockEntitySynchronizationParameter<Integer, GridBlockEntity> VIEW_TYPE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"grid_view_type\"), EntityDataSerializers.INT, 0, t -> t.getNode().getViewType(), (t, v) -> {\n        if (IGrid.isValidViewType(v)) {\n            t.getNode().setViewType(v);\n            t.getNode().markDirty();\n        }\n    }, (initial, p) -> trySortGrid(initial));\n    public static final BlockEntitySynchronizationParameter<List<Set<ResourceLocation>>, GridBlockEntity> ALLOWED_ITEM_TAGS = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"grid_allowed_item_tags\"), RSSerializers.LIST_OF_SET_SERIALIZER, new ArrayList<>(), t -> t.getNode().getAllowedTagList().getAllowedItemTags(), (t, v) -> t.getNode().getAllowedTagList().setAllowedItemTags(v));\n    public static final BlockEntitySynchronizationParameter<List<Set<ResourceLocation>>, GridBlockEntity> ALLOWED_FLUID_TAGS = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"grid_allowed_fluid_tags\"), RSSerializers.LIST_OF_SET_SERIALIZER, new ArrayList<>(), t -> t.getNode().getAllowedTagList().getAllowedFluidTags(), (t, v) -> t.getNode().getAllowedTagList().setAllowedFluidTags(v));\n    public static final BlockEntitySynchronizationParameter<Integer, GridBlockEntity> SORTING_DIRECTION = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"grid_sorting_direction\"), EntityDataSerializers.INT, 0, t -> t.getNode().getSortingDirection(), (t, v) -> {\n        if (IGrid.isValidSortingDirection(v)) {\n            t.getNode().setSortingDirection(v);\n            t.getNode().markDirty();\n        }\n    }, (initial, p) -> trySortGrid(initial));\n    public static final BlockEntitySynchronizationParameter<Integer, GridBlockEntity> SORTING_TYPE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"grid_sorting_type\"), EntityDataSerializers.INT, 0, t -> t.getNode().getSortingType(), (t, v) -> {\n        if (IGrid.isValidSortingType(v)) {\n            t.getNode().setSortingType(v);\n            t.getNode().markDirty();\n        }\n    }, (initial, p) -> trySortGrid(initial));\n    public static final BlockEntitySynchronizationParameter<Integer, GridBlockEntity> TAB_SELECTED = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"grid_tab_selected\"), EntityDataSerializers.INT, 0, t -> t.getNode().getTabSelected(), (t, v) -> {\n        t.getNode().setTabSelected(v == t.getNode().getTabSelected() ? -1 : v);\n        t.getNode().markDirty();\n    }, (initial, p) -> BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort()));\n    public static final BlockEntitySynchronizationParameter<Integer, GridBlockEntity> TAB_PAGE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"grid_tab_page\"), EntityDataSerializers.INT, 0, t -> t.getNode().getTabPage(), (t, v) -> {\n        if (v >= 0 && v <= t.getNode().getTotalTabPages()) {\n            t.getNode().setTabPage(v);\n            t.getNode().markDirty();\n        }\n    });\n    public static final BlockEntitySynchronizationParameter<Boolean, GridBlockEntity> PROCESSING_PATTERN = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"grid_processing_pattern\"), EntityDataSerializers.BOOLEAN, false, t -> t.getNode().isProcessingPattern(), (t, v) -> {\n        t.getNode().setProcessingPattern(v);\n        t.getNode().clearMatrix();\n        t.getNode().markDirty();\n    }, (initial, p) -> BaseScreen.executeLater(GridScreen.class, BaseScreen::init));\n    public static final BlockEntitySynchronizationParameter<Integer, GridBlockEntity> SIZE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"grid_size\"), EntityDataSerializers.INT, 0, t -> t.getNode().getSize(), (t, v) -> {\n        if (IGrid.isValidSize(v)) {\n            t.getNode().setSize(v);\n            t.getNode().markDirty();\n        }\n    }, (initial, p) -> BaseScreen.executeLater(GridScreen.class, grid -> grid.resize(grid.getMinecraft(), grid.width, grid.height)));\n    public static final BlockEntitySynchronizationParameter<Integer, GridBlockEntity> SEARCH_BOX_MODE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"grid_search_box_mode\"), EntityDataSerializers.INT, 0, t -> t.getNode().getSearchBoxMode(), (t, v) -> {\n        if (IGrid.isValidSearchBoxMode(v)) {\n            t.getNode().setSearchBoxMode(v);\n            t.getNode().markDirty();\n        }\n    }, (initial, p) -> BaseScreen.executeLater(GridScreen.class, grid -> grid.getSearchField().setMode(p)));\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .addWatchedParameter(VIEW_TYPE)\n        .addWatchedParameter(SORTING_DIRECTION)\n        .addWatchedParameter(SORTING_TYPE)\n        .addWatchedParameter(SEARCH_BOX_MODE)\n        .addWatchedParameter(SIZE)\n        .addWatchedParameter(TAB_SELECTED)\n        .addWatchedParameter(TAB_PAGE)\n        .addWatchedParameter(EXACT_PATTERN)\n        .addWatchedParameter(PROCESSING_PATTERN)\n        .addWatchedParameter(PROCESSING_TYPE)\n        .addParameter(ALLOWED_ITEM_TAGS)\n        .addParameter(ALLOWED_FLUID_TAGS)\n        .build();\n\n    public static BlockEntityType<GridBlockEntity> getType(GridType type) {\n        return switch (type) {\n            case NORMAL -> RSBlockEntities.GRID.get();\n            case CRAFTING -> RSBlockEntities.CRAFTING_GRID.get();\n            case PATTERN -> RSBlockEntities.PATTERN_GRID.get();\n            case FLUID -> RSBlockEntities.FLUID_GRID.get();\n        };\n    }\n\n    public static void trySortGrid(boolean initial) {\n        if (!initial) {\n            BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort());\n        }\n    }\n\n    private final GridType type;\n\n    public GridBlockEntity(GridType type, BlockPos pos, BlockState state) {\n        super(getType(type), pos, state, SPEC, GridNetworkNode.class);\n        this.type = type;\n    }\n\n    @Override\n    @Nonnull\n    public GridNetworkNode createNode(Level level, BlockPos pos) {\n        return new GridNetworkNode(level, pos, type);\n    }\n\n    public IItemHandler getInventory() {\n        if (type == GridType.PATTERN) {\n            return getNode().getPatterns();\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/grid/WirelessFluidGrid.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.grid.*;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener;\nimport com.refinedmods.refinedstorage.api.util.IFilter;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.apiimpl.storage.cache.listener.FluidGridStorageCacheListener;\nimport com.refinedmods.refinedstorage.inventory.item.FilterItemHandler;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport com.refinedmods.refinedstorage.item.NetworkItem;\nimport com.refinedmods.refinedstorage.item.WirelessFluidGridItem;\nimport com.refinedmods.refinedstorage.network.grid.WirelessFluidGridSettingsUpdateMessage;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.screen.grid.GridScreen;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceKey;\nimport net.minecraft.server.MinecraftServer;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.CraftingContainer;\nimport net.minecraft.world.inventory.ResultContainer;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class WirelessFluidGrid implements INetworkAwareGrid {\n    @Nullable\n    private final MinecraftServer server;\n    private final ResourceKey<Level> nodeDimension;\n    private final BlockPos nodePos;\n    private final PlayerSlot slot;\n    private final List<IFilter> filters = new ArrayList<>();\n    private final List<IGridTab> tabs = new ArrayList<>();\n    private ItemStack stack;\n    private final FilterItemHandler filter = (FilterItemHandler) new FilterItemHandler(filters, tabs)\n        .addListener(((handler, slot, reading) -> {\n            if (!stack.hasTag()) {\n                stack.setTag(new CompoundTag());\n            }\n\n            StackUtils.writeItems(handler, 0, stack.getTag());\n        }));\n    private int sortingType;\n    private int sortingDirection;\n    private int searchBoxMode;\n    private int tabSelected;\n    private int tabPage;\n    private int size;\n\n    public WirelessFluidGrid(ItemStack stack, @Nullable MinecraftServer server, PlayerSlot slot) {\n        this.stack = stack;\n        this.server = server;\n        this.nodeDimension = NetworkItem.getDimension(stack);\n        this.nodePos = new BlockPos(NetworkItem.getX(stack), NetworkItem.getY(stack), NetworkItem.getZ(stack));\n        this.slot = slot;\n\n        this.sortingType = WirelessFluidGridItem.getSortingType(stack);\n        this.sortingDirection = WirelessFluidGridItem.getSortingDirection(stack);\n        this.searchBoxMode = WirelessFluidGridItem.getSearchBoxMode(stack);\n        this.tabSelected = WirelessFluidGridItem.getTabSelected(stack);\n        this.tabPage = WirelessFluidGridItem.getTabPage(stack);\n        this.size = WirelessFluidGridItem.getSize(stack);\n\n        if (stack.hasTag()) {\n            StackUtils.readItems(filter, 0, stack.getTag());\n        }\n    }\n\n    public ItemStack getStack() {\n        return stack;\n    }\n\n    @Override\n    public GridType getGridType() {\n        return GridType.FLUID;\n    }\n\n    @Override\n    @Nullable\n    public INetwork getNetwork() {\n        Level level = server.getLevel(nodeDimension);\n        if (level == null) {\n            return null;\n        }\n        if (!level.isLoaded(nodePos)) {\n            return null;\n        }\n        return NetworkUtils.getNetworkFromNode(NetworkUtils.getNodeFromBlockEntity(level.getBlockEntity(nodePos)));\n    }\n\n    @Override\n    public IStorageCacheListener createListener(ServerPlayer player) {\n        return new FluidGridStorageCacheListener(player, getNetwork());\n    }\n\n    @Nullable\n    @Override\n    public IStorageCache getStorageCache() {\n        INetwork network = getNetwork();\n\n        return network != null ? network.getFluidStorageCache() : null;\n    }\n\n    @Nullable\n    @Override\n    public IItemGridHandler getItemHandler() {\n        return null;\n    }\n\n    @Nullable\n    @Override\n    public IFluidGridHandler getFluidHandler() {\n        INetwork network = getNetwork();\n\n        return network != null ? network.getFluidGridHandler() : null;\n    }\n\n    @Override\n    public void addCraftingListener(ICraftingGridListener listener) {\n        // NO OP\n    }\n\n    @Override\n    public void removeCraftingListener(ICraftingGridListener listener) {\n        // NO OP\n    }\n\n    @Override\n    public Component getTitle() {\n        return Component.translatable(\"gui.refinedstorage.fluid_grid\");\n    }\n\n    @Override\n    public int getViewType() {\n        return 0;\n    }\n\n    @Override\n    public int getSortingType() {\n        return sortingType;\n    }\n\n    @Override\n    public int getSortingDirection() {\n        return sortingDirection;\n    }\n\n    @Override\n    public int getSearchBoxMode() {\n        return searchBoxMode;\n    }\n\n    @Override\n    public int getTabSelected() {\n        return tabSelected;\n    }\n\n    @Override\n    public int getTabPage() {\n        return Math.min(tabPage, getTotalTabPages());\n    }\n\n    @Override\n    public int getTotalTabPages() {\n        return (int) Math.floor((float) Math.max(0, tabs.size() - 1) / (float) IGrid.TABS_PER_PAGE);\n    }\n\n    @Override\n    public int getSize() {\n        return size;\n    }\n\n    @Override\n    public void onViewTypeChanged(int type) {\n        // NO OP\n    }\n\n    @Override\n    public void onSortingTypeChanged(int type) {\n        RS.NETWORK_HANDLER.sendToServer(new WirelessFluidGridSettingsUpdateMessage(getSortingDirection(), type, getSearchBoxMode(), getSize(), getTabSelected(), getTabPage()));\n\n        this.sortingType = type;\n\n        BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort());\n    }\n\n    @Override\n    public void onSortingDirectionChanged(int direction) {\n        RS.NETWORK_HANDLER.sendToServer(new WirelessFluidGridSettingsUpdateMessage(direction, getSortingType(), getSearchBoxMode(), getSize(), getTabSelected(), getTabPage()));\n\n        this.sortingDirection = direction;\n\n        BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort());\n    }\n\n    @Override\n    public void onSearchBoxModeChanged(int searchBoxMode) {\n        RS.NETWORK_HANDLER.sendToServer(new WirelessFluidGridSettingsUpdateMessage(getSortingDirection(), getSortingType(), searchBoxMode, getSize(), getTabSelected(), getTabPage()));\n\n        this.searchBoxMode = searchBoxMode;\n    }\n\n    @Override\n    public void onSizeChanged(int size) {\n        RS.NETWORK_HANDLER.sendToServer(new WirelessFluidGridSettingsUpdateMessage(getSortingDirection(), getSortingType(), getSearchBoxMode(), size, getTabSelected(), getTabPage()));\n\n        this.size = size;\n\n        BaseScreen.executeLater(GridScreen.class, BaseScreen::init);\n    }\n\n    @Override\n    public void onTabSelectionChanged(int tab) {\n        this.tabSelected = tab == tabSelected ? -1 : tab;\n\n        RS.NETWORK_HANDLER.sendToServer(new WirelessFluidGridSettingsUpdateMessage(getSortingDirection(), getSortingType(), getSearchBoxMode(), getSize(), tabSelected, getTabPage()));\n\n        BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort());\n    }\n\n    @Override\n    public void onTabPageChanged(int page) {\n        if (page >= 0 && page <= getTotalTabPages()) {\n            RS.NETWORK_HANDLER.sendToServer(new WirelessFluidGridSettingsUpdateMessage(getSortingDirection(), getSortingType(), getSearchBoxMode(), getSize(), getTabSelected(), page));\n\n            this.tabPage = page;\n        }\n    }\n\n    @Override\n    public List<IFilter> getFilters() {\n        return filters;\n    }\n\n    @Override\n    public List<IGridTab> getTabs() {\n        return tabs;\n    }\n\n    @Override\n    public IItemHandlerModifiable getFilter() {\n        return filter;\n    }\n\n    @Override\n    public CraftingContainer getCraftingMatrix() {\n        return null;\n    }\n\n    @Override\n    public ResultContainer getCraftingResult() {\n        return null;\n    }\n\n    @Override\n    public void onCraftingMatrixChanged() {\n        // NO OP\n    }\n\n    @Override\n    public void onCrafted(Player player, @Nullable IStackList<ItemStack> availableItems, @Nullable IStackList<ItemStack> usedItems) {\n        // NO OP\n    }\n\n    @Override\n    public void onClear(Player player) {\n        // NO OP\n    }\n\n    @Override\n    public void onCraftedShift(Player player) {\n        // NO OP\n    }\n\n    @Override\n    public void onRecipeTransfer(Player player, ItemStack[][] recipe) {\n        // NO OP\n    }\n\n    @Override\n    public boolean isGridActive() {\n        return true;\n    }\n\n    @Override\n    public int getSlotId() {\n        return slot.getSlotIdInPlayerInventory();\n    }\n\n    @Override\n    public void onClosed(Player player) {\n        INetwork network = getNetwork();\n\n        if (network != null) {\n            network.getNetworkItemManager().close(player);\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/grid/WirelessGrid.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.grid.*;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener;\nimport com.refinedmods.refinedstorage.api.util.IFilter;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.apiimpl.storage.cache.listener.ItemGridStorageCacheListener;\nimport com.refinedmods.refinedstorage.inventory.item.FilterItemHandler;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport com.refinedmods.refinedstorage.item.NetworkItem;\nimport com.refinedmods.refinedstorage.item.WirelessGridItem;\nimport com.refinedmods.refinedstorage.network.grid.WirelessGridSettingsUpdateMessage;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.screen.grid.GridScreen;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.chat.Component;\n\nimport net.minecraft.resources.ResourceKey;\nimport net.minecraft.server.MinecraftServer;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.CraftingContainer;\nimport net.minecraft.world.inventory.ResultContainer;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class WirelessGrid implements INetworkAwareGrid {\n    @Nullable\n    private final MinecraftServer server;\n    private final ResourceKey<Level> nodeDimension;\n    private final BlockPos nodePos;\n    private final PlayerSlot slot;\n    private final List<IFilter> filters = new ArrayList<>();\n    private final List<IGridTab> tabs = new ArrayList<>();\n    private ItemStack stack;\n    private final FilterItemHandler filter = (FilterItemHandler) new FilterItemHandler(filters, tabs)\n        .addListener((handler, slot, reading) -> {\n            if (!stack.hasTag()) {\n                stack.setTag(new CompoundTag());\n            }\n\n            StackUtils.writeItems(handler, 0, stack.getTag());\n        });\n    private int viewType;\n    private int sortingType;\n    private int sortingDirection;\n    private int searchBoxMode;\n    private int tabSelected;\n    private int tabPage;\n    private int size;\n\n    public WirelessGrid(ItemStack stack, @Nullable MinecraftServer server, PlayerSlot slot) {\n        this.stack = stack;\n        this.server = server;\n        this.nodeDimension = NetworkItem.getDimension(stack);\n        this.nodePos = new BlockPos(NetworkItem.getX(stack), NetworkItem.getY(stack), NetworkItem.getZ(stack));\n        this.slot = slot;\n\n        this.viewType = WirelessGridItem.getViewType(stack);\n        this.sortingType = WirelessGridItem.getSortingType(stack);\n        this.sortingDirection = WirelessGridItem.getSortingDirection(stack);\n        this.searchBoxMode = WirelessGridItem.getSearchBoxMode(stack);\n        this.tabSelected = WirelessGridItem.getTabSelected(stack);\n        this.tabPage = WirelessGridItem.getTabPage(stack);\n        this.size = WirelessGridItem.getSize(stack);\n\n        if (stack.hasTag()) {\n            StackUtils.readItems(filter, 0, stack.getTag());\n        }\n    }\n\n    public ItemStack getStack() {\n        return stack;\n    }\n\n    @Override\n    public GridType getGridType() {\n        return GridType.NORMAL;\n    }\n\n    @Override\n    @Nullable\n    public INetwork getNetwork() {\n        Level level = server.getLevel(nodeDimension);\n        if (level == null) {\n            return null;\n        }\n        if (!level.isLoaded(nodePos)) {\n            return null;\n        }\n        return NetworkUtils.getNetworkFromNode(NetworkUtils.getNodeFromBlockEntity(level.getBlockEntity(nodePos)));\n    }\n\n    @Override\n    public IStorageCacheListener createListener(ServerPlayer player) {\n        return new ItemGridStorageCacheListener(player, getNetwork());\n    }\n\n    @Nullable\n    @Override\n    public IStorageCache getStorageCache() {\n        INetwork network = getNetwork();\n\n        return network != null ? network.getItemStorageCache() : null;\n    }\n\n    @Nullable\n    @Override\n    public IItemGridHandler getItemHandler() {\n        INetwork network = getNetwork();\n\n        return network != null ? network.getItemGridHandler() : null;\n    }\n\n    @Nullable\n    @Override\n    public IFluidGridHandler getFluidHandler() {\n        return null;\n    }\n\n    @Override\n    public void addCraftingListener(ICraftingGridListener listener) {\n        // NO OP\n    }\n\n    @Override\n    public void removeCraftingListener(ICraftingGridListener listener) {\n        // NO OP\n    }\n\n    @Override\n    public Component getTitle() {\n        return Component.translatable(\"gui.refinedstorage.grid\");\n    }\n\n    @Override\n    public int getViewType() {\n        return viewType;\n    }\n\n    @Override\n    public int getSortingType() {\n        return sortingType;\n    }\n\n    @Override\n    public int getSortingDirection() {\n        return sortingDirection;\n    }\n\n    @Override\n    public int getSearchBoxMode() {\n        return searchBoxMode;\n    }\n\n    @Override\n    public int getTabSelected() {\n        return tabSelected;\n    }\n\n    @Override\n    public int getTabPage() {\n        return Math.min(tabPage, getTotalTabPages());\n    }\n\n    @Override\n    public int getTotalTabPages() {\n        return (int) Math.floor((float) Math.max(0, tabs.size() - 1) / (float) IGrid.TABS_PER_PAGE);\n    }\n\n    @Override\n    public int getSize() {\n        return size;\n    }\n\n    @Override\n    public void onViewTypeChanged(int type) {\n        RS.NETWORK_HANDLER.sendToServer(new WirelessGridSettingsUpdateMessage(type, getSortingDirection(), getSortingType(), getSearchBoxMode(), getSize(), getTabSelected(), getTabPage()));\n\n        this.viewType = type;\n\n        BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort());\n    }\n\n    @Override\n    public void onSortingTypeChanged(int type) {\n        RS.NETWORK_HANDLER.sendToServer(new WirelessGridSettingsUpdateMessage(getViewType(), getSortingDirection(), type, getSearchBoxMode(), getSize(), getTabSelected(), getTabPage()));\n\n        this.sortingType = type;\n\n        BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort());\n    }\n\n    @Override\n    public void onSortingDirectionChanged(int direction) {\n        RS.NETWORK_HANDLER.sendToServer(new WirelessGridSettingsUpdateMessage(getViewType(), direction, getSortingType(), getSearchBoxMode(), getSize(), getTabSelected(), getTabPage()));\n\n        this.sortingDirection = direction;\n\n        BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort());\n    }\n\n    @Override\n    public void onSearchBoxModeChanged(int searchBoxMode) {\n        RS.NETWORK_HANDLER.sendToServer(new WirelessGridSettingsUpdateMessage(getViewType(), getSortingDirection(), getSortingType(), searchBoxMode, getSize(), getTabSelected(), getTabPage()));\n\n        this.searchBoxMode = searchBoxMode;\n    }\n\n    @Override\n    public void onSizeChanged(int size) {\n        RS.NETWORK_HANDLER.sendToServer(new WirelessGridSettingsUpdateMessage(getViewType(), getSortingDirection(), getSortingType(), getSearchBoxMode(), size, getTabSelected(), getTabPage()));\n\n        this.size = size;\n\n        BaseScreen.executeLater(GridScreen.class, BaseScreen::init);\n    }\n\n    @Override\n    public void onTabSelectionChanged(int tab) {\n        this.tabSelected = tab == tabSelected ? -1 : tab;\n\n        RS.NETWORK_HANDLER.sendToServer(new WirelessGridSettingsUpdateMessage(getViewType(), getSortingDirection(), getSortingType(), getSearchBoxMode(), getSize(), tabSelected, getTabPage()));\n\n        BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort());\n    }\n\n    @Override\n    public void onTabPageChanged(int page) {\n        if (page >= 0 && page <= getTotalTabPages()) {\n            RS.NETWORK_HANDLER.sendToServer(new WirelessGridSettingsUpdateMessage(getViewType(), getSortingDirection(), getSortingType(), getSearchBoxMode(), getSize(), getTabSelected(), page));\n\n            this.tabPage = page;\n        }\n    }\n\n    @Override\n    public List<IFilter> getFilters() {\n        return filters;\n    }\n\n    @Override\n    public List<IGridTab> getTabs() {\n        return tabs;\n    }\n\n    @Override\n    public IItemHandlerModifiable getFilter() {\n        return filter;\n    }\n\n    @Override\n    public CraftingContainer getCraftingMatrix() {\n        return null;\n    }\n\n    @Override\n    public ResultContainer getCraftingResult() {\n        return null;\n    }\n\n    @Override\n    public void onCraftingMatrixChanged() {\n        // NO OP\n    }\n\n    @Override\n    public void onCrafted(Player player, @Nullable IStackList<ItemStack> availableItems, @Nullable IStackList<ItemStack> usedItems) {\n        // NO OP\n    }\n\n    @Override\n    public void onClear(Player player) {\n        // NO OP\n    }\n\n    @Override\n    public void onCraftedShift(Player player) {\n        // NO OP\n    }\n\n    @Override\n    public void onRecipeTransfer(Player player, ItemStack[][] recipe) {\n        // NO OP\n    }\n\n    @Override\n    public boolean isGridActive() {\n        return true;\n    }\n\n    @Override\n    public int getSlotId() {\n        return slot.getSlotIdInPlayerInventory();\n    }\n\n    @Override\n    public void onClosed(Player player) {\n        INetwork network = getNetwork();\n\n        if (network != null) {\n            network.getNetworkItemManager().close(player);\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/grid/portable/IPortableGrid.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.grid.portable;\n\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.tracker.IStorageTracker;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport javax.annotation.Nullable;\n\npublic interface IPortableGrid {\n    @Nullable\n    IStorageCache getCache();\n\n    default IStorageCache<ItemStack> getItemCache() {\n        return getCache();\n    }\n\n    default IStorageCache<FluidStack> getFluidCache() {\n        return getCache();\n    }\n\n    @Nullable\n    IStorageDisk getStorage();\n\n    default IStorageDisk<ItemStack> getItemStorage() {\n        return getStorage();\n    }\n\n    default IStorageDisk<FluidStack> getFluidStorage() {\n        return getStorage();\n    }\n\n    void drainEnergy(int energy);\n\n    int getEnergy();\n\n    BaseItemHandler getDiskInventory();\n\n    IItemHandlerModifiable getFilter();\n\n    IStorageTracker<ItemStack> getItemStorageTracker();\n\n    IStorageTracker<FluidStack> getFluidStorageTracker();\n\n    boolean isGridActive();\n\n    PortableGridDiskState getDiskState();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/grid/portable/PortableGrid.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.grid.portable;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.GridType;\nimport com.refinedmods.refinedstorage.api.network.grid.ICraftingGridListener;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.api.network.grid.IGridTab;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler;\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.StorageType;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener;\nimport com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskProvider;\nimport com.refinedmods.refinedstorage.api.storage.disk.StorageDiskSyncData;\nimport com.refinedmods.refinedstorage.api.util.IFilter;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.grid.handler.PortableFluidGridHandler;\nimport com.refinedmods.refinedstorage.apiimpl.network.grid.handler.PortableItemGridHandler;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.DiskState;\nimport com.refinedmods.refinedstorage.apiimpl.storage.cache.PortableFluidStorageCache;\nimport com.refinedmods.refinedstorage.apiimpl.storage.cache.PortableItemStorageCache;\nimport com.refinedmods.refinedstorage.apiimpl.storage.cache.listener.PortableFluidGridStorageCacheListener;\nimport com.refinedmods.refinedstorage.apiimpl.storage.cache.listener.PortableItemGridStorageCacheListener;\nimport com.refinedmods.refinedstorage.apiimpl.storage.disk.PortableFluidStorageDisk;\nimport com.refinedmods.refinedstorage.apiimpl.storage.disk.PortableItemStorageDisk;\nimport com.refinedmods.refinedstorage.apiimpl.storage.tracker.FluidStorageTracker;\nimport com.refinedmods.refinedstorage.apiimpl.storage.tracker.ItemStorageTracker;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.FilterItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.validator.StorageDiskItemValidator;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport com.refinedmods.refinedstorage.item.WirelessGridItem;\nimport com.refinedmods.refinedstorage.item.blockitem.PortableGridBlockItem;\nimport com.refinedmods.refinedstorage.network.grid.PortableGridSettingsUpdateMessage;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.screen.grid.GridScreen;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.CraftingContainer;\nimport net.minecraft.world.inventory.ResultContainer;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.capabilities.Capabilities;\nimport net.neoforged.neoforge.energy.EnergyStorage;\nimport net.neoforged.neoforge.energy.IEnergyStorage;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.UUID;\n\npublic class PortableGrid implements IGrid, IPortableGrid, IStorageDiskContainerContext {\n    static final String NBT_ITEM_STORAGE_TRACKER_ID = \"ItemStorageTrackerId\";\n    static final String NBT_FLUID_STORAGE_TRACKER_ID = \"FluidStorageTrackerId\";\n    private final PortableItemGridHandler itemHandler = new PortableItemGridHandler(this, this);\n    private final PortableFluidGridHandler fluidHandler = new PortableFluidGridHandler(this);\n    private final PlayerSlot slot;\n    private final List<IFilter> filters = new ArrayList<>();\n    private final List<IGridTab> tabs = new ArrayList<>();\n    @Nullable\n    private IStorageDisk storage;\n    @Nullable\n    private IStorageCache cache;\n    @Nullable\n    private Player player;\n    private ItemStack stack;\n    private final FilterItemHandler filter = (FilterItemHandler) new FilterItemHandler(filters, tabs)\n        .addListener((handler, slot, reading) -> {\n            if (!stack.hasTag()) {\n                stack.setTag(new CompoundTag());\n            }\n\n            StackUtils.writeItems(handler, 0, stack.getTag());\n        });\n    private int sortingType;\n    private int sortingDirection;\n    private int searchBoxMode;\n    private int tabSelected;\n    private int tabPage;\n    private int size;\n    private ItemStorageTracker itemStorageTracker;\n    private UUID itemStorageTrackerId;\n    private FluidStorageTracker fluidStorageTracker;\n    private UUID fluidStorageTrackerId;\n\n    public PortableGrid(@Nullable Player player, ItemStack stack, PlayerSlot slot) {\n        this.player = player;\n        this.stack = stack;\n        this.slot = slot;\n\n        this.sortingType = WirelessGridItem.getSortingType(stack);\n        this.sortingDirection = WirelessGridItem.getSortingDirection(stack);\n        this.searchBoxMode = WirelessGridItem.getSearchBoxMode(stack);\n        this.tabSelected = WirelessGridItem.getTabSelected(stack);\n        this.tabPage = WirelessGridItem.getTabPage(stack);\n        this.size = WirelessGridItem.getSize(stack);\n\n        if (!stack.hasTag()) {\n            stack.setTag(new CompoundTag());\n        }\n        if (player != null) { //baked model does not need a storage tracker\n            if (stack.getTag().contains(NBT_ITEM_STORAGE_TRACKER_ID)) {\n                itemStorageTrackerId = stack.getTag().getUUID(NBT_ITEM_STORAGE_TRACKER_ID);\n            } else {\n                UUID id = UUID.randomUUID();\n                stack.getTag().putUUID(NBT_ITEM_STORAGE_TRACKER_ID, id);\n                itemStorageTrackerId = id;\n            }\n\n            if (stack.getTag().contains(NBT_FLUID_STORAGE_TRACKER_ID)) {\n                fluidStorageTrackerId = stack.getTag().getUUID(NBT_FLUID_STORAGE_TRACKER_ID);\n            } else {\n                UUID id = UUID.randomUUID();\n                stack.getTag().putUUID(NBT_FLUID_STORAGE_TRACKER_ID, id);\n                fluidStorageTrackerId = id;\n            }\n        }\n\n\n        StackUtils.readItems(disk, 4, stack.getTag());\n        StackUtils.readItems(filter, 0, stack.getTag());\n    }\n\n    public void onOpen() {\n        drainEnergy(RS.SERVER_CONFIG.getPortableGrid().getOpenUsage());\n    }\n\n    private final BaseItemHandler disk = new BaseItemHandler(1)\n        .addValidator(new StorageDiskItemValidator())\n        .addListener(((handler, slot, reading) -> {\n            if (player != null && !player.level().isClientSide) {\n                ItemStack diskStack = handler.getStackInSlot(slot);\n\n                if (diskStack.isEmpty()) {\n                    storage = null;\n                    cache = null;\n                } else {\n                    IStorageDisk diskInSlot = API.instance().getStorageDiskManager((ServerLevel) player.level()).getByStack(getDiskInventory().getStackInSlot(0));\n\n                    if (diskInSlot != null) {\n                        StorageType type = ((IStorageDiskProvider) getDiskInventory().getStackInSlot(0).getItem()).getType();\n\n                        if (type == StorageType.ITEM) {\n                            storage = new PortableItemStorageDisk(diskInSlot, PortableGrid.this);\n                            cache = new PortableItemStorageCache(PortableGrid.this);\n                        } else if (type == StorageType.FLUID) {\n                            storage = new PortableFluidStorageDisk(diskInSlot, PortableGrid.this);\n                            cache = new PortableFluidStorageCache(PortableGrid.this);\n                        }\n\n                        storage.setSettings(null, PortableGrid.this);\n                    } else {\n                        storage = null;\n                        cache = null;\n                    }\n                }\n\n                if (cache != null) {\n                    cache.invalidate(InvalidateCause.DISK_INVENTORY_CHANGED);\n                }\n\n                StackUtils.writeItems(handler, 4, stack.getTag());\n            }\n        }));\n\n    public ItemStack getStack() {\n        return stack;\n    }\n\n    @Override\n    @Nullable\n    public IStorageCache getCache() {\n        return cache;\n    }\n\n    @Override\n    @Nullable\n    public IStorageDisk getStorage() {\n        return storage;\n    }\n\n    @Override\n    public void drainEnergy(int energy) {\n        if (RS.SERVER_CONFIG.getPortableGrid().getUseEnergy() && ((PortableGridBlockItem) stack.getItem()).getType() != PortableGridBlockItem.Type.CREATIVE) {\n            IEnergyStorage energyStorage = stack.getCapability(Capabilities.EnergyStorage.ITEM);\n            if (energyStorage != null) {\n                energyStorage.extractEnergy(energy, false);\n            }\n        }\n    }\n\n    @Override\n    public int getEnergy() {\n        if (RS.SERVER_CONFIG.getPortableGrid().getUseEnergy() && ((PortableGridBlockItem) stack.getItem()).getType() != PortableGridBlockItem.Type.CREATIVE) {\n            return Optional.ofNullable(stack.getCapability(Capabilities.EnergyStorage.ITEM))\n                .map(IEnergyStorage::getEnergyStored)\n                .orElse(RS.SERVER_CONFIG.getPortableGrid().getCapacity());\n        }\n\n        return RS.SERVER_CONFIG.getPortableGrid().getCapacity();\n    }\n\n    @Override\n    public BaseItemHandler getDiskInventory() {\n        return disk;\n    }\n\n    public Player getPlayer() {\n        return player;\n    }\n\n    @Override\n    public GridType getGridType() {\n        return (getDiskInventory().getStackInSlot(0).isEmpty() || ((IStorageDiskProvider) getDiskInventory().getStackInSlot(0).getItem()).getType() == StorageType.ITEM) ? GridType.NORMAL : GridType.FLUID;\n    }\n\n    @Nullable\n    @Override\n    public IStorageCache getStorageCache() {\n        return storage != null ? cache : null;\n    }\n\n    @Override\n    public IStorageCacheListener createListener(ServerPlayer player) {\n        return getGridType() == GridType.FLUID ? new PortableFluidGridStorageCacheListener(this, player) : new PortableItemGridStorageCacheListener(this, player);\n    }\n\n    @Nullable\n    @Override\n    public IItemGridHandler getItemHandler() {\n        return itemHandler;\n    }\n\n    @Nullable\n    @Override\n    public IFluidGridHandler getFluidHandler() {\n        return fluidHandler;\n    }\n\n    @Override\n    public void addCraftingListener(ICraftingGridListener listener) {\n        // NO OP\n    }\n\n    @Override\n    public void removeCraftingListener(ICraftingGridListener listener) {\n        // NO OP\n    }\n\n    @Override\n    public Component getTitle() {\n        return Component.translatable(\"gui.refinedstorage.portable_grid\");\n    }\n\n    @Override\n    public int getViewType() {\n        return -1;\n    }\n\n    @Override\n    public int getSortingType() {\n        return sortingType;\n    }\n\n    @Override\n    public int getSortingDirection() {\n        return sortingDirection;\n    }\n\n    @Override\n    public int getSearchBoxMode() {\n        return searchBoxMode;\n    }\n\n    @Override\n    public int getTabSelected() {\n        return tabSelected;\n    }\n\n    @Override\n    public int getTabPage() {\n        return Math.min(tabPage, getTotalTabPages());\n    }\n\n    @Override\n    public int getTotalTabPages() {\n        return (int) Math.floor((float) Math.max(0, tabs.size() - 1) / (float) IGrid.TABS_PER_PAGE);\n    }\n\n    @Override\n    public int getSize() {\n        return size;\n    }\n\n    @Override\n    public void onViewTypeChanged(int type) {\n        // NO OP\n    }\n\n    @Override\n    public void onSortingTypeChanged(int type) {\n        RS.NETWORK_HANDLER.sendToServer(new PortableGridSettingsUpdateMessage(getViewType(), getSortingDirection(), type, getSearchBoxMode(), getSize(), getTabSelected(), getTabPage()));\n\n        this.sortingType = type;\n\n        BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort());\n    }\n\n    @Override\n    public void onSortingDirectionChanged(int direction) {\n        RS.NETWORK_HANDLER.sendToServer(new PortableGridSettingsUpdateMessage(getViewType(), direction, getSortingType(), getSearchBoxMode(), getSize(), getTabSelected(), getTabPage()));\n\n        this.sortingDirection = direction;\n\n        BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort());\n    }\n\n    @Override\n    public void onSearchBoxModeChanged(int searchBoxMode) {\n        RS.NETWORK_HANDLER.sendToServer(new PortableGridSettingsUpdateMessage(getViewType(), getSortingDirection(), getSortingType(), searchBoxMode, getSize(), getTabSelected(), getTabPage()));\n\n        this.searchBoxMode = searchBoxMode;\n    }\n\n    @Override\n    public void onSizeChanged(int size) {\n        RS.NETWORK_HANDLER.sendToServer(new PortableGridSettingsUpdateMessage(getViewType(), getSortingDirection(), getSortingType(), getSearchBoxMode(), size, getTabSelected(), getTabPage()));\n\n        this.size = size;\n\n        BaseScreen.executeLater(GridScreen.class, BaseScreen::init);\n    }\n\n    @Override\n    public void onTabSelectionChanged(int tab) {\n        this.tabSelected = tab == tabSelected ? -1 : tab;\n\n        RS.NETWORK_HANDLER.sendToServer(new PortableGridSettingsUpdateMessage(getViewType(), getSortingDirection(), getSortingType(), getSearchBoxMode(), getSize(), tabSelected, getTabPage()));\n\n        BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort());\n    }\n\n    @Override\n    public void onTabPageChanged(int page) {\n        if (page >= 0 && page <= getTotalTabPages()) {\n            RS.NETWORK_HANDLER.sendToServer(new PortableGridSettingsUpdateMessage(getViewType(), getSortingDirection(), getSortingType(), getSearchBoxMode(), getSize(), getTabSelected(), page));\n\n            this.tabPage = page;\n        }\n    }\n\n    @Override\n    public List<IFilter> getFilters() {\n        return filters;\n    }\n\n    @Override\n    public List<IGridTab> getTabs() {\n        return tabs;\n    }\n\n    @Override\n    public IItemHandlerModifiable getFilter() {\n        return filter;\n    }\n\n    @Override\n    public ItemStorageTracker getItemStorageTracker() {\n        if (itemStorageTracker == null) {\n            if (player != null) {\n                if (itemStorageTrackerId == null) {\n                    this.itemStorageTrackerId = UUID.randomUUID();\n                }\n\n                this.itemStorageTracker = (ItemStorageTracker) API.instance().getStorageTrackerManager((ServerLevel) player.level()).getOrCreate(itemStorageTrackerId, StorageType.ITEM);\n            }\n        }\n\n        return itemStorageTracker;\n    }\n\n    @Override\n    public FluidStorageTracker getFluidStorageTracker() {\n        if (fluidStorageTracker == null) {\n            if (player != null) {\n                if (fluidStorageTrackerId == null) {\n                    this.fluidStorageTrackerId = UUID.randomUUID();\n                }\n\n                this.fluidStorageTracker = (FluidStorageTracker) API.instance().getStorageTrackerManager((ServerLevel) player.level()).getOrCreate(fluidStorageTrackerId, StorageType.FLUID);\n            }\n        }\n\n        return fluidStorageTracker;\n    }\n\n    @Override\n    public CraftingContainer getCraftingMatrix() {\n        return null;\n    }\n\n    @Override\n    public ResultContainer getCraftingResult() {\n        return null;\n    }\n\n    @Override\n    public void onCraftingMatrixChanged() {\n        // NO OP\n    }\n\n    @Override\n    public void onCrafted(Player player, @Nullable IStackList<ItemStack> availableItems, @Nullable IStackList<ItemStack> usedItems) {\n        // NO OP\n    }\n\n    @Override\n    public void onClear(Player player) {\n        // NO OP\n    }\n\n    @Override\n    public void onCraftedShift(Player player) {\n        // NO OP\n    }\n\n    @Override\n    public void onRecipeTransfer(Player player, ItemStack[][] recipe) {\n        // NO OP\n    }\n\n    @Override\n    public void onClosed(Player player) {\n        if (!player.getCommandSenderWorld().isClientSide) {\n            StackUtils.writeItems(disk, 4, stack.getTag());\n        }\n    }\n\n    private boolean hasDisk() {\n        return !disk.getStackInSlot(0).isEmpty();\n    }\n\n    @Override\n    public boolean isGridActive() {\n        if (RS.SERVER_CONFIG.getPortableGrid().getUseEnergy() &&\n            ((PortableGridBlockItem) stack.getItem()).getType() != PortableGridBlockItem.Type.CREATIVE &&\n            Optional.ofNullable(stack.getCapability(Capabilities.EnergyStorage.ITEM)).map(IEnergyStorage::getEnergyStored).orElse(0) <= RS.SERVER_CONFIG.getPortableGrid().getOpenUsage()) {\n            return false;\n        }\n\n        return hasDisk();\n    }\n\n    @Override\n    public int getSlotId() {\n        return slot.getSlotIdInPlayerInventory();\n    }\n\n    @Nullable\n    private UUID getDiskId() {\n        return !hasDisk() ? null : ((IStorageDiskProvider) disk.getStackInSlot(0).getItem()).getId(disk.getStackInSlot(0));\n    }\n\n    private int getStored() {\n        API.instance().getStorageDiskSync().sendRequest(getDiskId());\n\n        StorageDiskSyncData data = API.instance().getStorageDiskSync().getData(getDiskId());\n\n        return data == null ? 0 : data.getStored();\n    }\n\n    private int getCapacity() {\n        API.instance().getStorageDiskSync().sendRequest(getDiskId());\n\n        StorageDiskSyncData data = API.instance().getStorageDiskSync().getData(getDiskId());\n\n        return data == null ? 0 : data.getCapacity();\n    }\n\n    @Override\n    public PortableGridDiskState getDiskState() {\n        if (!hasDisk()) {\n            return PortableGridDiskState.NONE;\n        }\n\n        if (!isGridActive()) {\n            return PortableGridDiskState.DISCONNECTED;\n        }\n\n        int stored = getStored();\n        int capacity = getCapacity();\n\n        if (stored == capacity) {\n            return PortableGridDiskState.FULL;\n        } else if ((int) ((float) stored / (float) capacity * 100F) >= DiskState.DISK_NEAR_CAPACITY_THRESHOLD) {\n            return PortableGridDiskState.NEAR_CAPACITY;\n        } else {\n            return PortableGridDiskState.NORMAL;\n        }\n    }\n\n    @Override\n    public AccessType getAccessType() {\n        return AccessType.INSERT_EXTRACT;\n    }\n\n\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/grid/portable/PortableGridBlockEntity.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.grid.portable;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.api.network.grid.GridType;\nimport com.refinedmods.refinedstorage.api.network.grid.ICraftingGridListener;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.api.network.grid.IGridTab;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler;\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.api.storage.StorageType;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener;\nimport com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskProvider;\nimport com.refinedmods.refinedstorage.api.storage.tracker.IStorageTracker;\nimport com.refinedmods.refinedstorage.api.util.IFilter;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.grid.handler.PortableFluidGridHandler;\nimport com.refinedmods.refinedstorage.apiimpl.network.grid.handler.PortableItemGridHandler;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.DiskState;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.storage.cache.PortableFluidStorageCache;\nimport com.refinedmods.refinedstorage.apiimpl.storage.cache.PortableItemStorageCache;\nimport com.refinedmods.refinedstorage.apiimpl.storage.cache.listener.PortableFluidGridStorageCacheListener;\nimport com.refinedmods.refinedstorage.apiimpl.storage.cache.listener.PortableItemGridStorageCacheListener;\nimport com.refinedmods.refinedstorage.apiimpl.storage.disk.PortableFluidStorageDisk;\nimport com.refinedmods.refinedstorage.apiimpl.storage.disk.PortableItemStorageDisk;\nimport com.refinedmods.refinedstorage.apiimpl.storage.tracker.FluidStorageTracker;\nimport com.refinedmods.refinedstorage.apiimpl.storage.tracker.ItemStorageTracker;\nimport com.refinedmods.refinedstorage.block.PortableGridBlock;\nimport com.refinedmods.refinedstorage.blockentity.BaseBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IRedstoneConfigurable;\nimport com.refinedmods.refinedstorage.blockentity.config.RedstoneMode;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec;\nimport com.refinedmods.refinedstorage.blockentity.grid.GridBlockEntity;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.FilterItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.validator.StorageDiskItemValidator;\nimport com.refinedmods.refinedstorage.inventory.listener.BlockEntityInventoryListener;\nimport com.refinedmods.refinedstorage.item.WirelessGridItem;\nimport com.refinedmods.refinedstorage.item.blockitem.PortableGridBlockItem;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.screen.grid.GridScreen;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.nbt.Tag;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.network.syncher.EntityDataSerializers;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.CraftingContainer;\nimport net.minecraft.world.inventory.ResultContainer;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.capabilities.Capabilities;\nimport net.neoforged.neoforge.energy.EnergyStorage;\nimport net.neoforged.neoforge.energy.IEnergyStorage;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport net.neoforged.neoforge.server.ServerLifecycleHooks;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.UUID;\n\npublic class PortableGridBlockEntity extends BaseBlockEntity implements IGrid, IPortableGrid, IRedstoneConfigurable, IStorageDiskContainerContext {\n    private static final String NBT_ITEM_STORAGE_TRACKER_ID = \"ItemStorageTrackerId\";\n    private static final String NBT_FLUID_STORAGE_TRACKER_ID = \"FluidStorageTrackerId\";\n    private static final String NBT_TYPE = \"Type\";\n    private static final String NBT_ENERGY = \"Energy\";\n    private static final String NBT_ENCHANTMENTS = \"Enchantments\"; // @Volatile: Minecraft specific nbt key, see EnchantmentHelper\n\n    public static final BlockEntitySynchronizationParameter<Integer, PortableGridBlockEntity> REDSTONE_MODE = RedstoneMode.createParameter(new ResourceLocation(RS.ID, \"portable_grid_redstone_mode\"));\n\n    private static final BlockEntitySynchronizationParameter<Integer, PortableGridBlockEntity> SORTING_DIRECTION = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"portable_grid_sorting_direction\"), EntityDataSerializers.INT, 0, PortableGridBlockEntity::getSortingDirection, (t, v) -> {\n        if (IGrid.isValidSortingDirection(v)) {\n            t.setSortingDirection(v);\n            t.setChanged();\n        }\n    }, (initial, p) -> GridBlockEntity.trySortGrid(initial));\n\n    private static final BlockEntitySynchronizationParameter<Integer, PortableGridBlockEntity> SORTING_TYPE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"portable_grid_sorting_type\"), EntityDataSerializers.INT, 0, PortableGridBlockEntity::getSortingType, (t, v) -> {\n        if (IGrid.isValidSortingType(v)) {\n            t.setSortingType(v);\n            t.setChanged();\n        }\n    }, (initial, p) -> GridBlockEntity.trySortGrid(initial));\n\n    private static final BlockEntitySynchronizationParameter<Integer, PortableGridBlockEntity> SEARCH_BOX_MODE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"portable_grid_search_box_mode\"), EntityDataSerializers.INT, 0, PortableGridBlockEntity::getSearchBoxMode, (t, v) -> {\n        if (IGrid.isValidSearchBoxMode(v)) {\n            t.setSearchBoxMode(v);\n            t.setChanged();\n        }\n    }, (initial, p) -> BaseScreen.executeLater(GridScreen.class, grid -> grid.getSearchField().setMode(p)));\n\n    private static final BlockEntitySynchronizationParameter<Integer, PortableGridBlockEntity> SIZE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"portable_grid_size\"), EntityDataSerializers.INT, 0, PortableGridBlockEntity::getSize, (t, v) -> {\n        if (IGrid.isValidSize(v)) {\n            t.setSize(v);\n            t.setChanged();\n        }\n    }, (initial, p) -> BaseScreen.executeLater(GridScreen.class, BaseScreen::init));\n\n    private static final BlockEntitySynchronizationParameter<Integer, PortableGridBlockEntity> TAB_SELECTED = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"portable_grid_tab_selected\"), EntityDataSerializers.INT, 0, PortableGridBlockEntity::getTabSelected, (t, v) -> {\n        t.setTabSelected(v == t.getTabSelected() ? -1 : v);\n        t.setChanged();\n    }, (initial, p) -> BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort()));\n\n    private static final BlockEntitySynchronizationParameter<Integer, PortableGridBlockEntity> TAB_PAGE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, \"portable_grid_tab_page\"), EntityDataSerializers.INT, 0, PortableGridBlockEntity::getTabPage, (t, v) -> {\n        if (v >= 0 && v <= t.getTotalTabPages()) {\n            t.setTabPage(v);\n            t.setChanged();\n        }\n    });\n\n    public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder()\n        .addWatchedParameter(REDSTONE_MODE)\n        .addWatchedParameter(SORTING_DIRECTION)\n        .addWatchedParameter(SORTING_TYPE)\n        .addWatchedParameter(SEARCH_BOX_MODE)\n        .addWatchedParameter(SIZE)\n        .addWatchedParameter(TAB_SELECTED)\n        .addWatchedParameter(TAB_PAGE)\n        .build();\n\n    private final PortableGridBlockItem.Type type;\n    private final List<IFilter> filters = new ArrayList<>();\n    private final List<IGridTab> tabs = new ArrayList<>();\n    private final FilterItemHandler filter = (FilterItemHandler) new FilterItemHandler(filters, tabs).addListener(new BlockEntityInventoryListener(this));\n    private final PortableItemGridHandler itemHandler = new PortableItemGridHandler(this, this);\n    private final PortableFluidGridHandler fluidHandler = new PortableFluidGridHandler(this);\n    private EnergyStorage energyStorage = createEnergyStorage(0);\n    private RedstoneMode redstoneMode = RedstoneMode.IGNORE;\n    private int sortingType;\n    private int sortingDirection;\n    private int searchBoxMode;\n    private int tabSelected;\n    private int tabPage;\n    private int size;\n    private GridType clientGridType;\n    @Nullable\n    private IStorageDisk storage;\n    @Nullable\n    private IStorageCache cache;\n    private PortableGridDiskState diskState = PortableGridDiskState.NONE;\n    private boolean active;\n    private ItemStorageTracker itemStorageTracker;\n    private UUID itemStorageTrackerId;\n    private FluidStorageTracker fluidStorageTracker;\n    private UUID fluidStorageTrackerId;\n    private ListTag enchants = null;\n    private boolean loadNextTick;\n\n    public PortableGridBlockEntity(PortableGridBlockItem.Type type, BlockPos pos, BlockState state) {\n        super(type == PortableGridBlockItem.Type.CREATIVE ? RSBlockEntities.CREATIVE_PORTABLE_GRID.get() : RSBlockEntities.PORTABLE_GRID.get(), pos, state, SPEC);\n        this.type = type;\n    }\n\n    public static void serverTick(PortableGridBlockEntity blockEntity) {\n        if (blockEntity.loadNextTick) {\n            blockEntity.active = blockEntity.isGridActive();\n            blockEntity.diskState = blockEntity.getDiskState();\n            blockEntity.loadNextTick = false;\n        }\n    }\n\n    private final BaseItemHandler disk = new BaseItemHandler(1)\n        .addValidator(new StorageDiskItemValidator())\n        .addListener(new BlockEntityInventoryListener(this))\n        .addListener((handler, slot, reading) -> {\n            if (level != null && !level.isClientSide) {\n                loadStorage();\n\n                if (!reading) {\n                    updateState();\n\n                    LevelUtils.updateBlock(level, worldPosition); // Re-send grid type\n                }\n            }\n        });\n\n    private void loadStorage() {\n        ItemStack diskStack = getDiskInventory().getStackInSlot(0);\n\n        if (diskStack.isEmpty()) {\n            this.storage = null;\n            this.cache = null;\n        } else {\n            IStorageDisk diskInSlot = API.instance().getStorageDiskManager((ServerLevel) level).getByStack(getDiskInventory().getStackInSlot(0));\n\n            if (diskInSlot != null) {\n                StorageType diskType = ((IStorageDiskProvider) getDiskInventory().getStackInSlot(0).getItem()).getType();\n\n                if (diskType == StorageType.ITEM) {\n                    this.storage = new PortableItemStorageDisk(diskInSlot, this);\n                    this.cache = new PortableItemStorageCache(this);\n                } else if (diskType == StorageType.FLUID) {\n                    this.storage = new PortableFluidStorageDisk(diskInSlot, this);\n                    this.cache = new PortableFluidStorageCache(this);\n                }\n\n                this.storage.setSettings(PortableGridBlockEntity.this::updateState, PortableGridBlockEntity.this);\n            } else {\n                this.storage = null;\n                this.cache = null;\n            }\n        }\n\n        if (cache != null) {\n            cache.invalidate(InvalidateCause.DISK_INVENTORY_CHANGED);\n        }\n    }\n\n    @Override\n    public void onLoad() {\n        super.onLoad();\n\n        this.loadStorage();\n\n        loadNextTick = true;\n    }\n\n    public void applyDataFromItemToBlockEntity(ItemStack stack) {\n        this.sortingType = WirelessGridItem.getSortingType(stack);\n        this.sortingDirection = WirelessGridItem.getSortingDirection(stack);\n        this.searchBoxMode = WirelessGridItem.getSearchBoxMode(stack);\n        this.tabSelected = WirelessGridItem.getTabSelected(stack);\n        this.tabPage = WirelessGridItem.getTabPage(stack);\n        this.size = WirelessGridItem.getSize(stack);\n\n        this.energyStorage = createEnergyStorage(\n            Optional.ofNullable(stack.getCapability(Capabilities.EnergyStorage.ITEM)).map(IEnergyStorage::getEnergyStored).orElse(0)\n        );\n\n        if (stack.hasTag()) {\n            for (int i = 0; i < 4; ++i) {\n                StackUtils.readItems(filter, i, stack.getTag());\n            }\n\n            StackUtils.readItems(disk, 4, stack.getTag());\n\n            this.redstoneMode = RedstoneMode.read(stack.getTag());\n            if (stack.getTag().contains(PortableGrid.NBT_ITEM_STORAGE_TRACKER_ID)) {\n                itemStorageTrackerId = stack.getTag().getUUID(NBT_ITEM_STORAGE_TRACKER_ID);\n            }\n\n            if (stack.getTag().contains(PortableGrid.NBT_FLUID_STORAGE_TRACKER_ID)) {\n                fluidStorageTrackerId = stack.getTag().getUUID(NBT_FLUID_STORAGE_TRACKER_ID);\n            }\n\n            if (stack.getTag().contains(NBT_ENCHANTMENTS)) {\n                enchants = stack.getTag().getList(NBT_ENCHANTMENTS, Tag.TAG_COMPOUND);\n            }\n        }\n\n        setChanged();\n    }\n\n    public void applyDataFromBlockEntityToItem(ItemStack stack) {\n        stack.setTag(new CompoundTag());\n\n        stack.getTag().putInt(GridNetworkNode.NBT_SORTING_DIRECTION, sortingDirection);\n        stack.getTag().putInt(GridNetworkNode.NBT_SORTING_TYPE, sortingType);\n        stack.getTag().putInt(GridNetworkNode.NBT_SEARCH_BOX_MODE, searchBoxMode);\n        stack.getTag().putInt(GridNetworkNode.NBT_SIZE, size);\n        stack.getTag().putInt(GridNetworkNode.NBT_TAB_SELECTED, tabSelected);\n        stack.getTag().putInt(GridNetworkNode.NBT_TAB_PAGE, tabPage);\n\n        if (itemStorageTrackerId != null) {\n            stack.getTag().putUUID(PortableGrid.NBT_ITEM_STORAGE_TRACKER_ID, itemStorageTrackerId);\n        }\n        if (fluidStorageTrackerId != null) {\n            stack.getTag().putUUID(PortableGrid.NBT_FLUID_STORAGE_TRACKER_ID, fluidStorageTrackerId);\n        }\n\n        if (enchants != null) {\n            stack.getTag().put(NBT_ENCHANTMENTS, enchants);\n        }\n\n        Optional.ofNullable(stack.getCapability(Capabilities.EnergyStorage.ITEM)).ifPresent(itemEnergy -> itemEnergy.receiveEnergy(energyStorage.getEnergyStored(), false));\n\n        for (int i = 0; i < 4; ++i) {\n            StackUtils.writeItems(filter, i, stack.getTag());\n        }\n\n        StackUtils.writeItems(disk, 4, stack.getTag());\n\n        redstoneMode.write(stack.getTag());\n    }\n\n    private EnergyStorage createEnergyStorage(int energyStored) {\n        return new EnergyStorage(\n            RS.SERVER_CONFIG.getPortableGrid().getCapacity(),\n            RS.SERVER_CONFIG.getPortableGrid().getCapacity(),\n            RS.SERVER_CONFIG.getPortableGrid().getCapacity(),\n            energyStored\n        );\n    }\n\n    @Override\n    public GridType getGridType() {\n        return clientGridType != null ? clientGridType : getServerGridType();\n    }\n\n    private GridType getServerGridType() {\n        return (getDiskInventory().getStackInSlot(0).isEmpty() || ((IStorageDiskProvider) getDiskInventory().getStackInSlot(0).getItem()).getType() == StorageType.ITEM) ? GridType.NORMAL : GridType.FLUID;\n    }\n\n    @Nullable\n    @Override\n    public IStorageCache getStorageCache() {\n        return storage != null ? cache : null;\n    }\n\n    @Override\n    public IStorageCacheListener createListener(ServerPlayer player) {\n        return getServerGridType() == GridType.FLUID ? new PortableFluidGridStorageCacheListener(this, player) : new PortableItemGridStorageCacheListener(this, player);\n    }\n\n    @Nullable\n    @Override\n    public IItemGridHandler getItemHandler() {\n        return itemHandler;\n    }\n\n    @Nullable\n    @Override\n    public IFluidGridHandler getFluidHandler() {\n        return fluidHandler;\n    }\n\n    @Override\n    public void addCraftingListener(ICraftingGridListener listener) {\n        // NO OP\n    }\n\n    @Override\n    public void removeCraftingListener(ICraftingGridListener listener) {\n        // NO OP\n    }\n\n    @Override\n    public Component getTitle() {\n        return Component.translatable(\"gui.refinedstorage.portable_grid\");\n    }\n\n    @Override\n    public int getViewType() {\n        return -1;\n    }\n\n    @Override\n    public int getSortingType() {\n        return level.isClientSide ? SORTING_TYPE.getValue() : sortingType;\n    }\n\n    public void setSortingType(int sortingType) {\n        this.sortingType = sortingType;\n    }\n\n    @Override\n    public int getSortingDirection() {\n        return level.isClientSide ? SORTING_DIRECTION.getValue() : sortingDirection;\n    }\n\n    public void setSortingDirection(int sortingDirection) {\n        this.sortingDirection = sortingDirection;\n    }\n\n    @Override\n    public int getSearchBoxMode() {\n        return level.isClientSide ? SEARCH_BOX_MODE.getValue() : searchBoxMode;\n    }\n\n    public void setSearchBoxMode(int searchBoxMode) {\n        this.searchBoxMode = searchBoxMode;\n    }\n\n    @Override\n    public int getTabSelected() {\n        return level.isClientSide ? TAB_SELECTED.getValue() : tabSelected;\n    }\n\n    public void setTabSelected(int tabSelected) {\n        this.tabSelected = tabSelected;\n    }\n\n    @Override\n    public int getTabPage() {\n        return level.isClientSide ? TAB_PAGE.getValue() : Math.min(tabPage, getTotalTabPages());\n    }\n\n    public void setTabPage(int page) {\n        this.tabPage = page;\n    }\n\n    @Override\n    public int getTotalTabPages() {\n        return (int) Math.floor((float) Math.max(0, tabs.size() - 1) / (float) IGrid.TABS_PER_PAGE);\n    }\n\n    @Override\n    public int getSize() {\n        return level.isClientSide ? SIZE.getValue() : size;\n    }\n\n    public void setSize(int size) {\n        this.size = size;\n    }\n\n    @Override\n    public void onViewTypeChanged(int type) {\n        // NO OP\n    }\n\n    @Override\n    public void onSortingTypeChanged(int type) {\n        BlockEntitySynchronizationManager.setParameter(SORTING_TYPE, type);\n    }\n\n    @Override\n    public void onSortingDirectionChanged(int direction) {\n        BlockEntitySynchronizationManager.setParameter(SORTING_DIRECTION, direction);\n    }\n\n    @Override\n    public void onSearchBoxModeChanged(int searchBoxMode) {\n        BlockEntitySynchronizationManager.setParameter(SEARCH_BOX_MODE, searchBoxMode);\n    }\n\n    @Override\n    public void onSizeChanged(int size) {\n        BlockEntitySynchronizationManager.setParameter(SIZE, size);\n    }\n\n    @Override\n    public void onTabSelectionChanged(int tab) {\n        BlockEntitySynchronizationManager.setParameter(TAB_SELECTED, tab);\n    }\n\n    @Override\n    public void onTabPageChanged(int page) {\n        if (page >= 0 && page <= getTotalTabPages()) {\n            BlockEntitySynchronizationManager.setParameter(PortableGridBlockEntity.TAB_PAGE, page);\n        }\n    }\n\n    @Override\n    public List<IFilter> getFilters() {\n        return filters;\n    }\n\n    @Override\n    public List<IGridTab> getTabs() {\n        return tabs;\n    }\n\n    @Override\n    public IItemHandlerModifiable getFilter() {\n        return filter;\n    }\n\n    @Override\n    public IStorageTracker<ItemStack> getItemStorageTracker() {\n        if (itemStorageTracker == null) {\n            if (itemStorageTrackerId == null) {\n                this.itemStorageTrackerId = UUID.randomUUID();\n            }\n\n            this.itemStorageTracker = (ItemStorageTracker) API.instance().getStorageTrackerManager(ServerLifecycleHooks.getCurrentServer().overworld()).getOrCreate(itemStorageTrackerId, StorageType.ITEM);\n        }\n\n        return itemStorageTracker;\n    }\n\n    @Override\n    public IStorageTracker<FluidStack> getFluidStorageTracker() {\n        if (fluidStorageTracker == null) {\n            if (fluidStorageTrackerId == null) {\n                this.fluidStorageTrackerId = UUID.randomUUID();\n            }\n\n            this.fluidStorageTracker = (FluidStorageTracker) API.instance().getStorageTrackerManager(ServerLifecycleHooks.getCurrentServer().overworld()).getOrCreate(fluidStorageTrackerId, StorageType.FLUID);\n        }\n\n        return fluidStorageTracker;\n    }\n\n    @Override\n    public CraftingContainer getCraftingMatrix() {\n        return null;\n    }\n\n    @Override\n    public ResultContainer getCraftingResult() {\n        return null;\n    }\n\n    @Override\n    public void onCraftingMatrixChanged() {\n        // NO OP\n    }\n\n    @Override\n    public void onCrafted(Player player, @Nullable IStackList<ItemStack> availableItems, @Nullable IStackList<ItemStack> usedItems) {\n        // NO OP\n    }\n\n    @Override\n    public void onClear(Player player) {\n        // NO OP\n    }\n\n    @Override\n    public void onCraftedShift(Player player) {\n        // NO OP\n    }\n\n    @Override\n    public void onRecipeTransfer(Player player, ItemStack[][] recipe) {\n        // NO OP\n    }\n\n    @Override\n    public void onClosed(Player player) {\n        // NO OP\n    }\n\n    private boolean hasDisk() {\n        return !disk.getStackInSlot(0).isEmpty();\n    }\n\n    @Override\n    public boolean isGridActive() {\n        if (level.isClientSide) {\n            BlockState state = level.getBlockState(worldPosition);\n\n            if (state.getBlock() instanceof PortableGridBlock) {\n                return state.getValue(PortableGridBlock.ACTIVE);\n            }\n\n            return false;\n        }\n\n        if (RS.SERVER_CONFIG.getPortableGrid().getUseEnergy() &&\n            type != PortableGridBlockItem.Type.CREATIVE &&\n            energyStorage.getEnergyStored() <= RS.SERVER_CONFIG.getPortableGrid().getOpenUsage()) {\n            return false;\n        }\n\n        if (!hasDisk()) {\n            return false;\n        }\n\n        return redstoneMode.isEnabled(level.hasNeighborSignal(worldPosition));\n    }\n\n    @Override\n    public int getSlotId() {\n        return -1;\n    }\n\n    @Override\n    @Nullable\n    public IStorageCache getCache() {\n        return cache;\n    }\n\n    @Override\n    @Nullable\n    public IStorageDisk getStorage() {\n        return storage;\n    }\n\n    @Override\n    public void drainEnergy(int energy) {\n        if (RS.SERVER_CONFIG.getPortableGrid().getUseEnergy() &&\n            type != PortableGridBlockItem.Type.CREATIVE &&\n            redstoneMode.isEnabled(level.hasNeighborSignal(worldPosition))) {\n            energyStorage.extractEnergy(energy, false);\n\n            updateState();\n        }\n    }\n\n    @Override\n    public int getEnergy() {\n        if (RS.SERVER_CONFIG.getPortableGrid().getUseEnergy() && type != PortableGridBlockItem.Type.CREATIVE) {\n            return energyStorage.getEnergyStored();\n        }\n\n        return RS.SERVER_CONFIG.getPortableGrid().getCapacity();\n    }\n\n    public EnergyStorage getEnergyStorage() {\n        return energyStorage;\n    }\n\n    @Override\n    public PortableGridDiskState getDiskState() {\n        if (!hasDisk()) {\n            return PortableGridDiskState.NONE;\n        }\n\n        if (!isGridActive()) {\n            return PortableGridDiskState.DISCONNECTED;\n        }\n\n        int stored = storage != null ? storage.getStored() : 0;\n        int capacity = storage != null ? storage.getCapacity() : 0;\n\n        if (stored == capacity) {\n            return PortableGridDiskState.FULL;\n        } else if ((int) ((float) stored / (float) capacity * 100F) >= DiskState.DISK_NEAR_CAPACITY_THRESHOLD) {\n            return PortableGridDiskState.NEAR_CAPACITY;\n        } else {\n            return PortableGridDiskState.NORMAL;\n        }\n    }\n\n    public void updateState() {\n        PortableGridDiskState newDiskState = getDiskState();\n\n        if (this.diskState != newDiskState) {\n            this.diskState = newDiskState;\n\n            level.setBlockAndUpdate(worldPosition, level.getBlockState(worldPosition).setValue(PortableGridBlock.DISK_STATE, diskState));\n        }\n\n        boolean isActive = isGridActive();\n\n        if (this.active != isActive) {\n            this.active = isActive;\n\n            level.setBlockAndUpdate(worldPosition, level.getBlockState(worldPosition).setValue(PortableGridBlock.ACTIVE, active));\n        }\n    }\n\n    @Override\n    public BaseItemHandler getDiskInventory() {\n        return disk;\n    }\n\n    @Override\n    public void saveAdditional(CompoundTag tag) {\n        super.saveAdditional(tag);\n\n        tag.putInt(GridNetworkNode.NBT_SORTING_DIRECTION, sortingDirection);\n        tag.putInt(GridNetworkNode.NBT_SORTING_TYPE, sortingType);\n        tag.putInt(GridNetworkNode.NBT_SEARCH_BOX_MODE, searchBoxMode);\n        tag.putInt(GridNetworkNode.NBT_SIZE, size);\n        tag.putInt(GridNetworkNode.NBT_TAB_SELECTED, tabSelected);\n        tag.putInt(GridNetworkNode.NBT_TAB_PAGE, tabPage);\n\n        StackUtils.writeItems(disk, 0, tag);\n        StackUtils.writeItems(filter, 1, tag);\n\n        tag.putInt(NBT_ENERGY, energyStorage.getEnergyStored());\n\n        redstoneMode.write(tag);\n\n        if (itemStorageTrackerId != null) {\n            tag.putUUID(NBT_ITEM_STORAGE_TRACKER_ID, itemStorageTrackerId);\n        }\n        if (fluidStorageTrackerId != null) {\n            tag.putUUID(NBT_FLUID_STORAGE_TRACKER_ID, fluidStorageTrackerId);\n        }\n\n        if (enchants != null) {\n            tag.put(NBT_ENCHANTMENTS, enchants);\n        }\n    }\n\n    @Override\n    public void load(CompoundTag tag) {\n        super.load(tag);\n\n        if (tag.contains(GridNetworkNode.NBT_SORTING_DIRECTION)) {\n            sortingDirection = tag.getInt(GridNetworkNode.NBT_SORTING_DIRECTION);\n        }\n\n        if (tag.contains(GridNetworkNode.NBT_SORTING_TYPE)) {\n            sortingType = tag.getInt(GridNetworkNode.NBT_SORTING_TYPE);\n        }\n\n        if (tag.contains(GridNetworkNode.NBT_SEARCH_BOX_MODE)) {\n            searchBoxMode = tag.getInt(GridNetworkNode.NBT_SEARCH_BOX_MODE);\n        }\n\n        if (tag.contains(GridNetworkNode.NBT_SIZE)) {\n            size = tag.getInt(GridNetworkNode.NBT_SIZE);\n        }\n\n        if (tag.contains(GridNetworkNode.NBT_TAB_SELECTED)) {\n            tabSelected = tag.getInt(GridNetworkNode.NBT_TAB_SELECTED);\n        }\n\n        if (tag.contains(GridNetworkNode.NBT_TAB_PAGE)) {\n            tabPage = tag.getInt(GridNetworkNode.NBT_TAB_PAGE);\n        }\n\n        StackUtils.readItems(disk, 0, tag);\n        StackUtils.readItems(filter, 1, tag);\n\n        if (tag.contains(NBT_ENERGY)) {\n            energyStorage = createEnergyStorage(tag.getInt(NBT_ENERGY));\n        }\n\n        redstoneMode = RedstoneMode.read(tag);\n\n        if (tag.contains(NBT_ITEM_STORAGE_TRACKER_ID)) {\n            itemStorageTrackerId = tag.getUUID(NBT_ITEM_STORAGE_TRACKER_ID);\n        }\n\n        if (tag.contains(NBT_FLUID_STORAGE_TRACKER_ID)) {\n            fluidStorageTrackerId = tag.getUUID(NBT_FLUID_STORAGE_TRACKER_ID);\n        }\n\n        if (tag.contains(NBT_ENCHANTMENTS)) {\n            enchants = tag.getList(NBT_ENCHANTMENTS, Tag.TAG_COMPOUND);\n        }\n    }\n\n    @Override\n    public CompoundTag writeUpdate(CompoundTag tag) {\n        tag.putInt(NBT_TYPE, getServerGridType().ordinal());\n\n        return super.writeUpdate(tag);\n    }\n\n    @Override\n    public void readUpdate(CompoundTag tag) {\n        super.readUpdate(tag);\n\n        clientGridType = GridType.values()[tag.getInt(NBT_TYPE)];\n    }\n\n    public void onOpened() {\n        drainEnergy(RS.SERVER_CONFIG.getPortableGrid().getOpenUsage());\n    }\n\n    @Override\n    public RedstoneMode getRedstoneMode() {\n        return redstoneMode;\n    }\n\n    @Override\n    public void setRedstoneMode(RedstoneMode mode) {\n        this.redstoneMode = mode;\n\n        setChanged();\n    }\n\n    @Override\n    public AccessType getAccessType() {\n        return AccessType.INSERT_EXTRACT;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/blockentity/grid/portable/PortableGridDiskState.java",
    "content": "package com.refinedmods.refinedstorage.blockentity.grid.portable;\n\nimport net.minecraft.util.StringRepresentable;\n\npublic enum PortableGridDiskState implements StringRepresentable {\n    NORMAL(0, \"normal\"),\n    NEAR_CAPACITY(1, \"near_capacity\"),\n    FULL(2, \"full\"),\n    DISCONNECTED(3, \"disconnected\"),\n    NONE(4, \"none\");\n\n    private final int id;\n    private final String type;\n\n    PortableGridDiskState(int id, String type) {\n        this.id = id;\n        this.type = type;\n    }\n\n    public int getId() {\n        return id;\n    }\n\n    @Override\n    public String getSerializedName() {\n        return type;\n    }\n\n    @Override\n    public String toString() {\n        return type;\n    }\n}\n\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/command/disk/CreateDiskCommand.java",
    "content": "package com.refinedmods.refinedstorage.command.disk;\n\nimport com.mojang.brigadier.Command;\nimport com.mojang.brigadier.builder.ArgumentBuilder;\nimport com.mojang.brigadier.context.CommandContext;\nimport com.mojang.brigadier.exceptions.CommandSyntaxException;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskFactory;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.render.Styles;\nimport net.minecraft.commands.CommandSourceStack;\nimport net.minecraft.commands.Commands;\nimport net.minecraft.commands.arguments.EntityArgument;\nimport net.minecraft.commands.arguments.UuidArgument;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.sounds.SoundEvents;\nimport net.minecraft.sounds.SoundSource;\nimport net.minecraft.world.entity.item.ItemEntity;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\n\nimport java.util.UUID;\n\npublic class CreateDiskCommand implements Command<CommandSourceStack> {\n    public static ArgumentBuilder<CommandSourceStack, ?> register() {\n        return Commands.literal(\"create\")\n            .requires(cs -> cs.hasPermission(2))\n            .then(Commands.argument(\"player\", EntityArgument.player())\n                .then(Commands.argument(\"id\", UuidArgument.uuid()).suggests(new StorageDiskIdSuggestionProvider())\n                    .executes(new CreateDiskCommand())\n                )\n            );\n    }\n\n    @Override\n    public int run(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {\n        Player player = EntityArgument.getPlayer(context, \"player\");\n        UUID id = UuidArgument.getUuid(context, \"id\");\n\n        IStorageDisk<?> disk = API.instance().getStorageDiskManager(context.getSource().getLevel()).get(id);\n        if (disk == null) {\n            context.getSource().sendFailure(Component.translatable(\"commands.refinedstorage.disk.create.error.disk_not_found\", id));\n        } else {\n            IStorageDiskFactory factory = API.instance().getStorageDiskRegistry().get(disk.getFactoryId());\n\n            if (factory != null) {\n                ItemStack stack = factory.createDiskItem(disk, id);\n\n                // @Volatile: From GiveCommand\n                boolean flag = player.getInventory().add(stack);\n                if (flag && stack.isEmpty()) {\n                    stack.setCount(1);\n\n                    ItemEntity itemEntity = player.drop(stack, false);\n                    if (itemEntity != null) {\n                        itemEntity.makeFakeItem();\n                    }\n\n                    player.level().playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.ITEM_PICKUP, SoundSource.PLAYERS, 0.2F, ((player.getRandom().nextFloat() - player.getRandom().nextFloat()) * 0.7F + 1.0F) * 2.0F);\n                    player.containerMenu.broadcastChanges();\n                } else {\n                    ItemEntity itemEntity = player.drop(stack, false);\n                    if (itemEntity != null) {\n                        itemEntity.setNoPickUpDelay();\n                        itemEntity.setThrower(player);\n                    }\n                }\n\n                context.getSource().sendSuccess(() -> Component.translatable(\n                    \"commands.refinedstorage.disk.create.success\",\n                    Component.literal(id.toString()).setStyle(Styles.YELLOW),\n                    context.getSource().getDisplayName().copy().setStyle(Styles.YELLOW)\n                ), false);\n            }\n        }\n\n        return 0;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/command/disk/ListDiskCommand.java",
    "content": "package com.refinedmods.refinedstorage.command.disk;\n\nimport com.mojang.brigadier.Command;\nimport com.mojang.brigadier.builder.ArgumentBuilder;\nimport com.mojang.brigadier.context.CommandContext;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport net.minecraft.commands.CommandSourceStack;\nimport net.minecraft.commands.Commands;\nimport net.minecraft.network.chat.Component;\n\npublic class ListDiskCommand implements Command<CommandSourceStack> {\n    public static ArgumentBuilder<CommandSourceStack, ?> register() {\n        return Commands.literal(\"list\")\n            .requires(cs -> cs.hasPermission(2))\n            .executes(new ListDiskCommand())\n            .then(ListDiskForPlayerCommand.register());\n    }\n\n    @Override\n    public int run(CommandContext<CommandSourceStack> context) {\n        API.instance().getStorageDiskManager(context.getSource().getLevel())\n            .getAll()\n            .keySet()\n            .forEach(id -> context.getSource().sendSuccess(() -> Component.literal(id.toString()), false));\n\n        return 0;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/command/disk/ListDiskForPlayerCommand.java",
    "content": "package com.refinedmods.refinedstorage.command.disk;\n\nimport com.mojang.brigadier.Command;\nimport com.mojang.brigadier.builder.ArgumentBuilder;\nimport com.mojang.brigadier.context.CommandContext;\nimport com.mojang.brigadier.exceptions.CommandSyntaxException;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport net.minecraft.commands.CommandSourceStack;\nimport net.minecraft.commands.Commands;\nimport net.minecraft.commands.arguments.EntityArgument;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.world.entity.player.Player;\n\nimport java.util.Map;\n\npublic class ListDiskForPlayerCommand implements Command<CommandSourceStack> {\n    public static ArgumentBuilder<CommandSourceStack, ?> register() {\n        return Commands.argument(\"player\", EntityArgument.player()).executes(new ListDiskForPlayerCommand());\n    }\n\n    @Override\n    public int run(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {\n        Player player = EntityArgument.getPlayer(context, \"player\");\n\n        API.instance().getStorageDiskManager(context.getSource().getLevel())\n            .getAll()\n            .entrySet()\n            .stream()\n            .filter(entry -> player.getGameProfile().getId().equals(entry.getValue().getOwner()))\n            .map(Map.Entry::getKey)\n            .forEach(id -> context.getSource().sendSuccess(() -> Component.literal(id.toString()), false));\n\n        return 0;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/command/disk/StorageDiskIdSuggestionProvider.java",
    "content": "package com.refinedmods.refinedstorage.command.disk;\n\nimport com.mojang.brigadier.context.CommandContext;\nimport com.mojang.brigadier.suggestion.SuggestionProvider;\nimport com.mojang.brigadier.suggestion.Suggestions;\nimport com.mojang.brigadier.suggestion.SuggestionsBuilder;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport net.minecraft.commands.CommandSourceStack;\n\nimport java.util.concurrent.CompletableFuture;\n\npublic class StorageDiskIdSuggestionProvider implements SuggestionProvider<CommandSourceStack> {\n    @Override\n    public CompletableFuture<Suggestions> getSuggestions(CommandContext<CommandSourceStack> context, SuggestionsBuilder builder) {\n        API.instance().getStorageDiskManager(context.getSource().getLevel())\n            .getAll()\n            .keySet()\n            .forEach(id -> builder.suggest(id.toString()));\n\n        return builder.buildFuture();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/command/network/GetNetworkCommand.java",
    "content": "package com.refinedmods.refinedstorage.command.network;\n\nimport com.mojang.brigadier.builder.ArgumentBuilder;\nimport com.mojang.brigadier.context.CommandContext;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.command.network.autocrafting.CancelAllAutocraftingCommand;\nimport com.refinedmods.refinedstorage.command.network.autocrafting.GetAutocraftingCommand;\nimport com.refinedmods.refinedstorage.command.network.autocrafting.ListAutocraftingCommand;\nimport net.minecraft.commands.CommandSourceStack;\nimport net.minecraft.commands.Commands;\nimport net.minecraft.commands.arguments.DimensionArgument;\nimport net.minecraft.commands.arguments.coordinates.BlockPosArgument;\n\npublic class GetNetworkCommand extends NetworkCommand {\n    public static ArgumentBuilder<CommandSourceStack, ?> register() {\n        return Commands.literal(\"get\")\n            .requires(cs -> cs.hasPermission(2))\n            .then(Commands.argument(\"dimension\", DimensionArgument.dimension())\n                .then(Commands.argument(\"pos\", BlockPosArgument.blockPos()).suggests(new NetworkPositionSuggestionProvider())\n                    .executes(new GetNetworkCommand())\n                    .then(Commands.literal(\"autocrafting\")\n                        .then(ListAutocraftingCommand.register())\n                        .then(GetAutocraftingCommand.register())\n                        .then(CancelAllAutocraftingCommand.register())\n                    )));\n    }\n\n    @Override\n    protected int run(CommandContext<CommandSourceStack> context, INetwork network) {\n        ListNetworkCommand.sendInfo(context, new ListNetworkCommand.NetworkInList(network), true);\n        return 0;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/command/network/ListNetworkCommand.java",
    "content": "package com.refinedmods.refinedstorage.command.network;\n\nimport com.mojang.brigadier.Command;\nimport com.mojang.brigadier.builder.ArgumentBuilder;\nimport com.mojang.brigadier.context.CommandContext;\nimport com.mojang.brigadier.exceptions.CommandSyntaxException;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.render.Styles;\nimport net.minecraft.commands.CommandSourceStack;\nimport net.minecraft.commands.Commands;\nimport net.minecraft.commands.arguments.DimensionArgument;\n\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerLevel;\n\nimport java.text.DecimalFormat;\nimport java.util.Comparator;\n\npublic class ListNetworkCommand implements Command<CommandSourceStack> {\n    private static final DecimalFormat TIME_FORMATTER = new DecimalFormat(\"########0.000\");\n\n    public static ArgumentBuilder<CommandSourceStack, ?> register() {\n        return Commands.literal(\"list\")\n            .requires(cs -> cs.hasPermission(2))\n            .then(Commands.argument(\"dimension\", DimensionArgument.dimension())\n                .executes(new ListNetworkCommand()));\n    }\n\n    public static void sendInfo(CommandContext<CommandSourceStack> context, NetworkInList listItem, boolean detailed) {\n        context.getSource().sendSuccess(() ->\n            Component.translatable(\n                \"commands.refinedstorage.network.list.pos\",\n                listItem.network.getPosition().getX(),\n                listItem.network.getPosition().getY(),\n                listItem.network.getPosition().getZ()\n            )\n                .append(\" [\")\n                .append(Component.translatable(\n                    \"commands.refinedstorage.network.list.tick_times\",\n                    Component.literal(TIME_FORMATTER.format(listItem.tickTime)).setStyle(Styles.YELLOW),\n                    Component.literal(TIME_FORMATTER.format(listItem.tps)).setStyle(Styles.YELLOW)\n                ))\n                .append(\"]\"), false);\n\n        if (detailed) {\n            context.getSource().sendSuccess(() -> Component.translatable(\"commands.refinedstorage.network.list.autocrafting_tasks\",\n                Component.literal(listItem.network.getCraftingManager().getTasks().size() + \"\").setStyle(Styles.YELLOW)\n            ), false);\n\n            context.getSource().sendSuccess(() -> Component.translatable(\"commands.refinedstorage.network.list.nodes\",\n                Component.literal(listItem.network.getNodeGraph().all().size() + \"\").setStyle(Styles.YELLOW)\n            ), false);\n\n            context.getSource().sendSuccess(() -> Component.translatable(\"commands.refinedstorage.network.list.energy_usage\",\n                Component.literal(listItem.network.getEnergyUsage() + \"\").setStyle(Styles.YELLOW)\n            ), false);\n        }\n    }\n\n    @Override\n    public int run(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {\n        ServerLevel level = DimensionArgument.getDimension(context, \"dimension\");\n\n        API.instance().getNetworkManager(level)\n            .all()\n            .stream()\n            .map(NetworkInList::new)\n            .sorted(Comparator.comparingDouble(network -> network.tickTime))\n            .forEach(listItem -> sendInfo(context, listItem, false));\n\n        return 0;\n    }\n\n    public static class NetworkInList {\n        private final double tickTime;\n        private final double tps;\n        private final INetwork network;\n\n        public NetworkInList(INetwork network) {\n            this.network = network;\n            // @Volatile: From TPSCommand\n            this.tickTime = mean(network.getTickTimes()) * 1.0E-6D;\n            this.tps = Math.min(1000.0 / tickTime, 20);\n        }\n\n        private long mean(long[] values) {\n            long sum = 0L;\n            for (long v : values) {\n                sum += v;\n            }\n            return sum / values.length;\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/command/network/NetworkCommand.java",
    "content": "package com.refinedmods.refinedstorage.command.network;\n\nimport com.mojang.brigadier.Command;\nimport com.mojang.brigadier.context.CommandContext;\nimport com.mojang.brigadier.exceptions.CommandSyntaxException;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport net.minecraft.commands.CommandSourceStack;\nimport net.minecraft.commands.arguments.DimensionArgument;\nimport net.minecraft.commands.arguments.coordinates.BlockPosArgument;\nimport net.minecraft.core.BlockPos;\n\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerLevel;\n\npublic abstract class NetworkCommand implements Command<CommandSourceStack> {\n    @Override\n    public int run(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {\n        ServerLevel level = DimensionArgument.getDimension(context, \"dimension\");\n        BlockPos pos = BlockPosArgument.getLoadedBlockPos(context, \"pos\");\n\n        INetwork network = API.instance().getNetworkManager(level).getNetwork(pos);\n\n        if (network == null) {\n            context.getSource().sendFailure(Component.translatable(\"commands.refinedstorage.network.get.error.not_found\"));\n            return 0;\n        } else {\n            return run(context, network);\n        }\n    }\n\n    protected abstract int run(CommandContext<CommandSourceStack> context, INetwork network) throws CommandSyntaxException;\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/command/network/NetworkPositionSuggestionProvider.java",
    "content": "package com.refinedmods.refinedstorage.command.network;\n\nimport com.mojang.brigadier.context.CommandContext;\nimport com.mojang.brigadier.exceptions.CommandSyntaxException;\nimport com.mojang.brigadier.suggestion.SuggestionProvider;\nimport com.mojang.brigadier.suggestion.Suggestions;\nimport com.mojang.brigadier.suggestion.SuggestionsBuilder;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport net.minecraft.commands.CommandSourceStack;\nimport net.minecraft.commands.arguments.DimensionArgument;\nimport net.minecraft.server.level.ServerLevel;\n\nimport java.util.concurrent.CompletableFuture;\n\npublic class NetworkPositionSuggestionProvider implements SuggestionProvider<CommandSourceStack> {\n    @Override\n    public CompletableFuture<Suggestions> getSuggestions(CommandContext<CommandSourceStack> context, SuggestionsBuilder builder) throws CommandSyntaxException {\n        ServerLevel level = DimensionArgument.getDimension(context, \"dimension\");\n\n        API.instance().getNetworkManager(level).all().forEach(network -> builder.suggest(network.getPosition().getX() + \" \" + network.getPosition().getY() + \" \" + network.getPosition().getZ()));\n\n        return builder.buildFuture();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/command/network/autocrafting/AutocraftingIdSuggestionProvider.java",
    "content": "package com.refinedmods.refinedstorage.command.network.autocrafting;\n\nimport com.mojang.brigadier.context.CommandContext;\nimport com.mojang.brigadier.exceptions.CommandSyntaxException;\nimport com.mojang.brigadier.suggestion.SuggestionProvider;\nimport com.mojang.brigadier.suggestion.Suggestions;\nimport com.mojang.brigadier.suggestion.SuggestionsBuilder;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport net.minecraft.commands.CommandSourceStack;\nimport net.minecraft.commands.arguments.DimensionArgument;\nimport net.minecraft.commands.arguments.coordinates.BlockPosArgument;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.server.level.ServerLevel;\n\nimport java.util.concurrent.CompletableFuture;\n\npublic class AutocraftingIdSuggestionProvider implements SuggestionProvider<CommandSourceStack> {\n    @Override\n    public CompletableFuture<Suggestions> getSuggestions(CommandContext<CommandSourceStack> context, SuggestionsBuilder builder) throws CommandSyntaxException {\n        ServerLevel level = DimensionArgument.getDimension(context, \"dimension\");\n        BlockPos pos = BlockPosArgument.getLoadedBlockPos(context, \"pos\");\n        INetwork network = API.instance().getNetworkManager(level).getNetwork(pos);\n\n        if (network != null) {\n            network.getCraftingManager().getTasks().forEach(task -> builder.suggest(task.getId().toString()));\n        }\n\n        return builder.buildFuture();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/command/network/autocrafting/CancelAllAutocraftingCommand.java",
    "content": "package com.refinedmods.refinedstorage.command.network.autocrafting;\n\nimport com.mojang.brigadier.builder.ArgumentBuilder;\nimport com.mojang.brigadier.context.CommandContext;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.command.network.NetworkCommand;\nimport com.refinedmods.refinedstorage.render.Styles;\nimport net.minecraft.commands.CommandSourceStack;\nimport net.minecraft.commands.Commands;\nimport net.minecraft.network.chat.Component;\n\n\npublic class CancelAllAutocraftingCommand extends NetworkCommand {\n    public static ArgumentBuilder<CommandSourceStack, ?> register() {\n        return Commands.literal(\"cancel\")\n            .executes(new CancelAllAutocraftingCommand())\n            .then(CancelSingleAutocraftingCommand.register());\n    }\n\n    public static void sendCancelMessage(CommandContext<CommandSourceStack> context, int count) {\n        final String translationKey = count == 1\n            ? \"commands.refinedstorage.network.autocrafting.cancel.single\"\n            : \"commands.refinedstorage.network.autocrafting.cancel.multiple\";\n        context.getSource().sendSuccess(() -> Component.translatable(translationKey, Component.literal(String.valueOf(count)).setStyle(Styles.YELLOW)), false);\n    }\n\n    @Override\n    protected int run(CommandContext<CommandSourceStack> context, INetwork network) {\n        int count = network.getCraftingManager().getTasks().size();\n\n        network.getCraftingManager().getTasks().forEach(task -> network.getCraftingManager().cancel(task.getId()));\n\n        sendCancelMessage(context, count);\n\n        return 0;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/command/network/autocrafting/CancelSingleAutocraftingCommand.java",
    "content": "package com.refinedmods.refinedstorage.command.network.autocrafting;\n\nimport com.mojang.brigadier.builder.ArgumentBuilder;\nimport com.mojang.brigadier.context.CommandContext;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.command.network.NetworkCommand;\nimport net.minecraft.commands.CommandSourceStack;\nimport net.minecraft.commands.Commands;\nimport net.minecraft.commands.arguments.UuidArgument;\n\nimport java.util.UUID;\n\npublic class CancelSingleAutocraftingCommand extends NetworkCommand {\n    public static ArgumentBuilder<CommandSourceStack, ?> register() {\n        return Commands.argument(\"id\", UuidArgument.uuid()).suggests(new AutocraftingIdSuggestionProvider())\n            .executes(new CancelSingleAutocraftingCommand());\n    }\n\n    @Override\n    protected int run(CommandContext<CommandSourceStack> context, INetwork network) {\n        UUID id = UuidArgument.getUuid(context, \"id\");\n\n        int count = 0;\n\n        ICraftingTask task = network.getCraftingManager().getTask(id);\n        if (task != null) {\n            count = 1;\n            network.getCraftingManager().cancel(task.getId());\n        }\n\n        CancelAllAutocraftingCommand.sendCancelMessage(context, count);\n\n        return 0;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/command/network/autocrafting/GetAutocraftingCommand.java",
    "content": "package com.refinedmods.refinedstorage.command.network.autocrafting;\n\nimport com.mojang.brigadier.builder.ArgumentBuilder;\nimport com.mojang.brigadier.context.CommandContext;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.command.network.NetworkCommand;\nimport net.minecraft.commands.CommandSourceStack;\nimport net.minecraft.commands.Commands;\nimport net.minecraft.commands.arguments.UuidArgument;\nimport net.minecraft.network.chat.Component;\n\n\nimport java.util.UUID;\n\npublic class GetAutocraftingCommand extends NetworkCommand {\n    public static ArgumentBuilder<CommandSourceStack, ?> register() {\n        return Commands.literal(\"get\").then(\n            Commands.argument(\"id\", UuidArgument.uuid()).suggests(new AutocraftingIdSuggestionProvider())\n                .executes(new GetAutocraftingCommand())\n        );\n    }\n\n    @Override\n    protected int run(CommandContext<CommandSourceStack> context, INetwork network) {\n        UUID id = UuidArgument.getUuid(context, \"id\");\n\n        ICraftingTask task = network.getCraftingManager().getTask(id);\n        if (task == null) {\n            context.getSource().sendFailure(Component.translatable(\"commands.refinedstorage.network.autocrafting.get.error.not_found\"));\n        } else {\n            ListAutocraftingCommand.addInfo(context, task);\n        }\n\n        return 0;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/command/network/autocrafting/ListAutocraftingCommand.java",
    "content": "package com.refinedmods.refinedstorage.command.network.autocrafting;\n\nimport com.mojang.brigadier.builder.ArgumentBuilder;\nimport com.mojang.brigadier.context.CommandContext;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingRequestInfo;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.command.network.NetworkCommand;\nimport com.refinedmods.refinedstorage.render.Styles;\nimport net.minecraft.commands.CommandSourceStack;\nimport net.minecraft.commands.Commands;\nimport net.minecraft.network.chat.Component;\n\npublic class ListAutocraftingCommand extends NetworkCommand {\n    public static ArgumentBuilder<CommandSourceStack, ?> register() {\n        return Commands.literal(\"list\").executes(new ListAutocraftingCommand());\n    }\n\n    public static void addInfo(CommandContext<CommandSourceStack> context, ICraftingTask task) {\n        context.getSource().sendSuccess(() ->\n                Component.literal(getAmount(task.getRequested()) + \"x \")\n                .append(getName(task.getRequested()).copy().setStyle(Styles.YELLOW))\n                .append(\" \")\n                .append(\"(\" + task.getCompletionPercentage() + \"%)\")\n                .append(\" \")\n                .append(Component.literal(\"[\" + task.getId().toString() + \"]\").setStyle(Styles.GRAY)),\n            false\n        );\n    }\n\n    private static int getAmount(ICraftingRequestInfo info) {\n        if (info.getItem() != null) {\n            return info.getItem().getCount();\n        }\n\n        if (info.getFluid() != null) {\n            return info.getFluid().getAmount();\n        }\n\n        return 0;\n    }\n\n    private static Component getName(ICraftingRequestInfo info) {\n        if (info.getItem() != null) {\n            return info.getItem().getHoverName();\n        }\n\n        if (info.getFluid() != null) {\n            return info.getFluid().getDisplayName();\n        }\n\n        return Component.empty();\n    }\n\n    @Override\n    protected int run(CommandContext<CommandSourceStack> context, INetwork network) {\n        network.getCraftingManager().getTasks().forEach(task -> addInfo(context, task));\n        return 0;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/command/pattern/PatternDumpCommand.java",
    "content": "package com.refinedmods.refinedstorage.command.pattern;\n\nimport com.mojang.brigadier.Command;\nimport com.mojang.brigadier.builder.ArgumentBuilder;\nimport com.mojang.brigadier.context.CommandContext;\nimport com.mojang.brigadier.exceptions.CommandSyntaxException;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.AllowedTagList;\nimport com.refinedmods.refinedstorage.item.PatternItem;\nimport com.refinedmods.refinedstorage.render.Styles;\nimport net.minecraft.commands.CommandSourceStack;\nimport net.minecraft.commands.Commands;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\n\npublic class PatternDumpCommand implements Command<CommandSourceStack> {\n    public static ArgumentBuilder<CommandSourceStack, ?> register() {\n        return Commands.literal(\"dump\")\n            .executes(new PatternDumpCommand());\n    }\n\n    @Override\n    public int run(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {\n        ItemStack stack = context.getSource().getPlayerOrException().getInventory().getSelected();\n\n        if (stack.getItem() instanceof PatternItem) {\n            boolean processing = PatternItem.isProcessing(stack);\n            boolean exact = PatternItem.isExact(stack);\n            AllowedTagList allowedTagList = PatternItem.getAllowedTags(stack);\n\n            ICraftingPattern pattern = PatternItem.fromCache(context.getSource().getLevel(), stack);\n\n            context.getSource().sendSuccess(() -> Component.literal(\"Crafting task factory ID: \").setStyle(Styles.YELLOW).append(Component.literal(pattern.getCraftingTaskFactoryId().toString()).setStyle(Styles.WHITE)), false);\n\n            if (!pattern.isValid()) {\n                context.getSource().sendFailure(Component.literal(\"Pattern is invalid! Reason: \").append(pattern.getErrorMessage()));\n            } else {\n                context.getSource().sendSuccess(() -> Component.literal(\"Processing: \").setStyle(Styles.YELLOW).append(Component.literal(String.valueOf(processing)).setStyle(Styles.WHITE)), false);\n                context.getSource().sendSuccess(() -> Component.literal(\"Exact: \").setStyle(Styles.YELLOW).append(Component.literal(String.valueOf(exact)).setStyle(Styles.WHITE)), false);\n                context.getSource().sendSuccess(() -> Component.literal(\"Has allowed tag list: \").setStyle(Styles.YELLOW).append(Component.literal(String.valueOf(allowedTagList != null)).setStyle(Styles.WHITE)), false);\n\n                if (pattern.isProcessing()) {\n                    for (int i = 0; i < pattern.getInputs().size(); ++i) {\n                        final int ii = i;\n                        if (!pattern.getInputs().get(i).isEmpty()) {\n                            context.getSource().sendSuccess(() -> Component.literal(\"Item inputs in slot \" + ii + \":\").setStyle(Styles.YELLOW), false);\n\n                            for (int j = 0; j < pattern.getInputs().get(i).size(); ++j) {\n                                final int jj = j;\n                                context.getSource().sendSuccess(() -> Component.literal(\"- Possibility #\" + jj + \": \" + pattern.getInputs().get(ii).get(jj).getCount() + \"x \").append(pattern.getInputs().get(ii).get(jj).getHoverName()), false);\n                            }\n                        }\n\n                        if (allowedTagList != null) {\n                            for (ResourceLocation allowed : allowedTagList.getAllowedItemTags().get(i)) {\n                                context.getSource().sendSuccess(() -> Component.literal(\"- Allowed item tag: \" + allowed.toString()), false);\n                            }\n                        }\n                    }\n\n                    for (int i = 0; i < pattern.getFluidInputs().size(); ++i) {\n                        final int ii = i;\n                        if (!pattern.getFluidInputs().get(i).isEmpty()) {\n                            context.getSource().sendSuccess(() -> Component.literal(\"Fluid inputs in slot \" + ii + \":\").setStyle(Styles.YELLOW), false);\n\n                            for (int j = 0; j < pattern.getFluidInputs().get(i).size(); ++j) {\n                                final int jj = j;\n                                context.getSource().sendSuccess(() -> Component.literal(\"- Possibility #\" + jj + \": \" + pattern.getFluidInputs().get(ii).get(jj).getAmount() + \" mB \").append(pattern.getFluidInputs().get(ii).get(jj).getDisplayName()), false);\n                            }\n                        }\n\n                        if (allowedTagList != null) {\n                            for (ResourceLocation allowed : allowedTagList.getAllowedFluidTags().get(i)) {\n                                context.getSource().sendSuccess(() -> Component.literal(\"- Allowed fluid tag: \" + allowed.toString()), false);\n                            }\n                        }\n                    }\n\n                    context.getSource().sendSuccess(() -> Component.literal(\"Outputs\").setStyle(Styles.YELLOW), false);\n                    for (ItemStack output : pattern.getOutputs()) {\n                        context.getSource().sendSuccess(() -> Component.literal(\"- \" + output.getCount() + \"x \").append(output.getHoverName()), false);\n                    }\n\n                    context.getSource().sendSuccess(() -> Component.literal(\"Fluid outputs\").setStyle(Styles.YELLOW), false);\n                    for (FluidStack output : pattern.getFluidOutputs()) {\n                        context.getSource().sendSuccess(() -> Component.literal(\"- \" + output.getAmount() + \" mB \").append(output.getDisplayName()), false);\n                    }\n                } else {\n                    for (int i = 0; i < pattern.getInputs().size(); ++i) {\n                        final int ii = i;\n                        if (!pattern.getInputs().get(i).isEmpty()) {\n                            context.getSource().sendSuccess(() -> Component.literal(\"Inputs in slot \" + ii + \":\").setStyle(Styles.YELLOW), false);\n\n                            for (int j = 0; j < pattern.getInputs().get(i).size(); ++j) {\n                                final int jj = j;\n                                context.getSource().sendSuccess(() -> Component.literal(\"- Possibility #\" + jj + \": \" + pattern.getInputs().get(ii).get(jj).getCount() + \"x \").append(pattern.getInputs().get(ii).get(jj).getHoverName()), false);\n                            }\n                        }\n                    }\n\n                    context.getSource().sendSuccess(() -> Component.literal(\"Outputs\").setStyle(Styles.YELLOW), false);\n                    for (ItemStack output : pattern.getOutputs()) {\n                        context.getSource().sendSuccess(() -> Component.literal(\"- \" + output.getCount() + \"x \").append(output.getHoverName()), false);\n                    }\n\n                    boolean anyByproducts = false;\n\n                    for (ItemStack byproduct : pattern.getByproducts()) {\n                        if (!byproduct.isEmpty()) {\n                            if (!anyByproducts) {\n                                context.getSource().sendSuccess(() -> Component.literal(\"Byproducts\").setStyle(Styles.YELLOW), false);\n\n                                anyByproducts = true;\n                            }\n\n                            context.getSource().sendSuccess(() -> Component.literal(\"- \" + byproduct.getCount() + \"x \").append(byproduct.getHoverName()), false);\n                        }\n                    }\n                }\n            }\n        } else {\n            context.getSource().sendFailure(Component.literal(\"You need to be holding a pattern in your hand.\"));\n        }\n\n        return 0;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/config/ClientConfig.java",
    "content": "package com.refinedmods.refinedstorage.config;\n\nimport net.neoforged.neoforge.common.ModConfigSpec;\n\npublic class ClientConfig {\n    private final ModConfigSpec.Builder builder = new ModConfigSpec.Builder();\n    private final ModConfigSpec spec;\n\n    private final Grid grid;\n    private final CrafterManager crafterManager;\n    private final Cover cover;\n\n    public ClientConfig() {\n        grid = new Grid();\n        crafterManager = new CrafterManager();\n        cover = new Cover();\n        spec = builder.build();\n    }\n\n    public ModConfigSpec getSpec() {\n        return spec;\n    }\n\n    public Grid getGrid() {\n        return grid;\n    }\n\n    public CrafterManager getCrafterManager() {\n        return crafterManager;\n    }\n\n    public Cover getCover() {\n        return cover;\n    }\n\n    public class Grid {\n        private final ModConfigSpec.IntValue maxRowsStretch;\n        private final ModConfigSpec.BooleanValue detailedTooltip;\n        private final ModConfigSpec.BooleanValue largeFont;\n        private final ModConfigSpec.BooleanValue preventSortingWhileShiftIsDown;\n        private final ModConfigSpec.BooleanValue rememberSearchQuery;\n\n        public Grid() {\n            builder.push(\"grid\");\n\n            maxRowsStretch = builder.comment(\"The maximum amount of rows that the Grid can show when stretched\")\n                .defineInRange(\"maxRowsStretch\", Integer.MAX_VALUE, 3, Integer.MAX_VALUE);\n            detailedTooltip = builder.comment(\n                    \"Whether the Grid should display a detailed tooltip when hovering over an item or fluid\")\n                .define(\"detailedTooltip\", true);\n            largeFont = builder.comment(\"Whether the Grid should use a large font for stack quantity display\")\n                .define(\"largeFont\", false);\n            preventSortingWhileShiftIsDown =\n                builder.comment(\"Whether the Grid should prevent sorting while the shift key is held down\")\n                    .define(\"preventSortingWhileShiftIsDown\", true);\n            rememberSearchQuery = builder.comment(\n                    \"Whether the Grid should remember the search query when closing and re-opening the Grid\")\n                .define(\"rememberSearchQuery\", false);\n\n            builder.pop();\n        }\n\n        public int getMaxRowsStretch() {\n            return maxRowsStretch.get();\n        }\n\n        public boolean getDetailedTooltip() {\n            return detailedTooltip.get();\n        }\n\n        public boolean getLargeFont() {\n            return largeFont.get();\n        }\n\n        public boolean getPreventSortingWhileShiftIsDown() {\n            return preventSortingWhileShiftIsDown.get();\n        }\n\n        public boolean getRememberSearchQuery() {\n            return rememberSearchQuery.get();\n        }\n    }\n\n    public class CrafterManager {\n        private final ModConfigSpec.IntValue maxRowsStretch;\n\n        public CrafterManager() {\n            builder.push(\"crafterManager\");\n\n            maxRowsStretch =\n                builder.comment(\"The maximum amount of rows that the Crafter Manager can show when stretched\")\n                    .defineInRange(\"maxRowsStretch\", Integer.MAX_VALUE, 3, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getMaxRowsStretch() {\n            return maxRowsStretch.get();\n        }\n    }\n\n    public class Cover {\n\n        private final ModConfigSpec.BooleanValue showAllCoversInJEI;\n\n        public Cover() {\n            builder.push(\"cover\");\n            showAllCoversInJEI =\n                builder.comment(\"When true all the possible covers will be added to JEI (Game restart required)\")\n                    .define(\"showAllCoversInJEI\", false);\n            builder.pop();\n        }\n\n        public boolean showAllRecipesInJEI() {\n            return showAllCoversInJEI.get();\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/config/ServerConfig.java",
    "content": "package com.refinedmods.refinedstorage.config;\n\nimport net.neoforged.neoforge.common.ModConfigSpec;\n\npublic class ServerConfig {\n    private final ModConfigSpec.Builder builder = new ModConfigSpec.Builder();\n    private final ModConfigSpec spec;\n\n    private final Upgrades upgrades;\n    private final Controller controller;\n    private final Cable cable;\n    private final Grid grid;\n    private final DiskDrive diskDrive;\n    private final StorageBlock storageBlock;\n    private final FluidStorageBlock fluidStorageBlock;\n    private final ExternalStorage externalStorage;\n    private final Importer importer;\n    private final Exporter exporter;\n    private final NetworkReceiver networkReceiver;\n    private final NetworkTransmitter networkTransmitter;\n    private final Relay relay;\n    private final Detector detector;\n    private final SecurityManager securityManager;\n    private final Interface iface;\n    private final FluidInterface fluidInterface;\n    private final WirelessTransmitter wirelessTransmitter;\n    private final StorageMonitor storageMonitor;\n    private final WirelessGrid wirelessGrid;\n    private final WirelessFluidGrid wirelessFluidGrid;\n    private final Constructor constructor;\n    private final Destructor destructor;\n    private final DiskManipulator diskManipulator;\n    private final PortableGrid portableGrid;\n    private final Crafter crafter;\n    private final CrafterManager crafterManager;\n    private final CraftingMonitor craftingMonitor;\n    private final WirelessCraftingMonitor wirelessCraftingMonitor;\n    private final Autocrafting autocrafting;\n\n    public ServerConfig() {\n        upgrades = new Upgrades();\n        controller = new Controller();\n        cable = new Cable();\n        grid = new Grid();\n        diskDrive = new DiskDrive();\n        storageBlock = new StorageBlock();\n        fluidStorageBlock = new FluidStorageBlock();\n        externalStorage = new ExternalStorage();\n        importer = new Importer();\n        exporter = new Exporter();\n        networkReceiver = new NetworkReceiver();\n        networkTransmitter = new NetworkTransmitter();\n        relay = new Relay();\n        detector = new Detector();\n        securityManager = new SecurityManager();\n        iface = new Interface();\n        fluidInterface = new FluidInterface();\n        wirelessTransmitter = new WirelessTransmitter();\n        storageMonitor = new StorageMonitor();\n        wirelessGrid = new WirelessGrid();\n        wirelessFluidGrid = new WirelessFluidGrid();\n        constructor = new Constructor();\n        destructor = new Destructor();\n        diskManipulator = new DiskManipulator();\n        portableGrid = new PortableGrid();\n        crafter = new Crafter();\n        crafterManager = new CrafterManager();\n        craftingMonitor = new CraftingMonitor();\n        wirelessCraftingMonitor = new WirelessCraftingMonitor();\n        autocrafting = new Autocrafting();\n\n        spec = builder.build();\n    }\n\n    public ModConfigSpec getSpec() {\n        return spec;\n    }\n\n    public Upgrades getUpgrades() {\n        return upgrades;\n    }\n\n    public Controller getController() {\n        return controller;\n    }\n\n    public Cable getCable() {\n        return cable;\n    }\n\n    public DiskDrive getDiskDrive() {\n        return diskDrive;\n    }\n\n    public Grid getGrid() {\n        return grid;\n    }\n\n    public StorageBlock getStorageBlock() {\n        return storageBlock;\n    }\n\n    public FluidStorageBlock getFluidStorageBlock() {\n        return fluidStorageBlock;\n    }\n\n    public ExternalStorage getExternalStorage() {\n        return externalStorage;\n    }\n\n    public Importer getImporter() {\n        return importer;\n    }\n\n    public Exporter getExporter() {\n        return exporter;\n    }\n\n    public NetworkReceiver getNetworkReceiver() {\n        return networkReceiver;\n    }\n\n    public NetworkTransmitter getNetworkTransmitter() {\n        return networkTransmitter;\n    }\n\n    public Relay getRelay() {\n        return relay;\n    }\n\n    public Detector getDetector() {\n        return detector;\n    }\n\n    public SecurityManager getSecurityManager() {\n        return securityManager;\n    }\n\n    public Interface getInterface() {\n        return iface;\n    }\n\n    public FluidInterface getFluidInterface() {\n        return fluidInterface;\n    }\n\n    public WirelessTransmitter getWirelessTransmitter() {\n        return wirelessTransmitter;\n    }\n\n    public StorageMonitor getStorageMonitor() {\n        return storageMonitor;\n    }\n\n    public WirelessGrid getWirelessGrid() {\n        return wirelessGrid;\n    }\n\n    public WirelessFluidGrid getWirelessFluidGrid() {\n        return wirelessFluidGrid;\n    }\n\n    public Constructor getConstructor() {\n        return constructor;\n    }\n\n    public Destructor getDestructor() {\n        return destructor;\n    }\n\n    public DiskManipulator getDiskManipulator() {\n        return diskManipulator;\n    }\n\n    public PortableGrid getPortableGrid() {\n        return portableGrid;\n    }\n\n    public Crafter getCrafter() {\n        return crafter;\n    }\n\n    public CrafterManager getCrafterManager() {\n        return crafterManager;\n    }\n\n    public CraftingMonitor getCraftingMonitor() {\n        return craftingMonitor;\n    }\n\n    public WirelessCraftingMonitor getWirelessCraftingMonitor() {\n        return wirelessCraftingMonitor;\n    }\n\n    public Autocrafting getAutocrafting() {\n        return autocrafting;\n    }\n\n    public class Controller {\n        private final ModConfigSpec.BooleanValue useEnergy;\n        private final ModConfigSpec.IntValue capacity;\n        private final ModConfigSpec.IntValue baseUsage;\n        private final ModConfigSpec.IntValue maxTransfer;\n\n        public Controller() {\n            builder.push(\"controller\");\n\n            useEnergy = builder.comment(\"Whether the Controller uses energy\").define(\"useEnergy\", true);\n            capacity = builder.comment(\"The energy capacity of the Controller\")\n                .defineInRange(\"capacity\", 32000, 0, Integer.MAX_VALUE);\n            baseUsage = builder.comment(\"The base energy used by the Controller\")\n                .defineInRange(\"baseUsage\", 0, 0, Integer.MAX_VALUE);\n            maxTransfer = builder.comment(\"The maximum energy that the Controller can receive\")\n                .defineInRange(\"maxTransfer\", Integer.MAX_VALUE, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public boolean getUseEnergy() {\n            return useEnergy.get();\n        }\n\n        public int getCapacity() {\n            return capacity.get();\n        }\n\n        public int getBaseUsage() {\n            return baseUsage.get();\n        }\n\n        public int getMaxTransfer() {\n            return maxTransfer.get();\n        }\n    }\n\n    public class Cable {\n        private final ModConfigSpec.IntValue usage;\n\n        public Cable() {\n            builder.push(\"cable\");\n\n            usage = builder.comment(\"The energy used by the Cable\").defineInRange(\"usage\", 0, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getUsage() {\n            return usage.get();\n        }\n    }\n\n    public class DiskDrive {\n        private final ModConfigSpec.IntValue usage;\n        private final ModConfigSpec.IntValue diskUsage;\n\n        public DiskDrive() {\n            builder.push(\"diskDrive\");\n\n            usage =\n                builder.comment(\"The energy used by the Disk Drive\").defineInRange(\"usage\", 0, 0, Integer.MAX_VALUE);\n            diskUsage = builder.comment(\"The energy used per disk in the Disk Drive\")\n                .defineInRange(\"diskUsage\", 1, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getUsage() {\n            return usage.get();\n        }\n\n        public int getDiskUsage() {\n            return diskUsage.get();\n        }\n    }\n\n    public class Grid {\n        private final ModConfigSpec.IntValue gridUsage;\n        private final ModConfigSpec.IntValue craftingGridUsage;\n        private final ModConfigSpec.IntValue patternGridUsage;\n        private final ModConfigSpec.IntValue fluidGridUsage;\n\n        public Grid() {\n            builder.push(\"grid\");\n\n            gridUsage = builder.comment(\"The energy used by Grids\").defineInRange(\"gridUsage\", 2, 0, Integer.MAX_VALUE);\n            craftingGridUsage = builder.comment(\"The energy used by Crafting Grids\")\n                .defineInRange(\"craftingGridUsage\", 4, 0, Integer.MAX_VALUE);\n            patternGridUsage = builder.comment(\"The energy used by Pattern Grids\")\n                .defineInRange(\"patternGridUsage\", 4, 0, Integer.MAX_VALUE);\n            fluidGridUsage = builder.comment(\"The energy used by Fluid Grids\")\n                .defineInRange(\"fluidGridUsage\", 2, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getGridUsage() {\n            return gridUsage.get();\n        }\n\n        public int getCraftingGridUsage() {\n            return craftingGridUsage.get();\n        }\n\n        public int getPatternGridUsage() {\n            return patternGridUsage.get();\n        }\n\n        public int getFluidGridUsage() {\n            return fluidGridUsage.get();\n        }\n    }\n\n    public class Upgrades {\n        private final ModConfigSpec.IntValue rangeUpgradeUsage;\n        private final ModConfigSpec.IntValue speedUpgradeUsage;\n        private final ModConfigSpec.IntValue craftingUpgradeUsage;\n        private final ModConfigSpec.IntValue stackUpgradeUsage;\n        private final ModConfigSpec.IntValue silkTouchUpgradeUsage;\n        private final ModConfigSpec.IntValue fortune1UpgradeUsage;\n        private final ModConfigSpec.IntValue fortune2UpgradeUsage;\n        private final ModConfigSpec.IntValue fortune3UpgradeUsage;\n        private final ModConfigSpec.IntValue regulatorUpgradeUsage;\n\n        public Upgrades() {\n            builder.push(\"upgrades\");\n\n            rangeUpgradeUsage = builder.comment(\"The additional energy used by the Range Upgrade\")\n                .defineInRange(\"rangeUpgradeUsage\", 8, 0, Integer.MAX_VALUE);\n            speedUpgradeUsage = builder.comment(\"The additional energy used by the Speed Upgrade\")\n                .defineInRange(\"speedUpgradeUsage\", 2, 0, Integer.MAX_VALUE);\n            craftingUpgradeUsage = builder.comment(\"The additional energy used by the Crafting Upgrade\")\n                .defineInRange(\"craftingUpgradeUsage\", 5, 0, Integer.MAX_VALUE);\n            stackUpgradeUsage = builder.comment(\"The additional energy used by the Stack Upgrade\")\n                .defineInRange(\"stackUpgradeUsage\", 12, 0, Integer.MAX_VALUE);\n            silkTouchUpgradeUsage = builder.comment(\"The additional energy used by the Silk Touch Upgrade\")\n                .defineInRange(\"silkTouchUpgradeUsage\", 15, 0, Integer.MAX_VALUE);\n            fortune1UpgradeUsage = builder.comment(\"The additional energy used by the Fortune 1 Upgrade\")\n                .defineInRange(\"fortune1UpgradeUsage\", 10, 0, Integer.MAX_VALUE);\n            fortune2UpgradeUsage = builder.comment(\"The additional energy used by the Fortune 2 Upgrade\")\n                .defineInRange(\"fortune2UpgradeUsage\", 12, 0, Integer.MAX_VALUE);\n            fortune3UpgradeUsage = builder.comment(\"The additional energy used by the Fortune 3 Upgrade\")\n                .defineInRange(\"fortune3UpgradeUsage\", 14, 0, Integer.MAX_VALUE);\n            regulatorUpgradeUsage = builder.comment(\"The additional energy used by the Regulator Upgrade\")\n                .defineInRange(\"regulatorUpgradeUsage\", 15, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getRangeUpgradeUsage() {\n            return rangeUpgradeUsage.get();\n        }\n\n        public int getSpeedUpgradeUsage() {\n            return speedUpgradeUsage.get();\n        }\n\n        public int getCraftingUpgradeUsage() {\n            return craftingUpgradeUsage.get();\n        }\n\n        public int getStackUpgradeUsage() {\n            return stackUpgradeUsage.get();\n        }\n\n        public int getSilkTouchUpgradeUsage() {\n            return silkTouchUpgradeUsage.get();\n        }\n\n        public int getFortune1UpgradeUsage() {\n            return fortune1UpgradeUsage.get();\n        }\n\n        public int getFortune2UpgradeUsage() {\n            return fortune2UpgradeUsage.get();\n        }\n\n        public int getFortune3UpgradeUsage() {\n            return fortune3UpgradeUsage.get();\n        }\n\n        public int getRegulatorUpgradeUsage() {\n            return regulatorUpgradeUsage.get();\n        }\n    }\n\n    public class StorageBlock {\n        private final ModConfigSpec.IntValue oneKUsage;\n        private final ModConfigSpec.IntValue fourKUsage;\n        private final ModConfigSpec.IntValue sixteenKUsage;\n        private final ModConfigSpec.IntValue sixtyFourKUsage;\n        private final ModConfigSpec.IntValue creativeUsage;\n\n        public StorageBlock() {\n            builder.push(\"storageBlock\");\n\n            oneKUsage = builder.comment(\"The energy used by the 1k Storage Block\")\n                .defineInRange(\"oneKUsage\", 2, 0, Integer.MAX_VALUE);\n            fourKUsage = builder.comment(\"The energy used by the 4k Storage Block\")\n                .defineInRange(\"fourKUsage\", 4, 0, Integer.MAX_VALUE);\n            sixteenKUsage = builder.comment(\"The energy used by the 16k Storage Block\")\n                .defineInRange(\"sixteenKUsage\", 6, 0, Integer.MAX_VALUE);\n            sixtyFourKUsage = builder.comment(\"The energy used by the 64k Storage Block\")\n                .defineInRange(\"sixtyFourKUsage\", 8, 0, Integer.MAX_VALUE);\n            creativeUsage = builder.comment(\"The energy used by the Creative Storage Block\")\n                .defineInRange(\"creativeUsage\", 10, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getOneKUsage() {\n            return oneKUsage.get();\n        }\n\n        public int getFourKUsage() {\n            return fourKUsage.get();\n        }\n\n        public int getSixteenKUsage() {\n            return sixteenKUsage.get();\n        }\n\n        public int getSixtyFourKUsage() {\n            return sixtyFourKUsage.get();\n        }\n\n        public int getCreativeUsage() {\n            return creativeUsage.get();\n        }\n    }\n\n    public class FluidStorageBlock {\n        private final ModConfigSpec.IntValue sixtyFourKUsage;\n        private final ModConfigSpec.IntValue twoHundredFiftySixKUsage;\n        private final ModConfigSpec.IntValue thousandTwentyFourKUsage;\n        private final ModConfigSpec.IntValue fourThousandNinetySixKUsage;\n        private final ModConfigSpec.IntValue creativeUsage;\n\n        public FluidStorageBlock() {\n            builder.push(\"fluidStorageBlock\");\n\n            sixtyFourKUsage = builder.comment(\"The energy used by the 64k Fluid Storage Block\")\n                .defineInRange(\"sixtyFourKUsage\", 2, 0, Integer.MAX_VALUE);\n            twoHundredFiftySixKUsage = builder.comment(\"The energy used by the 256k Fluid Storage Block\")\n                .defineInRange(\"twoHundredFiftySixKUsage\", 4, 0, Integer.MAX_VALUE);\n            thousandTwentyFourKUsage = builder.comment(\"The energy used by the 1024k Fluid Storage Block\")\n                .defineInRange(\"thousandTwentyFourKUsage\", 6, 0, Integer.MAX_VALUE);\n            fourThousandNinetySixKUsage = builder.comment(\"The energy used by the 4096k Fluid Storage Block\")\n                .defineInRange(\"fourThousandNinetySixKUsage\", 8, 0, Integer.MAX_VALUE);\n            creativeUsage = builder.comment(\"The energy used by the Creative Fluid Storage Block\")\n                .defineInRange(\"creativeUsage\", 10, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getSixtyFourKUsage() {\n            return sixtyFourKUsage.get();\n        }\n\n        public int getTwoHundredFiftySixKUsage() {\n            return twoHundredFiftySixKUsage.get();\n        }\n\n        public int getThousandTwentyFourKUsage() {\n            return thousandTwentyFourKUsage.get();\n        }\n\n        public int getFourThousandNinetySixKUsage() {\n            return fourThousandNinetySixKUsage.get();\n        }\n\n        public int getCreativeUsage() {\n            return creativeUsage.get();\n        }\n    }\n\n    public class ExternalStorage {\n        private final ModConfigSpec.IntValue usage;\n\n        public ExternalStorage() {\n            builder.push(\"externalStorage\");\n\n            usage = builder.comment(\"The energy used by the External Storage\")\n                .defineInRange(\"usage\", 6, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getUsage() {\n            return usage.get();\n        }\n    }\n\n    public class Importer {\n        private final ModConfigSpec.IntValue usage;\n\n        public Importer() {\n            builder.push(\"importer\");\n\n            usage = builder.comment(\"The energy used by the Importer\").defineInRange(\"usage\", 1, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getUsage() {\n            return usage.get();\n        }\n    }\n\n    public class Exporter {\n        private final ModConfigSpec.IntValue usage;\n\n        public Exporter() {\n            builder.push(\"exporter\");\n\n            usage = builder.comment(\"The energy used by the Exporter\").defineInRange(\"usage\", 1, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getUsage() {\n            return usage.get();\n        }\n    }\n\n    public class NetworkReceiver {\n        private final ModConfigSpec.IntValue usage;\n\n        public NetworkReceiver() {\n            builder.push(\"networkReceiver\");\n\n            usage = builder.comment(\"The energy used by the Network Receiver\")\n                .defineInRange(\"usage\", 0, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getUsage() {\n            return usage.get();\n        }\n    }\n\n    public class NetworkTransmitter {\n        private final ModConfigSpec.IntValue usage;\n\n        public NetworkTransmitter() {\n            builder.push(\"networkTransmitter\");\n\n            usage = builder.comment(\"The energy used by the Network Transmitter\")\n                .defineInRange(\"usage\", 64, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getUsage() {\n            return usage.get();\n        }\n    }\n\n    public class Relay {\n        private final ModConfigSpec.IntValue usage;\n\n        public Relay() {\n            builder.push(\"relay\");\n\n            usage = builder.comment(\"The energy used by the Relay\").defineInRange(\"usage\", 1, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getUsage() {\n            return usage.get();\n        }\n    }\n\n    public class Detector {\n        private final ModConfigSpec.IntValue usage;\n\n        public Detector() {\n            builder.push(\"detector\");\n\n            usage = builder.comment(\"The energy used by the Detector\").defineInRange(\"usage\", 2, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getUsage() {\n            return usage.get();\n        }\n    }\n\n    public class SecurityManager {\n        private final ModConfigSpec.IntValue usage;\n        private final ModConfigSpec.IntValue usagePerCard;\n\n        public SecurityManager() {\n            builder.push(\"securityManager\");\n\n            usage = builder.comment(\"The energy used by the Security Manager\")\n                .defineInRange(\"usage\", 4, 0, Integer.MAX_VALUE);\n            usagePerCard = builder.comment(\"The additional energy used by Security Cards in the Security Manager\")\n                .defineInRange(\"usagePerCard\", 10, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getUsage() {\n            return usage.get();\n        }\n\n        public int getUsagePerCard() {\n            return usagePerCard.get();\n        }\n    }\n\n    public class Interface {\n        private final ModConfigSpec.IntValue usage;\n\n        public Interface() {\n            builder.push(\"interface\");\n\n            usage = builder.comment(\"The energy used by the Interface\").defineInRange(\"usage\", 2, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getUsage() {\n            return usage.get();\n        }\n    }\n\n    public class FluidInterface {\n        private final ModConfigSpec.IntValue usage;\n\n        public FluidInterface() {\n            builder.push(\"fluidInterface\");\n\n            usage = builder.comment(\"The energy used by the Fluid Interface\")\n                .defineInRange(\"usage\", 2, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getUsage() {\n            return usage.get();\n        }\n    }\n\n    public class WirelessTransmitter {\n        private final ModConfigSpec.IntValue usage;\n        private final ModConfigSpec.IntValue baseRange;\n        private final ModConfigSpec.IntValue rangePerUpgrade;\n\n        public WirelessTransmitter() {\n            builder.push(\"wirelessTransmitter\");\n\n            usage = builder.comment(\"The energy used by the Wireless Transmitter\")\n                .defineInRange(\"usage\", 8, 0, Integer.MAX_VALUE);\n            baseRange = builder.comment(\"The base range of the Wireless Transmitter\")\n                .defineInRange(\"baseRange\", 16, 0, Integer.MAX_VALUE);\n            rangePerUpgrade = builder.comment(\"The additional range per Range Upgrade in the Wireless Transmitter\")\n                .defineInRange(\"rangePerUpgrade\", 8, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getUsage() {\n            return usage.get();\n        }\n\n        public int getBaseRange() {\n            return baseRange.get();\n        }\n\n        public int getRangePerUpgrade() {\n            return rangePerUpgrade.get();\n        }\n    }\n\n    public class StorageMonitor {\n        private final ModConfigSpec.IntValue usage;\n\n        public StorageMonitor() {\n            builder.push(\"storageMonitor\");\n\n            usage = builder.comment(\"The energy used by the Storage Monitor\")\n                .defineInRange(\"usage\", 3, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getUsage() {\n            return usage.get();\n        }\n    }\n\n    public class WirelessGrid {\n        private final ModConfigSpec.BooleanValue useEnergy;\n        private final ModConfigSpec.IntValue capacity;\n        private final ModConfigSpec.IntValue openUsage;\n        private final ModConfigSpec.IntValue extractUsage;\n        private final ModConfigSpec.IntValue insertUsage;\n\n        public WirelessGrid() {\n            builder.push(\"wirelessGrid\");\n\n            useEnergy = builder.comment(\"Whether the Wireless Grid uses energy\").define(\"useEnergy\", true);\n            capacity = builder.comment(\"The energy capacity of the Wireless Grid\")\n                .defineInRange(\"capacity\", 3200, 0, Integer.MAX_VALUE);\n            openUsage = builder.comment(\"The energy used by the Wireless Grid to open\")\n                .defineInRange(\"openUsage\", 30, 0, Integer.MAX_VALUE);\n            extractUsage = builder.comment(\"The energy used by the Wireless Grid to extract items\")\n                .defineInRange(\"extractUsage\", 5, 0, Integer.MAX_VALUE);\n            insertUsage = builder.comment(\"The energy used by the Wireless Grid to insert items\")\n                .defineInRange(\"insertUsage\", 5, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public boolean getUseEnergy() {\n            return useEnergy.get();\n        }\n\n        public int getCapacity() {\n            return capacity.get();\n        }\n\n        public int getOpenUsage() {\n            return openUsage.get();\n        }\n\n        public int getExtractUsage() {\n            return extractUsage.get();\n        }\n\n        public int getInsertUsage() {\n            return insertUsage.get();\n        }\n    }\n\n    public class WirelessFluidGrid {\n        private final ModConfigSpec.BooleanValue useEnergy;\n        private final ModConfigSpec.IntValue capacity;\n        private final ModConfigSpec.IntValue openUsage;\n        private final ModConfigSpec.IntValue extractUsage;\n        private final ModConfigSpec.IntValue insertUsage;\n\n        public WirelessFluidGrid() {\n            builder.push(\"wirelessFluidGrid\");\n\n            useEnergy = builder.comment(\"Whether the Wireless Fluid Grid uses energy\").define(\"useEnergy\", true);\n            capacity = builder.comment(\"The energy capacity of the Wireless Fluid Grid\")\n                .defineInRange(\"capacity\", 3200, 0, Integer.MAX_VALUE);\n            openUsage = builder.comment(\"The energy used by the Wireless Fluid Grid to open\")\n                .defineInRange(\"openUsage\", 30, 0, Integer.MAX_VALUE);\n            extractUsage = builder.comment(\"The energy used by the Wireless Fluid Grid to extract fluids\")\n                .defineInRange(\"extractUsage\", 5, 0, Integer.MAX_VALUE);\n            insertUsage = builder.comment(\"The energy used by the Wireless Fluid Grid to insert fluids\")\n                .defineInRange(\"insertUsage\", 5, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public boolean getUseEnergy() {\n            return useEnergy.get();\n        }\n\n        public int getCapacity() {\n            return capacity.get();\n        }\n\n        public int getOpenUsage() {\n            return openUsage.get();\n        }\n\n        public int getExtractUsage() {\n            return extractUsage.get();\n        }\n\n        public int getInsertUsage() {\n            return insertUsage.get();\n        }\n    }\n\n    public class PortableGrid {\n        private final ModConfigSpec.BooleanValue useEnergy;\n        private final ModConfigSpec.IntValue capacity;\n        private final ModConfigSpec.IntValue openUsage;\n        private final ModConfigSpec.IntValue extractUsage;\n        private final ModConfigSpec.IntValue insertUsage;\n\n        public PortableGrid() {\n            builder.push(\"portableGrid\");\n\n            useEnergy = builder.comment(\"Whether the Portable Grid uses energy\").define(\"useEnergy\", true);\n            capacity = builder.comment(\"The energy capacity of the Portable Grid\")\n                .defineInRange(\"capacity\", 3200, 0, Integer.MAX_VALUE);\n            openUsage = builder.comment(\"The energy used by the Portable Grid to open\")\n                .defineInRange(\"openUsage\", 30, 0, Integer.MAX_VALUE);\n            extractUsage = builder.comment(\"The energy used by the Portable Grid to extract items or fluids\")\n                .defineInRange(\"extractUsage\", 5, 0, Integer.MAX_VALUE);\n            insertUsage = builder.comment(\"The energy used by the Portable Grid to insert items or fluids\")\n                .defineInRange(\"insertUsage\", 5, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public boolean getUseEnergy() {\n            return useEnergy.get();\n        }\n\n        public int getCapacity() {\n            return capacity.get();\n        }\n\n        public int getOpenUsage() {\n            return openUsage.get();\n        }\n\n        public int getExtractUsage() {\n            return extractUsage.get();\n        }\n\n        public int getInsertUsage() {\n            return insertUsage.get();\n        }\n    }\n\n    public class Constructor {\n        private final ModConfigSpec.IntValue usage;\n\n        public Constructor() {\n            builder.push(\"constructor\");\n\n            usage =\n                builder.comment(\"The energy used by the Constructor\").defineInRange(\"usage\", 3, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getUsage() {\n            return usage.get();\n        }\n    }\n\n    public class Destructor {\n        private final ModConfigSpec.IntValue usage;\n\n        public Destructor() {\n            builder.push(\"destructor\");\n\n            usage =\n                builder.comment(\"The energy used by the Destructor\").defineInRange(\"usage\", 3, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getUsage() {\n            return usage.get();\n        }\n    }\n\n    public class DiskManipulator {\n        private final ModConfigSpec.IntValue usage;\n\n        public DiskManipulator() {\n            builder.push(\"diskManipulator\");\n\n            usage = builder.comment(\"The energy used by the Disk Manipulator\")\n                .defineInRange(\"usage\", 4, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getUsage() {\n            return usage.get();\n        }\n    }\n\n    public class Crafter {\n        private final ModConfigSpec.IntValue usage;\n        private final ModConfigSpec.IntValue patternUsage;\n\n        public Crafter() {\n            builder.push(\"crafter\");\n\n            usage = builder.comment(\"The energy used by the Crafter\").defineInRange(\"usage\", 4, 0, Integer.MAX_VALUE);\n            patternUsage = builder.comment(\"The energy used for every Pattern in the Crafter\")\n                .defineInRange(\"patternUsage\", 1, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getUsage() {\n            return usage.get();\n        }\n\n        public int getPatternUsage() {\n            return patternUsage.get();\n        }\n    }\n\n    public class CrafterManager {\n        private final ModConfigSpec.IntValue usage;\n\n        public CrafterManager() {\n            builder.push(\"crafterManager\");\n\n            usage = builder.comment(\"The energy used by the Crafter Manager\")\n                .defineInRange(\"usage\", 8, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getUsage() {\n            return usage.get();\n        }\n    }\n\n    public class CraftingMonitor {\n        private final ModConfigSpec.IntValue usage;\n\n        public CraftingMonitor() {\n            builder.push(\"craftingMonitor\");\n\n            usage = builder.comment(\"The energy used by the Crafting Monitor\")\n                .defineInRange(\"usage\", 8, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getUsage() {\n            return usage.get();\n        }\n    }\n\n    public class WirelessCraftingMonitor {\n        private final ModConfigSpec.BooleanValue useEnergy;\n        private final ModConfigSpec.IntValue capacity;\n        private final ModConfigSpec.IntValue openUsage;\n        private final ModConfigSpec.IntValue cancelUsage;\n        private final ModConfigSpec.IntValue cancelAllUsage;\n\n        public WirelessCraftingMonitor() {\n            builder.push(\"wirelessCraftingMonitor\");\n\n            useEnergy = builder.comment(\"Whether the Wireless Crafting Monitor uses energy\").define(\"useEnergy\", true);\n            capacity = builder.comment(\"The energy capacity of the Wireless Crafting Monitor\")\n                .defineInRange(\"capacity\", 3200, 0, Integer.MAX_VALUE);\n            openUsage = builder.comment(\"The energy used by the Wireless Crafting Monitor to open\")\n                .defineInRange(\"openUsage\", 30, 0, Integer.MAX_VALUE);\n            cancelUsage = builder.comment(\"The energy used by the Wireless Crafting Monitor to cancel a crafting task\")\n                .defineInRange(\"cancelUsage\", 5, 0, Integer.MAX_VALUE);\n            cancelAllUsage =\n                builder.comment(\"The energy used by the Wireless Crafting Monitor to cancel all crafting tasks\")\n                    .defineInRange(\"cancelAllUsage\", 10, 0, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public boolean getUseEnergy() {\n            return useEnergy.get();\n        }\n\n        public int getCapacity() {\n            return capacity.get();\n        }\n\n        public int getOpenUsage() {\n            return openUsage.get();\n        }\n\n        public int getCancelUsage() {\n            return cancelUsage.get();\n        }\n\n        public int getCancelAllUsage() {\n            return cancelAllUsage.get();\n        }\n    }\n\n    public class Autocrafting {\n        private final ModConfigSpec.IntValue calculationTimeoutMs;\n\n        public Autocrafting() {\n            builder.push(\"autocrafting\");\n\n            calculationTimeoutMs = builder.comment(\n                    \"The autocrafting calculation timeout in milliseconds, crafting tasks taking longer than this to calculate are cancelled to avoid server strain\")\n                .defineInRange(\"calculationTimeoutMs\", 5000, 5000, Integer.MAX_VALUE);\n\n            builder.pop();\n        }\n\n        public int getCalculationTimeoutMs() {\n            return calculationTimeoutMs.get();\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/AlternativesContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport net.minecraft.world.entity.player.Player;\n\npublic class AlternativesContainerMenu extends BaseContainerMenu {\n    public AlternativesContainerMenu(Player player) {\n        super(null, null, player, 0);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/AmountContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.container.slot.DisabledSlot;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\nimport net.neoforged.neoforge.items.ItemStackHandler;\n\npublic class AmountContainerMenu extends BaseContainerMenu {\n    public AmountContainerMenu(Player player, ItemStack stack) {\n        super(null, null, player, 0);\n\n        ItemStackHandler inventory = new ItemStackHandler(1);\n\n        inventory.setStackInSlot(0, ItemHandlerHelper.copyStackWithSize(stack, 1));\n\n        addSlot(new DisabledSlot(inventory, 0, 89, 48));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/BaseContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.container.slot.filter.FilterSlot;\nimport com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot;\nimport com.refinedmods.refinedstorage.container.slot.legacy.LegacyDisabledSlot;\nimport com.refinedmods.refinedstorage.container.slot.legacy.LegacyFilterSlot;\nimport com.refinedmods.refinedstorage.container.transfer.TransferManager;\nimport com.refinedmods.refinedstorage.network.FluidFilterSlotUpdateMessage;\nimport com.refinedmods.refinedstorage.blockentity.BaseBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationWatcher;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.minecraft.world.inventory.ClickType;\nimport net.minecraft.world.inventory.MenuType;\nimport net.minecraft.world.inventory.Slot;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic abstract class BaseContainerMenu extends AbstractContainerMenu {\n    protected final TransferManager transferManager = new TransferManager(this);\n    @Nullable\n    private final BaseBlockEntity blockEntity;\n    private final Player player;\n    private final List<FluidFilterSlot> fluidSlots = new ArrayList<>();\n    private final List<FluidStack> fluids = new ArrayList<>();\n    @Nullable\n    private BlockEntitySynchronizationWatcher listener;\n\n    protected BaseContainerMenu(@Nullable MenuType<?> type, @Nullable BaseBlockEntity blockEntity, Player player, int windowId) {\n        super(type, windowId);\n\n        this.blockEntity = blockEntity;\n\n        if (blockEntity != null && player instanceof ServerPlayer) {\n            listener = new BlockEntitySynchronizationWatcher((ServerPlayer) player, blockEntity.getDataManager());\n        }\n\n        this.player = player;\n    }\n\n    public Player getPlayer() {\n        return player;\n    }\n\n    @Nullable\n    public BaseBlockEntity getBlockEntity() {\n        return blockEntity;\n    }\n\n    protected void addPlayerInventory(int xInventory, int yInventory) {\n        int disabledSlotNumber = getDisabledSlotNumber();\n\n        int id = 9;\n\n        for (int y = 0; y < 3; y++) {\n            for (int x = 0; x < 9; x++) {\n                if (id == disabledSlotNumber) {\n                    addSlot(new LegacyDisabledSlot(player.getInventory(), id, xInventory + x * 18, yInventory + y * 18));\n                } else {\n                    addSlot(new Slot(player.getInventory(), id, xInventory + x * 18, yInventory + y * 18));\n                }\n\n                id++;\n            }\n        }\n\n        id = 0;\n\n        for (int i = 0; i < 9; i++) {\n            int x = xInventory + i * 18;\n            int y = yInventory + 4 + (3 * 18);\n\n            if (id == disabledSlotNumber) {\n                addSlot(new LegacyDisabledSlot(player.getInventory(), id, x, y));\n            } else {\n                addSlot(new Slot(player.getInventory(), id, x, y));\n            }\n\n            id++;\n        }\n    }\n\n    public List<FluidFilterSlot> getFluidSlots() {\n        return fluidSlots;\n    }\n\n    @Override\n    public void clicked(int id, int dragType, ClickType clickType, Player player) {\n        Slot slot = id >= 0 ? getSlot(id) : null;\n\n        int disabledSlotNumber = getDisabledSlotNumber();\n\n        // Prevent swapping disabled held item with the number keys (dragType is the slot we're swapping with)\n        if (disabledSlotNumber != -1 &&\n            clickType == ClickType.SWAP &&\n            dragType == disabledSlotNumber) {\n            return;\n        }\n\n        if (slot instanceof FilterSlot) {\n            if (((FilterSlot) slot).isSizeAllowed()) {\n                if (clickType == ClickType.QUICK_MOVE) {\n                    slot.set(ItemStack.EMPTY);\n                } else if (!player.containerMenu.getCarried().isEmpty()) {\n                    slot.set(player.containerMenu.getCarried().copy());\n                }\n            } else if (player.containerMenu.getCarried().isEmpty()) {\n                slot.set(ItemStack.EMPTY);\n            } else if (slot.mayPlace(player.containerMenu.getCarried())) {\n                slot.set(player.containerMenu.getCarried().copy());\n            }\n\n            return;\n        } else if (slot instanceof FluidFilterSlot) {\n            if (((FluidFilterSlot) slot).isSizeAllowed()) {\n                if (clickType == ClickType.QUICK_MOVE) {\n                    ((FluidFilterSlot) slot).onContainerClicked(ItemStack.EMPTY);\n                } else if (!player.containerMenu.getCarried().isEmpty()) {\n                    ((FluidFilterSlot) slot).onContainerClicked(player.containerMenu.getCarried());\n                }\n            } else if (player.containerMenu.getCarried().isEmpty()) {\n                ((FluidFilterSlot) slot).onContainerClicked(ItemStack.EMPTY);\n            } else {\n                ((FluidFilterSlot) slot).onContainerClicked(player.containerMenu.getCarried());\n            }\n\n            return;\n        } else if (slot instanceof LegacyFilterSlot) {\n            if (player.containerMenu.getCarried().isEmpty()) {\n                slot.set(ItemStack.EMPTY);\n            } else if (slot.mayPlace(player.containerMenu.getCarried())) {\n                slot.set(player.containerMenu.getCarried().copy());\n            }\n\n            return;\n        } else if (slot instanceof LegacyDisabledSlot) {\n            return;\n        }\n\n        super.clicked(id, dragType, clickType, player);\n    }\n\n    @Override\n    public ItemStack quickMoveStack(Player player, int slotIndex) {\n        return transferManager.transfer(slotIndex);\n    }\n\n    @Override\n    public boolean stillValid(Player player) {\n        return isBlockEntityStillPresent();\n    }\n\n    private boolean isBlockEntityStillPresent() {\n        if (blockEntity != null) {\n            return blockEntity.getLevel().getBlockEntity(blockEntity.getBlockPos()) == blockEntity;\n        }\n        return true;\n    }\n\n    @Override\n    public boolean canTakeItemForPickAll(ItemStack stack, Slot slot) {\n        if (slot instanceof FilterSlot || slot instanceof FluidFilterSlot || slot instanceof LegacyFilterSlot) {\n            return false;\n        }\n\n        return super.canTakeItemForPickAll(stack, slot);\n    }\n\n    protected int getDisabledSlotNumber() {\n        return -1;\n    }\n\n    @Override\n    protected Slot addSlot(Slot slot) {\n        if (slot instanceof FluidFilterSlot) {\n            fluids.add(FluidStack.EMPTY);\n            fluidSlots.add((FluidFilterSlot) slot);\n        }\n\n        return super.addSlot(slot);\n    }\n\n    @Override\n    public void broadcastChanges() {\n        super.broadcastChanges();\n\n        // Prevent sending changes about a tile that doesn't exist anymore.\n        // This prevents crashes when sending network node data (network node would crash because it no longer exists and we're querying it from the various tile data parameters).\n        if (listener != null && isBlockEntityStillPresent()) {\n            listener.detectAndSendChanges();\n        }\n\n        if (this.getPlayer() instanceof ServerPlayer) {\n            for (int i = 0; i < this.fluidSlots.size(); ++i) {\n                FluidFilterSlot slot = this.fluidSlots.get(i);\n\n                FluidStack cached = this.fluids.get(i);\n                FluidStack actual = slot.getFluidInventory().getFluid(slot.getSlotIndex());\n\n                if (!API.instance().getComparer().isEqual(cached, actual, IComparer.COMPARE_QUANTITY | IComparer.COMPARE_NBT)) {\n                    this.fluids.set(i, actual.copy());\n\n                    RS.NETWORK_HANDLER.sendTo((ServerPlayer) getPlayer(), new FluidFilterSlotUpdateMessage(((Slot) slot).index, actual));\n                }\n            }\n        }\n    }\n\n    @Override\n    public void removed(Player player) {\n        super.removed(player);\n\n        if (listener != null) {\n            listener.onClosed();\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/ConstructorContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.container.slot.filter.FilterSlot;\nimport com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot;\nimport com.refinedmods.refinedstorage.blockentity.ConstructorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport net.minecraft.world.entity.player.Player;\nimport net.neoforged.neoforge.items.SlotItemHandler;\n\npublic class ConstructorContainerMenu extends BaseContainerMenu {\n    public ConstructorContainerMenu(ConstructorBlockEntity constructor, Player player, int windowId) {\n        super(RSContainerMenus.CONSTRUCTOR.get(), constructor, player, windowId);\n\n        for (int i = 0; i < 4; ++i) {\n            addSlot(new SlotItemHandler(constructor.getNode().getUpgrades(), i, 187, 6 + (i * 18)));\n        }\n\n        addSlot(new FilterSlot(constructor.getNode().getItemFilters(), 0, 80, 20).setEnableHandler(() -> constructor.getNode().getType() == IType.ITEMS));\n        addSlot(new FluidFilterSlot(constructor.getNode().getFluidFilters(), 0, 80, 20, 0).setEnableHandler(() -> constructor.getNode().getType() == IType.FLUIDS));\n\n        addPlayerInventory(8, 55);\n\n        transferManager.addBiTransfer(player.getInventory(), constructor.getNode().getUpgrades());\n        transferManager.addFilterTransfer(player.getInventory(), constructor.getNode().getItemFilters(), constructor.getNode().getFluidFilters(), constructor.getNode()::getType);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/ControllerContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.blockentity.ControllerBlockEntity;\nimport net.minecraft.world.entity.player.Player;\n\npublic class ControllerContainerMenu extends BaseContainerMenu {\n    public ControllerContainerMenu(ControllerBlockEntity controller, Player player, int windowId) {\n        super(RSContainerMenus.CONTROLLER.get(), controller, player, windowId);\n\n        addPlayerInventory(8, 99);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/CrafterContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.blockentity.CrafterBlockEntity;\nimport net.minecraft.world.entity.player.Player;\nimport net.neoforged.neoforge.items.SlotItemHandler;\n\npublic class CrafterContainerMenu extends BaseContainerMenu {\n    public CrafterContainerMenu(CrafterBlockEntity crafter, Player player, int windowId) {\n        super(RSContainerMenus.CRAFTER.get(), crafter, player, windowId);\n\n        for (int i = 0; i < 9; ++i) {\n            addSlot(new SlotItemHandler(crafter.getNode().getPatternInventory(), i, 8 + (18 * i), 20));\n        }\n\n        for (int i = 0; i < 4; ++i) {\n            addSlot(new SlotItemHandler(crafter.getNode().getUpgrades(), i, 187, 6 + (i * 18)));\n        }\n\n        addPlayerInventory(8, 55);\n\n        transferManager.addBiTransfer(player.getInventory(), crafter.getNode().getUpgrades());\n        transferManager.addBiTransfer(player.getInventory(), crafter.getNode().getPatternInventory());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/CrafterManagerContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.CrafterManagerNetworkNode;\nimport com.refinedmods.refinedstorage.container.slot.CrafterManagerSlot;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.validator.PatternItemValidator;\nimport com.refinedmods.refinedstorage.item.PatternItem;\nimport com.refinedmods.refinedstorage.screen.IScreenInfoProvider;\nimport com.refinedmods.refinedstorage.screen.grid.filtering.GridFilterParser;\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack;\nimport com.refinedmods.refinedstorage.blockentity.CrafterManagerBlockEntity;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.Slot;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.function.Predicate;\n\npublic class CrafterManagerContainerMenu extends BaseContainerMenu {\n    private final CrafterManagerNetworkNode crafterManager;\n    private final Map<String, IItemHandlerModifiable> dummyInventories = new HashMap<>();\n    private final Map<String, Integer> headings = new HashMap<>();\n    private IScreenInfoProvider screenInfoProvider;\n    private Map<String, Integer> containerData;\n    private int rows;\n\n    public CrafterManagerContainerMenu(CrafterManagerBlockEntity crafterManager, Player player, int windowId) {\n        super(RSContainerMenus.CRAFTER_MANAGER.get(), crafterManager, player, windowId);\n\n        this.crafterManager = crafterManager.getNode();\n    }\n\n    public void setScreenInfoProvider(IScreenInfoProvider infoProvider) {\n        this.screenInfoProvider = infoProvider;\n    }\n\n    public void initSlotsServer() {\n        addPlayerInventory(8, screenInfoProvider.getYPlayerInventory());\n\n        if (crafterManager.getNetwork() != null) {\n            for (Map.Entry<Component, List<IItemHandlerModifiable>> entry : crafterManager.getNetwork().getCraftingManager().getNamedContainers().entrySet()) {\n                for (IItemHandlerModifiable handler : entry.getValue()) {\n                    for (int i = 0; i < handler.getSlots(); ++i) {\n                        addSlot(new CrafterManagerSlot(handler, i, 0, 0, true, screenInfoProvider, crafterManager));\n                    }\n                }\n            }\n        }\n    }\n\n    public void initSlots(@Nullable Map<String, Integer> data) {\n        if (data != null) {\n            this.containerData = data;\n        }\n\n        this.slots.clear();\n        this.lastSlots.clear();\n        this.headings.clear();\n\n        this.rows = 0;\n\n        addPlayerInventory(8, screenInfoProvider.getYPlayerInventory());\n\n        int y = 19 + 18 - screenInfoProvider.getCurrentOffset() * 18;\n        int x = 8;\n\n        Predicate<IGridStack> filters = GridFilterParser.getFilters(null, screenInfoProvider.getSearchFieldText(), Collections.emptyList());\n\n        for (Map.Entry<String, Integer> category : containerData.entrySet()) {\n            IItemHandlerModifiable dummy;\n\n            if (data == null) { // We're only resizing, get the previous inventory...\n                dummy = dummyInventories.get(category.getKey());\n            } else {\n                dummy = new BaseItemHandler(category.getValue()) {\n                    @Override\n                    public int getSlotLimit(int slot) {\n                        return 1;\n                    }\n\n                    @Nonnull\n                    @Override\n                    public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) {\n                        if (new PatternItemValidator(getPlayer().getCommandSenderWorld()).test(stack)) {\n                            return super.insertItem(slot, stack, simulate);\n                        }\n\n                        return stack;\n                    }\n                };\n\n                dummyInventories.put(category.getKey(), dummy);\n            }\n\n            boolean foundItemsInCategory = false;\n\n            int yHeading = y - 19;\n\n            int slotFound = 0;\n            for (int slot = 0; slot < category.getValue(); ++slot) {\n                boolean visible = true;\n\n                if (!screenInfoProvider.getSearchFieldText().trim().isEmpty()) {\n                    ItemStack stack = dummy.getStackInSlot(slot);\n\n                    if (stack.isEmpty()) {\n                        visible = false;\n                    } else {\n                        ICraftingPattern pattern = PatternItem.fromCache(crafterManager.getLevel(), stack);\n\n                        visible = false;\n\n                        if (pattern.isValid()) {\n                            for (ItemStack output : pattern.getOutputs()) {\n                                ItemGridStack outputConverted = new ItemGridStack(output);\n\n                                if (filters.test(outputConverted)) {\n                                    visible = true;\n                                    break;\n                                }\n                            }\n                        }\n                    }\n                }\n\n                addSlot(new CrafterManagerSlot(dummy, slot, x, y, visible, screenInfoProvider, crafterManager));\n\n                if (visible) {\n                    foundItemsInCategory = true;\n\n                    x += 18;\n\n                    // Don't increase y level if we are on our last slot row (otherwise we do y += 18 * 3)\n                    if ((slotFound + 1) % 9 == 0 && slot + 1 < category.getValue()) {\n                        x = 8;\n                        y += 18;\n                        rows++;\n                    }\n\n                    slotFound++;\n                }\n            }\n\n            if (foundItemsInCategory) {\n                headings.put(category.getKey(), yHeading);\n\n                x = 8;\n                y += 18 * 2;\n                rows += 2; // Heading and first row\n            }\n        }\n    }\n\n    public Map<String, Integer> getHeadings() {\n        return headings;\n    }\n\n    public int getRows() {\n        return rows;\n    }\n\n    @Override\n    public ItemStack quickMoveStack(Player player, int index) {\n        ItemStack stack = ItemStack.EMPTY;\n\n        Slot slot = getSlot(index);\n\n        if (slot.hasItem()) {\n            stack = slot.getItem();\n            if (!new PatternItemValidator(getPlayer().getCommandSenderWorld()).test(stack)) {\n                return ItemStack.EMPTY;\n            }\n            if (index < 9 * 4) {\n                if (!moveItemStackTo(stack, 9 * 4, slots.size(), false)) {\n                    return ItemStack.EMPTY;\n                }\n            } else if (!moveItemStackTo(stack, 0, 9 * 4, false)) {\n                return ItemStack.EMPTY;\n            }\n\n            if (stack.getCount() == 0) {\n                slot.set(ItemStack.EMPTY);\n            } else {\n                slot.setChanged();\n            }\n        }\n\n        return stack;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/CraftingMonitorContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager;\nimport com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorListener;\nimport com.refinedmods.refinedstorage.network.craftingmonitor.CraftingMonitorSyncTask;\nimport com.refinedmods.refinedstorage.network.craftingmonitor.CraftingMonitorUpdateMessage;\nimport com.refinedmods.refinedstorage.blockentity.craftingmonitor.CraftingMonitorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.craftingmonitor.ICraftingMonitor;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.MenuType;\nimport net.minecraft.world.inventory.Slot;\nimport net.minecraft.world.item.ItemStack;\n\nimport javax.annotation.Nullable;\n\npublic class CraftingMonitorContainerMenu extends BaseContainerMenu implements ICraftingMonitorListener {\n    private final ICraftingMonitor craftingMonitor;\n    private boolean addedListener;\n\n    public CraftingMonitorContainerMenu(MenuType<CraftingMonitorContainerMenu> type, ICraftingMonitor craftingMonitor, @Nullable CraftingMonitorBlockEntity blockEntity, Player player, int windowId) {\n        super(type, blockEntity, player, windowId);\n\n        this.craftingMonitor = craftingMonitor;\n    }\n\n    @Override\n    public void broadcastChanges() {\n        super.broadcastChanges();\n\n        if (!getPlayer().level().isClientSide) {\n            ICraftingManager manager = craftingMonitor.getCraftingManager();\n\n            if (manager != null && !addedListener) {\n                manager.addListener(this);\n\n                this.addedListener = true;\n            } else if (manager == null && addedListener) {\n                this.addedListener = false;\n            }\n        }\n    }\n\n    @Override\n    public void removed(Player player) {\n        super.removed(player);\n\n        if (!player.getCommandSenderWorld().isClientSide) {\n            craftingMonitor.onClosed(player);\n\n            ICraftingManager manager = craftingMonitor.getCraftingManager();\n\n            if (manager != null && addedListener) {\n                manager.removeListener(this);\n            }\n        }\n    }\n\n    public ICraftingMonitor getCraftingMonitor() {\n        return craftingMonitor;\n    }\n\n    @Override\n    public ItemStack quickMoveStack(Player player, int index) {\n        ItemStack stack = ItemStack.EMPTY;\n\n        Slot slot = getSlot(index);\n\n        if (slot.hasItem()) {\n            stack = slot.getItem();\n\n            if (index < 4) {\n                if (!moveItemStackTo(stack, 4, slots.size(), false)) {\n                    return ItemStack.EMPTY;\n                }\n            } else if (!moveItemStackTo(stack, 0, 4, false)) {\n                return ItemStack.EMPTY;\n            }\n\n            if (stack.getCount() == 0) {\n                slot.set(ItemStack.EMPTY);\n            } else {\n                slot.setChanged();\n            }\n        }\n\n        return stack;\n    }\n\n    @Override\n    protected int getDisabledSlotNumber() {\n        return craftingMonitor.getSlotId();\n    }\n\n    @Override\n    public void onAttached() {\n        onChanged();\n    }\n\n    @Override\n    public void onChanged() {\n        RS.NETWORK_HANDLER.sendTo((ServerPlayer) getPlayer(), new CraftingMonitorUpdateMessage(\n            craftingMonitor.getTasks().stream().map(task -> new CraftingMonitorSyncTask(\n                task.getId(),\n                task.getRequested(),\n                task.getQuantity(),\n                task.getStartTime(),\n                task.getCompletionPercentage(),\n                task.getCraftingMonitorElements()\n            )).toList()\n        ));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/CraftingSettingsContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.container.slot.DisabledSlot;\nimport com.refinedmods.refinedstorage.container.slot.filter.DisabledFluidFilterSlot;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport com.refinedmods.refinedstorage.screen.grid.stack.FluidGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack;\nimport net.minecraft.world.entity.player.Player;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\nimport net.neoforged.neoforge.items.ItemStackHandler;\n\npublic class CraftingSettingsContainerMenu extends BaseContainerMenu {\n    public CraftingSettingsContainerMenu(Player player, IGridStack stack) {\n        super(null, null, player, 0);\n\n        if (stack instanceof FluidGridStack) {\n            FluidInventory inventory = new FluidInventory(1);\n\n            inventory.setFluid(0, ((FluidGridStack) stack).getStack());\n\n            addSlot(new DisabledFluidFilterSlot(inventory, 0, 89, 48));\n        } else if (stack instanceof ItemGridStack) {\n            ItemStackHandler handler = new ItemStackHandler(1);\n\n            handler.setStackInSlot(0, ItemHandlerHelper.copyStackWithSize(((ItemGridStack) stack).getStack(), 1));\n\n            addSlot(new DisabledSlot(handler, 0, 89, 48));\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/DestructorContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.container.slot.filter.FilterSlot;\nimport com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot;\nimport com.refinedmods.refinedstorage.blockentity.DestructorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport net.minecraft.world.entity.player.Player;\nimport net.neoforged.neoforge.items.SlotItemHandler;\n\npublic class DestructorContainerMenu extends BaseContainerMenu {\n    public DestructorContainerMenu(DestructorBlockEntity destructor, Player player, int windowId) {\n        super(RSContainerMenus.DESTRUCTOR.get(), destructor, player, windowId);\n\n        for (int i = 0; i < 4; ++i) {\n            addSlot(new SlotItemHandler(destructor.getNode().getUpgrades(), i, 187, 6 + (i * 18)));\n        }\n\n        for (int i = 0; i < 9; ++i) {\n            addSlot(new FilterSlot(destructor.getNode().getItemFilters(), i, 8 + (18 * i), 20).setEnableHandler(() -> destructor.getNode().getType() == IType.ITEMS));\n        }\n\n        for (int i = 0; i < 9; ++i) {\n            addSlot(new FluidFilterSlot(destructor.getNode().getFluidFilters(), i, 8 + (18 * i), 20).setEnableHandler(() -> destructor.getNode().getType() == IType.FLUIDS));\n        }\n\n        addPlayerInventory(8, 55);\n\n        transferManager.addBiTransfer(player.getInventory(), destructor.getNode().getUpgrades());\n        transferManager.addFilterTransfer(player.getInventory(), destructor.getNode().getItemFilters(), destructor.getNode().getFluidFilters(), destructor.getNode()::getType);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/DetectorContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.container.slot.filter.FilterSlot;\nimport com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot;\nimport com.refinedmods.refinedstorage.blockentity.DetectorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport net.minecraft.world.entity.player.Player;\n\npublic class DetectorContainerMenu extends BaseContainerMenu {\n    public DetectorContainerMenu(DetectorBlockEntity detector, Player player, int windowId) {\n        super(RSContainerMenus.DETECTOR.get(), detector, player, windowId);\n\n        addSlot(new FilterSlot(detector.getNode().getItemFilters(), 0, 107, 20).setEnableHandler(() -> detector.getNode().getType() == IType.ITEMS));\n        addSlot(new FluidFilterSlot(detector.getNode().getFluidFilters(), 0, 107, 20).setEnableHandler(() -> detector.getNode().getType() == IType.FLUIDS));\n\n        addPlayerInventory(8, 55);\n\n        transferManager.addFilterTransfer(player.getInventory(), detector.getNode().getItemFilters(), detector.getNode().getFluidFilters(), detector.getNode()::getType);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/DiskDriveContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.container.slot.filter.FilterSlot;\nimport com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot;\nimport com.refinedmods.refinedstorage.blockentity.DiskDriveBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport net.minecraft.world.entity.player.Player;\nimport net.neoforged.neoforge.items.SlotItemHandler;\n\npublic class DiskDriveContainerMenu extends BaseContainerMenu {\n    public DiskDriveContainerMenu(DiskDriveBlockEntity diskDrive, Player player, int windowId) {\n        super(RSContainerMenus.DISK_DRIVE.get(), diskDrive, player, windowId);\n\n        int x = 80;\n        int y = 54;\n\n        for (int i = 0; i < 8; ++i) {\n            addSlot(new SlotItemHandler(diskDrive.getNode().getDisks(), i, x + ((i % 2) * 18), y + Math.floorDiv(i, 2) * 18));\n        }\n\n        for (int i = 0; i < 9; ++i) {\n            addSlot(new FilterSlot(diskDrive.getNode().getItemFilters(), i, 8 + (18 * i), 20).setEnableHandler(() -> diskDrive.getNode().getType() == IType.ITEMS));\n        }\n\n        for (int i = 0; i < 9; ++i) {\n            addSlot(new FluidFilterSlot(diskDrive.getNode().getFluidFilters(), i, 8 + (18 * i), 20).setEnableHandler(() -> diskDrive.getNode().getType() == IType.FLUIDS));\n        }\n\n        addPlayerInventory(8, 141);\n\n        transferManager.addBiTransfer(player.getInventory(), diskDrive.getNode().getDisks());\n        transferManager.addFilterTransfer(player.getInventory(), diskDrive.getNode().getItemFilters(), diskDrive.getNode().getFluidFilters(), diskDrive.getNode()::getType);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/DiskManipulatorContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.container.slot.filter.FilterSlot;\nimport com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot;\nimport com.refinedmods.refinedstorage.blockentity.DiskManipulatorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport net.minecraft.world.entity.player.Player;\nimport net.neoforged.neoforge.items.SlotItemHandler;\n\npublic class DiskManipulatorContainerMenu extends BaseContainerMenu {\n    public DiskManipulatorContainerMenu(DiskManipulatorBlockEntity diskManipulator, Player player, int windowId) {\n        super(RSContainerMenus.DISK_MANIPULATOR.get(), diskManipulator, player, windowId);\n\n        for (int i = 0; i < 4; ++i) {\n            addSlot(new SlotItemHandler(diskManipulator.getNode().getUpgrades(), i, 187, 6 + (i * 18)));\n        }\n\n        for (int i = 0; i < 3; ++i) {\n            addSlot(new SlotItemHandler(diskManipulator.getNode().getInputDisks(), i, 44, 57 + (i * 18)));\n        }\n\n        for (int i = 0; i < 3; ++i) {\n            addSlot(new SlotItemHandler(diskManipulator.getNode().getOutputDisks(), i, 116, 57 + (i * 18)));\n        }\n\n        for (int i = 0; i < 9; ++i) {\n            addSlot(new FilterSlot(diskManipulator.getNode().getItemFilters(), i, 8 + (18 * i), 20).setEnableHandler(() -> diskManipulator.getNode().getType() == IType.ITEMS));\n        }\n\n        for (int i = 0; i < 9; ++i) {\n            addSlot(new FluidFilterSlot(diskManipulator.getNode().getFluidFilters(), i, 8 + (18 * i), 20).setEnableHandler(() -> diskManipulator.getNode().getType() == IType.FLUIDS));\n        }\n\n        addPlayerInventory(8, 129);\n\n        transferManager.addBiTransfer(player.getInventory(), diskManipulator.getNode().getUpgrades());\n        transferManager.addBiTransfer(player.getInventory(), diskManipulator.getNode().getInputDisks());\n        transferManager.addTransfer(diskManipulator.getNode().getOutputDisks(), player.getInventory());\n        transferManager.addFilterTransfer(player.getInventory(), diskManipulator.getNode().getItemFilters(), diskManipulator.getNode().getFluidFilters(), diskManipulator.getNode()::getType);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/ExporterContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.container.slot.filter.FilterSlot;\nimport com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot;\nimport com.refinedmods.refinedstorage.item.UpgradeItem;\nimport com.refinedmods.refinedstorage.blockentity.ExporterBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport net.minecraft.world.entity.player.Player;\nimport net.neoforged.neoforge.items.SlotItemHandler;\n\npublic class ExporterContainerMenu extends BaseContainerMenu {\n    private final ExporterBlockEntity exporter;\n    private boolean hasRegulatorMode;\n\n    public ExporterContainerMenu(ExporterBlockEntity exporter, Player player, int windowId) {\n        super(RSContainerMenus.EXPORTER.get(), exporter, player, windowId);\n\n        this.exporter = exporter;\n        this.hasRegulatorMode = hasRegulatorMode();\n\n        initSlots();\n    }\n\n    private boolean hasRegulatorMode() {\n        return exporter.getNode().getUpgrades().hasUpgrade(UpgradeItem.Type.REGULATOR);\n    }\n\n    @Override\n    public void broadcastChanges() {\n        super.broadcastChanges();\n\n        boolean updatedHasRegulatorMode = hasRegulatorMode();\n        if (hasRegulatorMode != updatedHasRegulatorMode) {\n            hasRegulatorMode = updatedHasRegulatorMode;\n\n            initSlots();\n        }\n    }\n\n    public void initSlots() {\n        this.slots.clear();\n        this.lastSlots.clear();\n\n        this.transferManager.clearTransfers();\n\n        for (int i = 0; i < 4; ++i) {\n            addSlot(new SlotItemHandler(exporter.getNode().getUpgrades(), i, 187, 6 + (i * 18)));\n        }\n\n        for (int i = 0; i < 9; ++i) {\n            addSlot(new FilterSlot(\n                exporter.getNode().getItemFilters(),\n                i,\n                8 + (18 * i),\n                20,\n                exporter.getNode().getUpgrades().hasUpgrade(UpgradeItem.Type.REGULATOR) ? FilterSlot.FILTER_ALLOW_SIZE : 0\n            ).setEnableHandler(() -> exporter.getNode().getType() == IType.ITEMS));\n        }\n\n        for (int i = 0; i < 9; ++i) {\n            addSlot(new FluidFilterSlot(\n                exporter.getNode().getFluidFilters(),\n                i,\n                8 + (18 * i),\n                20,\n                exporter.getNode().getUpgrades().hasUpgrade(UpgradeItem.Type.REGULATOR) ? FluidFilterSlot.FILTER_ALLOW_SIZE : 0\n            ).setEnableHandler(() -> exporter.getNode().getType() == IType.FLUIDS));\n        }\n\n        addPlayerInventory(8, 55);\n\n        transferManager.addBiTransfer(getPlayer().getInventory(), exporter.getNode().getUpgrades());\n        transferManager.addFilterTransfer(getPlayer().getInventory(), exporter.getNode().getItemFilters(), exporter.getNode().getFluidFilters(), exporter.getNode()::getType);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/ExternalStorageContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.container.slot.filter.FilterSlot;\nimport com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot;\nimport com.refinedmods.refinedstorage.blockentity.ExternalStorageBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport net.minecraft.world.entity.player.Player;\n\npublic class ExternalStorageContainerMenu extends BaseContainerMenu {\n    public ExternalStorageContainerMenu(ExternalStorageBlockEntity externalStorage, Player player, int windowId) {\n        super(RSContainerMenus.EXTERNAL_STORAGE.get(), externalStorage, player, windowId);\n\n        for (int i = 0; i < 9; ++i) {\n            addSlot(new FilterSlot(externalStorage.getNode().getItemFilters(), i, 8 + (18 * i), 20).setEnableHandler(() -> externalStorage.getNode().getType() == IType.ITEMS));\n        }\n\n        for (int i = 0; i < 9; ++i) {\n            addSlot(new FluidFilterSlot(externalStorage.getNode().getFluidFilters(), i, 8 + (18 * i), 20).setEnableHandler(() -> externalStorage.getNode().getType() == IType.FLUIDS));\n        }\n\n        addPlayerInventory(8, 141);\n\n        transferManager.addFilterTransfer(player.getInventory(), externalStorage.getNode().getItemFilters(), externalStorage.getNode().getFluidFilters(), externalStorage.getNode()::getType);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/FilterContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.container.slot.filter.FilterSlot;\nimport com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot;\nimport com.refinedmods.refinedstorage.inventory.fluid.ConfiguredFluidsInFilterItemHandler;\nimport com.refinedmods.refinedstorage.inventory.fluid.ConfiguredIconInFluidFilterItemHandler;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport com.refinedmods.refinedstorage.inventory.item.ConfiguredIconInFilterItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.ConfiguredItemsInFilterItemHandler;\nimport com.refinedmods.refinedstorage.item.FilterItem;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\n\npublic class FilterContainerMenu extends BaseContainerMenu {\n    private final ItemStack filterItem;\n\n    public FilterContainerMenu(Player player, ItemStack filterItem, int windowId) {\n        super(RSContainerMenus.FILTER.get(), null, player, windowId);\n\n        this.filterItem = filterItem;\n\n        int y = 20;\n        int x = 8;\n\n        ConfiguredItemsInFilterItemHandler filter = new ConfiguredItemsInFilterItemHandler(filterItem);\n        FluidInventory fluidFilter = new ConfiguredFluidsInFilterItemHandler(filterItem);\n\n        for (int i = 0; i < 27; ++i) {\n            addSlot(new FilterSlot(filter, i, x, y).setEnableHandler(() -> FilterItem.getType(filterItem) == IType.ITEMS));\n            addSlot(new FluidFilterSlot(fluidFilter, i, x, y).setEnableHandler(() -> FilterItem.getType(filterItem) == IType.FLUIDS));\n\n            if ((i + 1) % 9 == 0) {\n                x = 8;\n                y += 18;\n            } else {\n                x += 18;\n            }\n        }\n\n        addSlot(new FilterSlot(new ConfiguredIconInFilterItemHandler(filterItem), 0, 8, 117).setEnableHandler(() -> FilterItem.getType(filterItem) == IType.ITEMS));\n        addSlot(new FluidFilterSlot(new ConfiguredIconInFluidFilterItemHandler(filterItem), 0, 8, 117).setEnableHandler(() -> FilterItem.getType(filterItem) == IType.FLUIDS));\n\n        addPlayerInventory(8, 149);\n\n        transferManager.addFilterTransfer(player.getInventory(), filter, fluidFilter, () -> FilterItem.getType(filterItem));\n    }\n\n    public ItemStack getFilterItem() {\n        return filterItem;\n    }\n\n    @Override\n    protected int getDisabledSlotNumber() {\n        return getPlayer().getInventory().selected;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/FluidAmountContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.container.slot.filter.DisabledFluidFilterSlot;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport net.minecraft.world.entity.player.Player;\nimport net.neoforged.neoforge.fluids.FluidStack;\n\npublic class FluidAmountContainerMenu extends BaseContainerMenu {\n    public FluidAmountContainerMenu(Player player, FluidStack stack) {\n        super(null, null, player, 0);\n\n        FluidInventory inventory = new FluidInventory(1);\n\n        inventory.setFluid(0, stack);\n\n        addSlot(new DisabledFluidFilterSlot(inventory, 0, 89, 48, 0));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/FluidInterfaceContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.container.slot.filter.FilterSlot;\nimport com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot;\nimport com.refinedmods.refinedstorage.blockentity.FluidInterfaceBlockEntity;\nimport net.minecraft.world.entity.player.Player;\nimport net.neoforged.neoforge.items.SlotItemHandler;\n\npublic class FluidInterfaceContainerMenu extends BaseContainerMenu {\n    public FluidInterfaceContainerMenu(FluidInterfaceBlockEntity fluidInterface, Player player, int windowId) {\n        super(RSContainerMenus.FLUID_INTERFACE.get(), fluidInterface, player, windowId);\n\n        for (int i = 0; i < 4; ++i) {\n            addSlot(new SlotItemHandler(fluidInterface.getNode().getUpgrades(), i, 187, 6 + (i * 18)));\n        }\n\n        addSlot(new SlotItemHandler(fluidInterface.getNode().getIn(), 0, 44, 32));\n        addSlot(new FluidFilterSlot(fluidInterface.getNode().getOut(), 0, 116, 32, FilterSlot.FILTER_ALLOW_SIZE));\n\n        addPlayerInventory(8, 122);\n\n        transferManager.addBiTransfer(player.getInventory(), fluidInterface.getNode().getIn());\n        transferManager.addFluidFilterTransfer(player.getInventory(), fluidInterface.getNode().getOut());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/FluidStorageContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot;\nimport com.refinedmods.refinedstorage.blockentity.FluidStorageBlockEntity;\nimport net.minecraft.world.entity.player.Player;\n\npublic class FluidStorageContainerMenu extends BaseContainerMenu {\n    public FluidStorageContainerMenu(FluidStorageBlockEntity fluidStorage, Player player, int windowId) {\n        super(RSContainerMenus.FLUID_STORAGE_BLOCK.get(), fluidStorage, player, windowId);\n\n        for (int i = 0; i < 9; ++i) {\n            addSlot(new FluidFilterSlot(fluidStorage.getNode().getFilters(), i, 8 + (18 * i), 20));\n        }\n\n        addPlayerInventory(8, 141);\n\n        transferManager.addFluidFilterTransfer(player.getInventory(), fluidStorage.getNode().getFilters());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/GridContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.api.network.grid.GridType;\nimport com.refinedmods.refinedstorage.api.network.grid.ICraftingGridListener;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.BaseBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.blockentity.grid.portable.IPortableGrid;\nimport com.refinedmods.refinedstorage.container.slot.filter.FilterSlot;\nimport com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot;\nimport com.refinedmods.refinedstorage.container.slot.grid.CraftingGridSlot;\nimport com.refinedmods.refinedstorage.container.slot.grid.ResultCraftingGridSlot;\nimport com.refinedmods.refinedstorage.container.slot.legacy.LegacyBaseSlot;\nimport com.refinedmods.refinedstorage.container.slot.legacy.LegacyDisabledSlot;\nimport com.refinedmods.refinedstorage.container.slot.legacy.LegacyFilterSlot;\nimport com.refinedmods.refinedstorage.screen.IScreenInfoProvider;\nimport net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.ContainerListener;\nimport net.minecraft.world.inventory.Slot;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.SlotItemHandler;\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class GridContainerMenu extends BaseContainerMenu implements ICraftingGridListener {\n    private final IGrid grid;\n    private IStorageCache storageCache;\n    private IStorageCacheListener storageCacheListener;\n    private IScreenInfoProvider screenInfoProvider;\n\n    private ResultCraftingGridSlot craftingResultSlot;\n    private LegacyBaseSlot patternResultSlot;\n    private List<Slot> itemPatternSlots = new ArrayList<>();\n    private List<Slot> fluidPatternSlots = new ArrayList<>();\n    private int patternScrollOffset;\n\n    public GridContainerMenu(IGrid grid, @Nullable BaseBlockEntity blockEntity, Player player, int windowId) {\n        super(RSContainerMenus.GRID.get(), blockEntity, player, windowId);\n\n        this.grid = grid;\n\n        grid.addCraftingListener(this);\n    }\n\n    public IScreenInfoProvider getScreenInfoProvider() {\n        return screenInfoProvider;\n    }\n\n    public void setScreenInfoProvider(IScreenInfoProvider screenInfoProvider) {\n        this.screenInfoProvider = screenInfoProvider;\n    }\n\n    public void initSlots() {\n        this.slots.clear();\n        this.lastSlots.clear();\n\n        this.transferManager.clearTransfers();\n\n        addFilterSlots();\n\n        if (grid instanceof IPortableGrid) {\n            addPortableGridSlots();\n        }\n\n        if (grid.getGridType() == GridType.CRAFTING) {\n            addCraftingSlots();\n        } else if (grid.getGridType() == GridType.PATTERN) {\n            addPatternSlots();\n        }\n\n        transferManager.setNotFoundHandler(slotIndex -> {\n            if (!getPlayer().getCommandSenderWorld().isClientSide) {\n                Slot slot = slots.get(slotIndex);\n                if (grid instanceof IPortableGrid && slot instanceof SlotItemHandler && ((SlotItemHandler) slot).getItemHandler().equals(((IPortableGrid) grid).getDiskInventory())) {\n                    return ItemStack.EMPTY;\n                }\n\n                if (slot.hasItem()) {\n                    if (slot == craftingResultSlot) {\n                        grid.onCraftedShift(getPlayer());\n\n                        broadcastChanges();\n                    } else {\n                        ItemStack stack = slot.getItem();\n\n                        if (grid.getGridType() == GridType.FLUID) {\n                            IFluidGridHandler fluidHandler = grid.getFluidHandler();\n\n                            if (fluidHandler != null) {\n                                slot.set(fluidHandler.onInsert((ServerPlayer) getPlayer(), stack));\n                            }\n                        } else {\n                            IItemGridHandler itemHandler = grid.getItemHandler();\n\n                            if (itemHandler != null) {\n                                slot.set(itemHandler.onInsert((ServerPlayer) getPlayer(), stack, false));\n                            } else if (slot instanceof CraftingGridSlot && moveItemStackTo(stack, 14, 14 + (9 * 4), false)) {\n                                slot.setChanged();\n\n                                // This is needed because when a grid is disconnected,\n                                // and a player shift clicks from the matrix to the inventory (this if case),\n                                // the crafting inventory isn't being notified.\n                                grid.onCraftingMatrixChanged();\n                            }\n                        }\n\n                        broadcastChanges();\n                    }\n                }\n            }\n\n            return ItemStack.EMPTY;\n        });\n\n        addPlayerInventory(8, screenInfoProvider.getYPlayerInventory());\n    }\n\n    private void addPortableGridSlots() {\n        addSlot(new SlotItemHandler(((IPortableGrid) grid).getDiskInventory(), 0, 204, 6));\n\n        transferManager.addBiTransfer(getPlayer().getInventory(), ((IPortableGrid) grid).getDiskInventory());\n    }\n\n    private void addFilterSlots() {\n        int yStart = 6;\n\n        if (grid instanceof IPortableGrid) {\n            yStart = 38;\n        }\n\n        for (int i = 0; i < 4; ++i) {\n            addSlot(new SlotItemHandler(grid.getFilter(), i, 204, yStart + (18 * i)));\n        }\n\n        transferManager.addBiTransfer(getPlayer().getInventory(), grid.getFilter());\n    }\n\n    private void addCraftingSlots() {\n        int headerAndSlots = screenInfoProvider.getTopHeight() + (screenInfoProvider.getVisibleRows() * 18);\n\n        int x = 26;\n        int y = headerAndSlots + 4;\n\n        for (int i = 0; i < 9; ++i) {\n            addSlot(new CraftingGridSlot(grid.getCraftingMatrix(), i, x, y));\n\n            x += 18;\n\n            if ((i + 1) % 3 == 0) {\n                y += 18;\n                x = 26;\n            }\n        }\n\n        craftingResultSlot = new ResultCraftingGridSlot(getPlayer(), grid, 0, 130 + 4, headerAndSlots + 22);\n        addSlot(craftingResultSlot);\n    }\n\n    private void addPatternSlots() {\n        itemPatternSlots.clear();\n        fluidPatternSlots.clear();\n        int headerAndSlots = screenInfoProvider.getTopHeight() + (screenInfoProvider.getVisibleRows() * 18);\n\n        addSlot(new SlotItemHandler(((GridNetworkNode) grid).getPatterns(), 0, 172, headerAndSlots + 4));\n        addSlot(new SlotItemHandler(((GridNetworkNode) grid).getPatterns(), 1, 172, headerAndSlots + 40));\n\n        transferManager.addBiTransfer(getPlayer().getInventory(), ((GridNetworkNode) grid).getPatterns());\n\n        // Processing patterns\n        int ox = 8;\n        int x = ox;\n        int y = headerAndSlots + 4;\n\n        for (int i = 0; i < GridNetworkNode.PROCESSING_MATRIX_SIZE * 2; ++i) {\n            int itemFilterSlotConfig = FilterSlot.FILTER_ALLOW_SIZE;\n            if (i < GridNetworkNode.PROCESSING_MATRIX_SIZE) {\n                itemFilterSlotConfig |= FilterSlot.FILTER_ALLOW_ALTERNATIVES;\n            }\n\n            int fluidFilterSlotConfig = FluidFilterSlot.FILTER_ALLOW_SIZE;\n            if (i < GridNetworkNode.PROCESSING_MATRIX_SIZE) {\n                fluidFilterSlotConfig |= FluidFilterSlot.FILTER_ALLOW_ALTERNATIVES;\n            }\n\n            int finalI = i;\n            itemPatternSlots.add(addSlot(new FilterSlot(((GridNetworkNode) grid).getProcessingMatrix(), i, x, y, itemFilterSlotConfig)\n                .setEnableHandler(() -> getSlotEnabled(finalI, true))));\n            fluidPatternSlots.add(addSlot(new FluidFilterSlot(((GridNetworkNode) grid).getProcessingMatrixFluids(), i, x, y, fluidFilterSlotConfig)\n                .setEnableHandler(() -> getSlotEnabled(finalI, false))));\n\n            x += 18;\n\n            if ((i + 1) % 3 == 0) {\n                if (i == GridNetworkNode.PROCESSING_MATRIX_SIZE - 1) {\n                    ox = 93;\n                    x = ox;\n                    y = headerAndSlots + 4;\n                } else {\n                    x = ox;\n                    y += 18;\n                }\n            }\n        }\n\n        // Regular patterns\n        x = 26;\n        y = headerAndSlots + 4;\n\n        for (int i = 0; i < 9; ++i) {\n            addSlot(new LegacyFilterSlot(grid.getCraftingMatrix(), i, x, y).setEnableHandler(() -> !((GridNetworkNode) grid).isProcessingPattern()));\n\n            x += 18;\n\n            if ((i + 1) % 3 == 0) {\n                y += 18;\n                x = 26;\n            }\n        }\n\n        patternResultSlot = new LegacyDisabledSlot(grid.getCraftingResult(), 0, 134, headerAndSlots + 22).setEnableHandler(() -> !((GridNetworkNode) grid).isProcessingPattern());\n        addSlot(patternResultSlot);\n    }\n\n    private boolean getSlotEnabled(int i, boolean item) {\n        if (!((GridNetworkNode) grid).isProcessingPattern() || !isVisible(i)) {\n            return false;\n        }\n\n        if (item) {\n            if (itemPatternSlots.get(i).hasItem()) {\n                return true;\n            }\n\n            if (((FluidFilterSlot) fluidPatternSlots.get(i)).hasStack()) {\n                return false;\n            }\n\n            return ((GridNetworkNode) grid).getType() == IType.ITEMS;\n        } else {\n            if (((FluidFilterSlot) fluidPatternSlots.get(i)).hasStack()) {\n                return true;\n            }\n\n            if (itemPatternSlots.get(i).hasItem()) {\n                return false;\n            }\n\n            return ((GridNetworkNode) grid).getType() == IType.FLUIDS;\n        }\n    }\n\n    private boolean isVisible(int slotNumber) {\n        return (slotNumber >= patternScrollOffset * 3\n            && slotNumber < patternScrollOffset * 3 + 9)\n\n            || (slotNumber >= patternScrollOffset * 3 + GridNetworkNode.PROCESSING_MATRIX_SIZE\n            && slotNumber < patternScrollOffset * 3 + GridNetworkNode.PROCESSING_MATRIX_SIZE + 9);\n    }\n\n    public IGrid getGrid() {\n        return grid;\n    }\n\n    @Override\n    public void onCraftingMatrixChanged() {\n        for (int i = 0; i < slots.size(); ++i) {\n            Slot slot = slots.get(i);\n\n            if (slot instanceof CraftingGridSlot || slot == craftingResultSlot || slot == patternResultSlot) {\n                for (ContainerListener listener : containerListeners) {\n                    // @Volatile: We can't use ContainerListener#slotChanged since ServerPlayer blocks ResultSlot changes...\n                    if (listener instanceof ServerPlayer) {\n                        ((ServerPlayer) listener).connection.send(new ClientboundContainerSetSlotPacket(containerId, incrementStateId(), i, slot.getItem()));\n                    }\n                }\n            }\n        }\n    }\n\n    @Override\n    public void broadcastChanges() {\n        if (!getPlayer().level().isClientSide) {\n            // The grid is offline.\n            if (grid.getStorageCache() == null) {\n                // The grid just went offline, there is still a listener.\n                if (storageCacheListener != null) {\n                    // Remove it from the previous cache and clean up.\n                    storageCache.removeListener(storageCacheListener);\n\n                    storageCacheListener = null;\n                    storageCache = null;\n                }\n            } else if (storageCacheListener == null) { // The grid came online.\n                storageCacheListener = grid.createListener((ServerPlayer) getPlayer());\n                storageCache = grid.getStorageCache();\n\n                storageCache.addListener(storageCacheListener);\n            }\n        }\n\n        super.broadcastChanges();\n    }\n\n    @Override\n    public void removed(Player player) {\n        super.removed(player);\n\n        if (!player.getCommandSenderWorld().isClientSide) {\n            grid.onClosed(player);\n\n            if (storageCache != null && storageCacheListener != null) {\n                storageCache.removeListener(storageCacheListener);\n            }\n        }\n\n        grid.removeCraftingListener(this);\n    }\n\n    @Override\n    public boolean canTakeItemForPickAll(ItemStack stack, Slot slot) {\n        if (slot == craftingResultSlot || slot == patternResultSlot) {\n            return false;\n        }\n\n        return super.canTakeItemForPickAll(stack, slot);\n    }\n\n    @Override\n    public int getDisabledSlotNumber() {\n        return grid.getSlotId();\n    }\n\n    public void updatePatternSlotPositions(int newOffset) {\n        patternScrollOffset = newOffset;\n        int yPosition = screenInfoProvider.getTopHeight() + (screenInfoProvider.getVisibleRows() * 18) + 4;\n        int originalYPosition = yPosition;\n\n        for (int i = 0; i < itemPatternSlots.size(); i++) {\n\n            if (i == GridNetworkNode.PROCESSING_MATRIX_SIZE) { // reset when reaching output slots\n                yPosition = originalYPosition;\n            }\n\n            if (isVisible(i)) {\n                itemPatternSlots.get(i).y = yPosition;\n                fluidPatternSlots.get(i).y = yPosition;\n                if ((i + 1) % 3 == 0) {\n                    yPosition += 18;\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/ImporterContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.container.slot.filter.FilterSlot;\nimport com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot;\nimport com.refinedmods.refinedstorage.blockentity.ImporterBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport net.minecraft.world.entity.player.Player;\nimport net.neoforged.neoforge.items.SlotItemHandler;\n\npublic class ImporterContainerMenu extends BaseContainerMenu {\n    public ImporterContainerMenu(ImporterBlockEntity importer, Player player, int windowId) {\n        super(RSContainerMenus.IMPORTER.get(), importer, player, windowId);\n\n        for (int i = 0; i < 4; ++i) {\n            addSlot(new SlotItemHandler(importer.getNode().getUpgrades(), i, 187, 6 + (i * 18)));\n        }\n\n        for (int i = 0; i < 9; ++i) {\n            addSlot(new FilterSlot(importer.getNode().getItemFilters(), i, 8 + (18 * i), 20).setEnableHandler(() -> importer.getNode().getType() == IType.ITEMS));\n        }\n\n        for (int i = 0; i < 9; ++i) {\n            addSlot(new FluidFilterSlot(importer.getNode().getFluidFilters(), i, 8 + (18 * i), 20).setEnableHandler(() -> importer.getNode().getType() == IType.FLUIDS));\n        }\n\n        addPlayerInventory(8, 55);\n\n        transferManager.addBiTransfer(player.getInventory(), importer.getNode().getUpgrades());\n        transferManager.addFilterTransfer(player.getInventory(), importer.getNode().getItemFilters(), importer.getNode().getFluidFilters(), importer.getNode()::getType);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/InterfaceContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.container.slot.OutputSlot;\nimport com.refinedmods.refinedstorage.container.slot.filter.FilterSlot;\nimport com.refinedmods.refinedstorage.blockentity.InterfaceBlockEntity;\nimport net.minecraft.world.entity.player.Player;\nimport net.neoforged.neoforge.items.SlotItemHandler;\n\npublic class InterfaceContainerMenu extends BaseContainerMenu {\n    public InterfaceContainerMenu(InterfaceBlockEntity blockEntity, Player player, int windowId) {\n        super(RSContainerMenus.INTERFACE.get(), blockEntity, player, windowId);\n\n        for (int i = 0; i < 9; ++i) {\n            addSlot(new SlotItemHandler(blockEntity.getNode().getImportItems(), i, 8 + (18 * i), 20));\n        }\n\n        for (int i = 0; i < 9; ++i) {\n            addSlot(new FilterSlot(blockEntity.getNode().getExportFilterItems(), i, 8 + (18 * i), 54, FilterSlot.FILTER_ALLOW_SIZE));\n        }\n\n        for (int i = 0; i < 9; ++i) {\n            addSlot(new OutputSlot(blockEntity.getNode().getExportItems(), i, 8 + (18 * i), 100));\n        }\n\n        for (int i = 0; i < 4; ++i) {\n            addSlot(new SlotItemHandler(blockEntity.getNode().getUpgrades(), i, 187, 6 + (i * 18)));\n        }\n\n        addPlayerInventory(8, 134);\n\n        transferManager.addBiTransfer(player.getInventory(), blockEntity.getNode().getUpgrades());\n        transferManager.addBiTransfer(player.getInventory(), blockEntity.getNode().getImportItems());\n        transferManager.addTransfer(blockEntity.getNode().getExportItems(), player.getInventory());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/NetworkTransmitterContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.blockentity.NetworkTransmitterBlockEntity;\nimport net.minecraft.world.entity.player.Player;\nimport net.neoforged.neoforge.items.SlotItemHandler;\n\npublic class NetworkTransmitterContainerMenu extends BaseContainerMenu {\n    public NetworkTransmitterContainerMenu(NetworkTransmitterBlockEntity networkTransmitter, Player player, int windowId) {\n        super(RSContainerMenus.NETWORK_TRANSMITTER.get(), networkTransmitter, player, windowId);\n\n        addSlot(new SlotItemHandler(networkTransmitter.getNode().getNetworkCard(), 0, 8, 20));\n\n        addPlayerInventory(8, 55);\n\n        transferManager.addBiTransfer(player.getInventory(), networkTransmitter.getNode().getNetworkCard());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/RelayContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.blockentity.RelayBlockEntity;\nimport net.minecraft.world.entity.player.Player;\n\npublic class RelayContainerMenu extends BaseContainerMenu {\n    public RelayContainerMenu(RelayBlockEntity relay, Player player, int windowId) {\n        super(RSContainerMenus.RELAY.get(), relay, player, windowId);\n\n        addPlayerInventory(8, 50);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/SecurityManagerContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.blockentity.SecurityManagerBlockEntity;\n\nimport net.minecraft.world.entity.player.Player;\nimport net.neoforged.neoforge.items.SlotItemHandler;\n\npublic class SecurityManagerContainerMenu extends BaseContainerMenu {\n    private final SecurityManagerBlockEntity securityManager;\n\n    public SecurityManagerContainerMenu(SecurityManagerBlockEntity securityManager, Player player, int windowId) {\n        super(RSContainerMenus.SECURITY_MANAGER.get(), securityManager, player, windowId);\n\n        int x = 8;\n        int y = 20;\n\n        for (int i = 0; i < 9 * 2; ++i) {\n            addSlot(new SlotItemHandler(securityManager.getNode().getCardsItems(), i, x, y));\n\n            if (((i + 1) % 9) == 0) {\n                x = 8;\n                y += 18;\n            } else {\n                x += 18;\n            }\n        }\n\n        addSlot(new SlotItemHandler(securityManager.getNode().getEditCard(), 0, 80, 70));\n\n        addPlayerInventory(8, 152);\n\n        transferManager.addBiTransfer(player.getInventory(), securityManager.getNode().getCardsItems());\n        transferManager.addTransfer(securityManager.getNode().getEditCard(), player.getInventory());\n\n        this.securityManager = securityManager;\n    }\n\n    public void updatePermission(Permission permission, boolean state) {\n        securityManager.getNode().updatePermission(permission, state);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/StorageContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.container.slot.filter.FilterSlot;\nimport com.refinedmods.refinedstorage.blockentity.StorageBlockEntity;\nimport net.minecraft.world.entity.player.Player;\n\npublic class StorageContainerMenu extends BaseContainerMenu {\n    public StorageContainerMenu(StorageBlockEntity storage, Player player, int windowId) {\n        super(RSContainerMenus.STORAGE_BLOCK.get(), storage, player, windowId);\n\n        for (int i = 0; i < 9; ++i) {\n            addSlot(new FilterSlot(storage.getNode().getFilters(), i, 8 + (18 * i), 20));\n        }\n\n        addPlayerInventory(8, 141);\n\n        transferManager.addItemFilterTransfer(player.getInventory(), storage.getNode().getFilters());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/StorageMonitorContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.container.slot.filter.FilterSlot;\nimport com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot;\nimport com.refinedmods.refinedstorage.blockentity.StorageMonitorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport net.minecraft.world.entity.player.Player;\n\npublic class StorageMonitorContainerMenu extends BaseContainerMenu {\n    public StorageMonitorContainerMenu(StorageMonitorBlockEntity storageMonitor, Player player, int windowId) {\n        super(RSContainerMenus.STORAGE_MONITOR.get(), storageMonitor, player, windowId);\n\n        addSlot(new FilterSlot(storageMonitor.getNode().getItemFilters(), 0, 80, 20).setEnableHandler(() -> storageMonitor.getNode().getType() == IType.ITEMS));\n        addSlot(new FluidFilterSlot(storageMonitor.getNode().getFluidFilters(), 0, 80, 20).setEnableHandler(() -> storageMonitor.getNode().getType() == IType.FLUIDS));\n\n        addPlayerInventory(8, 55);\n\n        transferManager.addFilterTransfer(player.getInventory(), storageMonitor.getNode().getItemFilters(), storageMonitor.getNode().getFluidFilters(), storageMonitor.getNode()::getType);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/WirelessTransmitterContainerMenu.java",
    "content": "package com.refinedmods.refinedstorage.container;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.blockentity.WirelessTransmitterBlockEntity;\nimport net.minecraft.world.entity.player.Player;\nimport net.neoforged.neoforge.items.SlotItemHandler;\n\npublic class WirelessTransmitterContainerMenu extends BaseContainerMenu {\n    public WirelessTransmitterContainerMenu(WirelessTransmitterBlockEntity wirelessTransmitter, Player player, int windowId) {\n        super(RSContainerMenus.WIRELESS_TRANSMITTER.get(), wirelessTransmitter, player, windowId);\n\n        for (int i = 0; i < 4; ++i) {\n            addSlot(new SlotItemHandler(wirelessTransmitter.getNode().getUpgrades(), i, 187, 6 + (i * 18)));\n        }\n\n        addPlayerInventory(8, 55);\n\n        transferManager.addBiTransfer(player.getInventory(), wirelessTransmitter.getNode().getUpgrades());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/factory/BlockEntityContainerFactory.java",
    "content": "package com.refinedmods.refinedstorage.container.factory;\n\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.neoforged.neoforge.network.IContainerFactory;\n\npublic class BlockEntityContainerFactory<C extends AbstractContainerMenu, T extends BlockEntity> implements IContainerFactory<C> {\n    private final Factory<C, T> factory;\n\n    public BlockEntityContainerFactory(Factory<C, T> factory) {\n        this.factory = factory;\n    }\n\n    @Override\n    public C create(int windowId, Inventory inv, FriendlyByteBuf data) {\n        BlockPos pos = data.readBlockPos();\n\n        T blockEntity = (T) inv.player.level().getBlockEntity(pos);\n\n        return factory.create(windowId, inv, blockEntity);\n    }\n\n    public interface Factory<C, T> {\n        C create(int windowId, Inventory inv, T blockEntity);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/factory/BlockEntityMenuProvider.java",
    "content": "package com.refinedmods.refinedstorage.container.factory;\n\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.world.MenuProvider;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.minecraft.world.level.block.entity.BlockEntity;\n\nimport javax.annotation.Nullable;\n\npublic class BlockEntityMenuProvider<T extends BlockEntity> implements MenuProvider {\n    private final Component name;\n    private final Provider<T> provider;\n    private final BlockPos pos;\n\n    public BlockEntityMenuProvider(Component name, Provider<T> provider, BlockPos pos) {\n        this.name = name;\n        this.provider = provider;\n        this.pos = pos;\n    }\n\n    @Override\n    public Component getDisplayName() {\n        return name;\n    }\n\n    @Nullable\n    @Override\n    public AbstractContainerMenu createMenu(int windowId, Inventory inventory, Player player) {\n        T blockEntity = (T) player.level().getBlockEntity(pos);\n\n        return provider.create(blockEntity, windowId, inventory, player);\n    }\n\n    public interface Provider<T> {\n        AbstractContainerMenu create(T blockEntity, int windowId, Inventory inventory, Player player);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/factory/CrafterManagerContainerFactory.java",
    "content": "package com.refinedmods.refinedstorage.container.factory;\n\nimport com.refinedmods.refinedstorage.container.CrafterManagerContainerMenu;\nimport com.refinedmods.refinedstorage.screen.EmptyScreenInfoProvider;\nimport com.refinedmods.refinedstorage.blockentity.CrafterManagerBlockEntity;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.neoforged.neoforge.network.IContainerFactory;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\npublic class CrafterManagerContainerFactory implements IContainerFactory<CrafterManagerContainerMenu> {\n    @Override\n    public CrafterManagerContainerMenu create(int windowId, Inventory inv, FriendlyByteBuf buf) {\n        Map<String, Integer> data = new LinkedHashMap<>();\n\n        BlockPos pos = buf.readBlockPos();\n\n        int size = buf.readInt();\n\n        for (int i = 0; i < size; ++i) {\n            data.put(buf.readComponent().getString(), buf.readInt());\n        }\n\n        CrafterManagerContainerMenu container = new CrafterManagerContainerMenu((CrafterManagerBlockEntity) inv.player.level().getBlockEntity(pos), inv.player, windowId);\n\n        container.setScreenInfoProvider(new EmptyScreenInfoProvider());\n        container.initSlots(data);\n\n        return container;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/factory/CrafterManagerMenuProvider.java",
    "content": "package com.refinedmods.refinedstorage.container.factory;\n\nimport com.refinedmods.refinedstorage.container.CrafterManagerContainerMenu;\nimport com.refinedmods.refinedstorage.screen.EmptyScreenInfoProvider;\nimport com.refinedmods.refinedstorage.blockentity.CrafterManagerBlockEntity;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.chat.Component;\n\nimport net.minecraft.world.MenuProvider;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport javax.annotation.Nullable;\nimport java.util.List;\nimport java.util.Map;\n\npublic class CrafterManagerMenuProvider implements MenuProvider {\n    private final CrafterManagerBlockEntity blockEntity;\n\n    public CrafterManagerMenuProvider(CrafterManagerBlockEntity blockEntity) {\n        this.blockEntity = blockEntity;\n    }\n\n    public static void writeToBuffer(FriendlyByteBuf buf, Level level, BlockPos pos) {\n        buf.writeBlockPos(pos);\n\n        Map<Component, List<IItemHandlerModifiable>> containerData = ((CrafterManagerBlockEntity) level.getBlockEntity(pos)).getNode().getNetwork().getCraftingManager().getNamedContainers();\n\n        buf.writeInt(containerData.size());\n\n        for (Map.Entry<Component, List<IItemHandlerModifiable>> entry : containerData.entrySet()) {\n            buf.writeComponent(entry.getKey());\n\n            int slots = 0;\n            for (IItemHandlerModifiable handler : entry.getValue()) {\n                slots += handler.getSlots();\n            }\n\n            buf.writeInt(slots);\n        }\n    }\n\n    @Override\n    public Component getDisplayName() {\n        return Component.translatable(\"gui.refinedstorage.crafter_manager\");\n    }\n\n    @Nullable\n    @Override\n    public AbstractContainerMenu createMenu(int windowId, Inventory playerInventory, Player playerEntity) {\n        CrafterManagerContainerMenu container = new CrafterManagerContainerMenu(blockEntity, playerEntity, windowId);\n\n        container.setScreenInfoProvider(new EmptyScreenInfoProvider());\n        container.initSlotsServer();\n\n        return container;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/factory/CraftingMonitorContainerFactory.java",
    "content": "package com.refinedmods.refinedstorage.container.factory;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.container.CraftingMonitorContainerMenu;\nimport com.refinedmods.refinedstorage.blockentity.craftingmonitor.CraftingMonitorBlockEntity;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.neoforged.neoforge.network.IContainerFactory;\n\npublic class CraftingMonitorContainerFactory implements IContainerFactory<CraftingMonitorContainerMenu> {\n    @Override\n    public CraftingMonitorContainerMenu create(int windowId, Inventory inv, FriendlyByteBuf data) {\n        BlockPos pos = data.readBlockPos();\n\n        CraftingMonitorBlockEntity blockEntity = (CraftingMonitorBlockEntity) inv.player.level().getBlockEntity(pos);\n\n        return new CraftingMonitorContainerMenu(RSContainerMenus.CRAFTING_MONITOR.get(), blockEntity.getNode(), blockEntity, inv.player, windowId);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/factory/CraftingMonitorMenuProvider.java",
    "content": "package com.refinedmods.refinedstorage.container.factory;\n\nimport com.refinedmods.refinedstorage.container.CraftingMonitorContainerMenu;\nimport com.refinedmods.refinedstorage.blockentity.craftingmonitor.CraftingMonitorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.craftingmonitor.ICraftingMonitor;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.world.MenuProvider;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.minecraft.world.inventory.MenuType;\n\nimport javax.annotation.Nullable;\n\npublic class CraftingMonitorMenuProvider implements MenuProvider {\n    private final ICraftingMonitor craftingMonitor;\n    @Nullable\n    private final CraftingMonitorBlockEntity blockEntity;\n    private final MenuType<CraftingMonitorContainerMenu> containerType;\n\n    public CraftingMonitorMenuProvider(MenuType<CraftingMonitorContainerMenu> containerType, ICraftingMonitor craftingMonitor, @Nullable CraftingMonitorBlockEntity blockEntity) {\n        this.containerType = containerType;\n        this.craftingMonitor = craftingMonitor;\n        this.blockEntity = blockEntity;\n    }\n\n    @Override\n    public Component getDisplayName() {\n        return craftingMonitor.getTitle();\n    }\n\n    @Nullable\n    @Override\n    public AbstractContainerMenu createMenu(int windowId, Inventory playerInventory, Player playerEntity) {\n        return new CraftingMonitorContainerMenu(containerType, craftingMonitor, blockEntity, playerEntity, windowId);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/factory/GridContainerFactory.java",
    "content": "package com.refinedmods.refinedstorage.container.factory;\n\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport com.refinedmods.refinedstorage.blockentity.BaseBlockEntity;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.neoforged.neoforge.network.IContainerFactory;\nimport org.apache.commons.lang3.tuple.Pair;\n\npublic class GridContainerFactory implements IContainerFactory<GridContainerMenu> {\n    @Override\n    public GridContainerMenu create(int windowId, Inventory inv, FriendlyByteBuf data) {\n        ResourceLocation id = data.readResourceLocation();\n\n        BlockPos pos = null;\n        ItemStack stack = null;\n\n        if (data.readBoolean()) {\n            pos = data.readBlockPos();\n        }\n\n        if (data.readBoolean()) {\n            stack = data.readItem();\n        }\n\n        PlayerSlot slot = new PlayerSlot(data);\n\n        Pair<IGrid, BlockEntity> grid = API.instance().getGridManager().createGrid(id, inv.player, stack, pos, slot);\n\n        return new GridContainerMenu(grid.getLeft(), grid.getRight() instanceof BaseBlockEntity ? (BaseBlockEntity) grid.getRight() : null, inv.player, windowId);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/factory/GridMenuProvider.java",
    "content": "package com.refinedmods.refinedstorage.container.factory;\n\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport com.refinedmods.refinedstorage.screen.EmptyScreenInfoProvider;\nimport com.refinedmods.refinedstorage.blockentity.BaseBlockEntity;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.world.MenuProvider;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.minecraft.world.level.block.entity.BlockEntity;\n\nimport javax.annotation.Nullable;\n\npublic class GridMenuProvider implements MenuProvider {\n    private final IGrid grid;\n    private final BlockEntity blockEntity;\n\n    public GridMenuProvider(IGrid grid, BlockEntity blockEntity) {\n        this.grid = grid;\n        this.blockEntity = blockEntity;\n    }\n\n    @Override\n    public Component getDisplayName() {\n        return grid.getTitle();\n    }\n\n    @Nullable\n    @Override\n    public AbstractContainerMenu createMenu(int windowId, Inventory inv, Player player) {\n        GridContainerMenu c = new GridContainerMenu(grid, blockEntity instanceof BaseBlockEntity ? (BaseBlockEntity) blockEntity : null, player, windowId);\n\n        c.setScreenInfoProvider(new EmptyScreenInfoProvider());\n        c.initSlots();\n\n        return c;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/factory/WirelessCraftingMonitorContainerFactory.java",
    "content": "package com.refinedmods.refinedstorage.container.factory;\n\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.container.CraftingMonitorContainerMenu;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport com.refinedmods.refinedstorage.blockentity.craftingmonitor.WirelessCraftingMonitor;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.network.IContainerFactory;\n\npublic class WirelessCraftingMonitorContainerFactory implements IContainerFactory<CraftingMonitorContainerMenu> {\n    @Override\n    public CraftingMonitorContainerMenu create(int windowId, Inventory inv, FriendlyByteBuf data) {\n\n        PlayerSlot slot = new PlayerSlot(data);\n\n        ItemStack stack = slot.getStackFromSlot(inv.player);\n\n        WirelessCraftingMonitor wirelessCraftingMonitor = new WirelessCraftingMonitor(stack, null, slot);\n\n        return new CraftingMonitorContainerMenu(RSContainerMenus.WIRELESS_CRAFTING_MONITOR.get(), wirelessCraftingMonitor, null, inv.player, windowId);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/slot/BaseSlot.java",
    "content": "package com.refinedmods.refinedstorage.container.slot;\n\nimport java.util.function.BooleanSupplier;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport net.neoforged.neoforge.items.SlotItemHandler;\n\npublic class BaseSlot extends SlotItemHandler {\n    private BooleanSupplier enableHandler = () -> true;\n\n    public BaseSlot(IItemHandler itemHandler, int inventoryIndex, int x, int y) {\n        super(itemHandler, inventoryIndex, x, y);\n    }\n\n    public BaseSlot setEnableHandler(BooleanSupplier enableHandler) {\n        this.enableHandler = enableHandler;\n\n        return this;\n    }\n\n    @Override\n    public boolean isActive() {\n        return enableHandler.getAsBoolean();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/slot/CrafterManagerSlot.java",
    "content": "package com.refinedmods.refinedstorage.container.slot;\n\nimport com.refinedmods.refinedstorage.apiimpl.network.node.CrafterManagerNetworkNode;\nimport com.refinedmods.refinedstorage.screen.IScreenInfoProvider;\nimport net.neoforged.neoforge.items.IItemHandler;\n\npublic class CrafterManagerSlot extends BaseSlot {\n    private final boolean visible;\n    private final CrafterManagerNetworkNode crafterManager;\n    private final IScreenInfoProvider display;\n\n    public CrafterManagerSlot(IItemHandler itemHandler, int inventoryIndex, int x, int y, boolean visible, IScreenInfoProvider display, CrafterManagerNetworkNode crafterManager) {\n        super(itemHandler, inventoryIndex, x, y);\n\n        this.visible = visible;\n        this.display = display;\n        this.crafterManager = crafterManager;\n    }\n\n    @Override\n    public boolean isActive() {\n        return y >= display.getTopHeight() && y < display.getTopHeight() + 18 * display.getVisibleRows() && visible && crafterManager.isActiveOnClient();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/slot/DisabledSlot.java",
    "content": "package com.refinedmods.refinedstorage.container.slot;\n\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport javax.annotation.Nonnull;\n\npublic class DisabledSlot extends BaseSlot {\n    public DisabledSlot(IItemHandler itemHandler, int inventoryIndex, int x, int y) {\n        super(itemHandler, inventoryIndex, x, y);\n    }\n\n    @Override\n    public boolean mayPlace(@Nonnull ItemStack stack) {\n        return false;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/slot/OutputSlot.java",
    "content": "package com.refinedmods.refinedstorage.container.slot;\n\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport javax.annotation.Nonnull;\n\npublic class OutputSlot extends BaseSlot {\n    public OutputSlot(IItemHandler inventory, int inventoryIndex, int x, int y) {\n        super(inventory, inventoryIndex, x, y);\n    }\n\n    @Override\n    public boolean mayPlace(@Nonnull ItemStack stack) {\n        return false;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/slot/filter/DisabledFluidFilterSlot.java",
    "content": "package com.refinedmods.refinedstorage.container.slot.filter;\n\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport net.minecraft.world.item.ItemStack;\n\nimport javax.annotation.Nonnull;\n\npublic class DisabledFluidFilterSlot extends FluidFilterSlot {\n    public DisabledFluidFilterSlot(FluidInventory inventory, int inventoryIndex, int x, int y, int flags) {\n        super(inventory, inventoryIndex, x, y, flags);\n    }\n\n    public DisabledFluidFilterSlot(FluidInventory inventory, int inventoryIndex, int x, int y) {\n        super(inventory, inventoryIndex, x, y);\n    }\n\n    @Override\n    public void onContainerClicked(@Nonnull ItemStack stack) {\n        // NO OP\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/slot/filter/FilterSlot.java",
    "content": "package com.refinedmods.refinedstorage.container.slot.filter;\n\nimport com.refinedmods.refinedstorage.container.slot.BaseSlot;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.BlockItem;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport javax.annotation.Nonnull;\n\npublic class FilterSlot extends BaseSlot {\n    public static final int FILTER_ALLOW_SIZE = 1;\n    public static final int FILTER_ALLOW_BLOCKS = 2;\n    public static final int FILTER_ALLOW_ALTERNATIVES = 4;\n\n    private final int flags;\n\n    public FilterSlot(IItemHandler handler, int inventoryIndex, int x, int y, int flags) {\n        super(handler, inventoryIndex, x, y);\n\n        this.flags = flags;\n    }\n\n    public FilterSlot(IItemHandler handler, int inventoryIndex, int x, int y) {\n        this(handler, inventoryIndex, x, y, 0);\n    }\n\n    @Override\n    public boolean mayPlace(@Nonnull ItemStack stack) {\n        if (super.mayPlace(stack)) {\n            if (isBlockAllowed()) {\n                return stack.getItem() instanceof BlockItem;\n            }\n\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public void set(@Nonnull ItemStack stack) {\n        if (!stack.isEmpty() && !isSizeAllowed()) {\n            stack.setCount(1);\n        }\n\n        super.set(stack);\n    }\n\n    @Override\n    public boolean mayPickup(Player playerIn) {\n        return false;\n    }\n\n    public boolean isSizeAllowed() {\n        return (flags & FILTER_ALLOW_SIZE) == FILTER_ALLOW_SIZE;\n    }\n\n    public boolean isBlockAllowed() {\n        return (flags & FILTER_ALLOW_BLOCKS) == FILTER_ALLOW_BLOCKS;\n    }\n\n    public boolean isAlternativesAllowed() {\n        return (flags & FILTER_ALLOW_ALTERNATIVES) == FILTER_ALLOW_ALTERNATIVES;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/slot/filter/FluidFilterSlot.java",
    "content": "package com.refinedmods.refinedstorage.container.slot.filter;\n\nimport com.refinedmods.refinedstorage.container.slot.BaseSlot;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.ItemStackHandler;\nimport javax.annotation.Nonnull;\n\npublic class FluidFilterSlot extends BaseSlot {\n    public static final int FILTER_ALLOW_SIZE = 1;\n    public static final int FILTER_ALLOW_ALTERNATIVES = 2;\n\n    private final int flags;\n    private final FluidInventory fluidInventory;\n\n    public FluidFilterSlot(FluidInventory inventory, int inventoryIndex, int x, int y, int flags) {\n        super(new ItemStackHandler(inventory.getSlots()), inventoryIndex, x, y);\n\n        this.flags = flags;\n        this.fluidInventory = inventory;\n    }\n\n    public FluidFilterSlot(FluidInventory inventory, int inventoryIndex, int x, int y) {\n        this(inventory, inventoryIndex, x, y, 0);\n    }\n\n    @Override\n    public boolean mayPlace(@Nonnull ItemStack stack) {\n        return false;\n    }\n\n    public void onContainerClicked(@Nonnull ItemStack stack) {\n        fluidInventory.setFluid(getSlotIndex(), StackUtils.getFluid(stack, true).getValue());\n    }\n\n    @Override\n    public boolean mayPickup(Player playerIn) {\n        return false;\n    }\n\n    public boolean isSizeAllowed() {\n        return (flags & FILTER_ALLOW_SIZE) == FILTER_ALLOW_SIZE;\n    }\n\n    public boolean isAlternativesAllowed() {\n        return (flags & FILTER_ALLOW_ALTERNATIVES) == FILTER_ALLOW_ALTERNATIVES;\n    }\n\n    public FluidInventory getFluidInventory() {\n        return fluidInventory;\n    }\n\n    // not overriding getHasStack as we do the tooltips ourselves\n    public boolean hasStack() {\n        return !fluidInventory.getFluid(getSlotIndex()).isEmpty();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/slot/grid/CraftingGridSlot.java",
    "content": "package com.refinedmods.refinedstorage.container.slot.grid;\n\nimport net.minecraft.world.Container;\nimport net.minecraft.world.inventory.Slot;\n\npublic class CraftingGridSlot extends Slot {\n    public CraftingGridSlot(Container inventory, int inventoryIndex, int x, int y) {\n        super(inventory, inventoryIndex, x, y);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/slot/grid/ResultCraftingGridSlot.java",
    "content": "package com.refinedmods.refinedstorage.container.slot.grid;\n\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.ResultSlot;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.common.CommonHooks;\nimport net.neoforged.neoforge.event.EventHooks;\nimport javax.annotation.Nonnull;\n\npublic class ResultCraftingGridSlot extends ResultSlot {\n    private final IGrid grid;\n\n    public ResultCraftingGridSlot(Player player, IGrid grid, int inventoryIndex, int x, int y) {\n        super(player, grid.getCraftingMatrix(), grid.getCraftingResult(), inventoryIndex, x, y);\n\n        this.grid = grid;\n    }\n\n    // @Volatile: Overriding logic from the super onTake method for Grid behaviors like refilling stacks from the network\n    @Override\n    public void onTake(Player player, @Nonnull ItemStack stack) {\n        checkTakeAchievements(stack);\n        CommonHooks.setCraftingPlayer(player);\n\n        if (!player.getCommandSenderWorld().isClientSide) {\n            grid.onCrafted(player, null, null);\n        }\n\n        EventHooks.firePlayerCraftingEvent(player, stack.copy(), grid.getCraftingMatrix());\n        CommonHooks.setCraftingPlayer(null);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/slot/legacy/LegacyBaseSlot.java",
    "content": "package com.refinedmods.refinedstorage.container.slot.legacy;\n\nimport net.minecraft.world.Container;\nimport net.minecraft.world.inventory.Slot;\n\nimport java.util.function.BooleanSupplier;\n\npublic class LegacyBaseSlot extends Slot {\n    private BooleanSupplier enableHandler = () -> true;\n\n    public LegacyBaseSlot(Container inventory, int inventoryIndex, int x, int y) {\n        super(inventory, inventoryIndex, x, y);\n    }\n\n    public LegacyBaseSlot setEnableHandler(BooleanSupplier enableHandler) {\n        this.enableHandler = enableHandler;\n\n        return this;\n    }\n\n    @Override\n    public boolean isActive() {\n        return enableHandler.getAsBoolean();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/slot/legacy/LegacyDisabledSlot.java",
    "content": "package com.refinedmods.refinedstorage.container.slot.legacy;\n\nimport net.minecraft.world.Container;\nimport net.minecraft.world.item.ItemStack;\n\nimport javax.annotation.Nonnull;\n\npublic class LegacyDisabledSlot extends LegacyBaseSlot {\n    public LegacyDisabledSlot(Container inventory, int inventoryIndex, int x, int y) {\n        super(inventory, inventoryIndex, x, y);\n    }\n\n    @Override\n    public boolean mayPlace(@Nonnull ItemStack stack) {\n        return false;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/slot/legacy/LegacyFilterSlot.java",
    "content": "package com.refinedmods.refinedstorage.container.slot.legacy;\n\n\nimport net.minecraft.world.Container;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\n\nimport javax.annotation.Nonnull;\n\npublic class LegacyFilterSlot extends LegacyBaseSlot {\n    public LegacyFilterSlot(Container inventory, int inventoryIndex, int x, int y) {\n        super(inventory, inventoryIndex, x, y);\n    }\n\n    @Override\n    public boolean mayPickup(Player player) {\n        return false;\n    }\n\n    @Override\n    public boolean mayPlace(ItemStack stack) {\n        return true;\n    }\n\n    @Override\n    public void set(@Nonnull ItemStack stack) {\n        if (!stack.isEmpty()) {\n            stack.setCount(1);\n        }\n\n        super.set(stack);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/transfer/FilterInventoryWrapper.java",
    "content": "package com.refinedmods.refinedstorage.container.transfer;\n\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport java.util.function.Supplier;\n\nclass FilterInventoryWrapper implements IInventoryWrapper {\n    private final ItemFilterInventoryWrapper item;\n    private final FluidFilterInventoryWrapper fluid;\n    private final Supplier<Integer> typeGetter;\n\n    FilterInventoryWrapper(IItemHandlerModifiable itemTo, FluidInventory fluidTo, Supplier<Integer> typeGetter) {\n        this.item = new ItemFilterInventoryWrapper(itemTo);\n        this.fluid = new FluidFilterInventoryWrapper(fluidTo);\n        this.typeGetter = typeGetter;\n    }\n\n    @Override\n    public InsertionResult insert(ItemStack stack) {\n        return typeGetter.get() == IType.ITEMS ? item.insert(stack) : fluid.insert(stack);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/transfer/FluidFilterInventoryWrapper.java",
    "content": "package com.refinedmods.refinedstorage.container.transfer;\n\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.fluids.FluidType;\n\nclass FluidFilterInventoryWrapper implements IInventoryWrapper {\n    private final FluidInventory filterInv;\n\n    FluidFilterInventoryWrapper(FluidInventory filterInv) {\n        this.filterInv = filterInv;\n    }\n\n    @Override\n    public InsertionResult insert(ItemStack stack) {\n        InsertionResult stop = new InsertionResult(InsertionResultType.STOP);\n\n        FluidStack fluidInContainer = StackUtils.getFluid(stack, true).getValue();\n\n        if (fluidInContainer.isEmpty()) {\n            return stop;\n        }\n\n        for (FluidStack fluid : filterInv.getFluids()) {\n            if (API.instance().getComparer().isEqual(fluidInContainer, fluid, IComparer.COMPARE_NBT)) {\n                return stop;\n            }\n        }\n\n        for (int i = 0; i < filterInv.getSlots(); ++i) {\n            if (filterInv.getFluid(i).isEmpty()) {\n                filterInv.setFluid(i, StackUtils.copy(fluidInContainer, FluidType.BUCKET_VOLUME));\n\n                return stop;\n            }\n        }\n\n        return stop;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/transfer/IInventoryWrapper.java",
    "content": "package com.refinedmods.refinedstorage.container.transfer;\n\nimport net.minecraft.world.item.ItemStack;\n\ninterface IInventoryWrapper {\n    InsertionResult insert(ItemStack stack);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/transfer/InsertionResult.java",
    "content": "package com.refinedmods.refinedstorage.container.transfer;\n\nimport net.minecraft.world.item.ItemStack;\n\nclass InsertionResult {\n    private final InsertionResultType type;\n    private ItemStack value;\n\n    InsertionResult(ItemStack value) {\n        this.type = InsertionResultType.CONTINUE_IF_POSSIBLE;\n        this.value = value;\n    }\n\n    InsertionResult(InsertionResultType type) {\n        this.type = type;\n    }\n\n    public InsertionResultType getType() {\n        return type;\n    }\n\n    public ItemStack getValue() {\n        return value;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/transfer/InsertionResultType.java",
    "content": "package com.refinedmods.refinedstorage.container.transfer;\n\nenum InsertionResultType {\n    CONTINUE_IF_POSSIBLE,\n    STOP\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/transfer/InventoryInventoryWrapper.java",
    "content": "package com.refinedmods.refinedstorage.container.transfer;\n\nimport net.minecraft.world.Container;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\nimport net.neoforged.neoforge.items.wrapper.InvWrapper;\nimport net.neoforged.neoforge.items.wrapper.RangedWrapper;\nimport java.util.Objects;\n\nclass InventoryInventoryWrapper implements IInventoryWrapper {\n    private final Container inventory;\n    private final IItemHandler wrapper;\n\n    InventoryInventoryWrapper(Container inventory) {\n        this.inventory = inventory;\n\n        if (inventory instanceof Inventory) {\n            // Don't use PlayerMainInvWrapper to avoid stack animations.\n            this.wrapper = new RangedWrapper(new InvWrapper(inventory), 0, ((Inventory) inventory).items.size());\n        } else {\n            this.wrapper = new InvWrapper(inventory);\n        }\n    }\n\n    @Override\n    public InsertionResult insert(ItemStack stack) {\n        return new InsertionResult(ItemHandlerHelper.insertItem(wrapper, stack, false));\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        InventoryInventoryWrapper that = (InventoryInventoryWrapper) o;\n\n        return Objects.equals(inventory, that.inventory);\n    }\n\n    @Override\n    public int hashCode() {\n        return Objects.hash(inventory);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/transfer/ItemFilterInventoryWrapper.java",
    "content": "package com.refinedmods.refinedstorage.container.transfer;\n\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\n\nclass ItemFilterInventoryWrapper implements IInventoryWrapper {\n    private final IItemHandlerModifiable filterInv;\n\n    ItemFilterInventoryWrapper(IItemHandlerModifiable filterInv) {\n        this.filterInv = filterInv;\n    }\n\n    @Override\n    public InsertionResult insert(ItemStack stack) {\n        InsertionResult stop = new InsertionResult(InsertionResultType.STOP);\n\n        for (int i = 0; i < filterInv.getSlots(); ++i) {\n            if (API.instance().getComparer().isEqualNoQuantity(filterInv.getStackInSlot(i), stack)) {\n                return stop;\n            }\n        }\n\n        for (int i = 0; i < filterInv.getSlots(); ++i) {\n            if (filterInv.getStackInSlot(i).isEmpty()) {\n                filterInv.setStackInSlot(i, ItemHandlerHelper.copyStackWithSize(stack, 1));\n\n                break;\n            }\n        }\n\n        return stop;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/transfer/ItemHandlerInventoryWrapper.java",
    "content": "package com.refinedmods.refinedstorage.container.transfer;\n\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\nimport java.util.Objects;\n\nclass ItemHandlerInventoryWrapper implements IInventoryWrapper {\n    private final IItemHandler handler;\n\n    ItemHandlerInventoryWrapper(IItemHandler handler) {\n        this.handler = handler;\n    }\n\n    @Override\n    public InsertionResult insert(ItemStack stack) {\n        return new InsertionResult(ItemHandlerHelper.insertItem(handler, stack, false));\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        ItemHandlerInventoryWrapper that = (ItemHandlerInventoryWrapper) o;\n\n        return Objects.equals(handler, that.handler);\n    }\n\n    @Override\n    public int hashCode() {\n        return Objects.hash(handler);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/container/transfer/TransferManager.java",
    "content": "package com.refinedmods.refinedstorage.container.transfer;\n\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport net.minecraft.world.Container;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.minecraft.world.inventory.Slot;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport net.neoforged.neoforge.items.SlotItemHandler;\nimport javax.annotation.Nullable;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.function.Function;\nimport java.util.function.Supplier;\n\npublic class TransferManager {\n    private final Map<IInventoryWrapper, List<IInventoryWrapper>> fromToMap = new HashMap<>();\n    private final AbstractContainerMenu container;\n\n    @Nullable\n    private Function<Integer, ItemStack> notFoundHandler;\n\n    public TransferManager(AbstractContainerMenu container) {\n        this.container = container;\n    }\n\n    public void clearTransfers() {\n        this.fromToMap.clear();\n    }\n\n    public void setNotFoundHandler(@Nullable Function<Integer, ItemStack> handler) {\n        this.notFoundHandler = handler;\n    }\n\n    public void addTransfer(Container from, IItemHandler to) {\n        addTransfer(new InventoryInventoryWrapper(from), new ItemHandlerInventoryWrapper(to));\n    }\n\n    public void addTransfer(Container from, Container to) {\n        addTransfer(new InventoryInventoryWrapper(from), new InventoryInventoryWrapper(to));\n    }\n\n    public void addFilterTransfer(Container from, IItemHandlerModifiable itemTo, FluidInventory fluidTo, Supplier<Integer> typeGetter) {\n        addTransfer(new InventoryInventoryWrapper(from), new FilterInventoryWrapper(itemTo, fluidTo, typeGetter));\n    }\n\n    public void addItemFilterTransfer(Container from, IItemHandlerModifiable to) {\n        addTransfer(new InventoryInventoryWrapper(from), new ItemFilterInventoryWrapper(to));\n    }\n\n    public void addFluidFilterTransfer(Container from, FluidInventory to) {\n        addTransfer(new InventoryInventoryWrapper(from), new FluidFilterInventoryWrapper(to));\n    }\n\n    public void addTransfer(IItemHandler from, Container to) {\n        addTransfer(new ItemHandlerInventoryWrapper(from), new InventoryInventoryWrapper(to));\n    }\n\n    public void addBiTransfer(Container from, IItemHandler to) {\n        addTransfer(from, to);\n        addTransfer(to, from);\n    }\n\n    private void addTransfer(IInventoryWrapper from, IInventoryWrapper to) {\n        List<IInventoryWrapper> toList = fromToMap.computeIfAbsent(from, k -> new LinkedList<>());\n\n        toList.add(to);\n    }\n\n    public ItemStack transfer(int index) {\n        Slot slot = container.getSlot(index);\n\n        IInventoryWrapper key;\n        if (slot instanceof SlotItemHandler) {\n            key = new ItemHandlerInventoryWrapper(((SlotItemHandler) slot).getItemHandler());\n        } else {\n            key = new InventoryInventoryWrapper(slot.container);\n        }\n\n        List<IInventoryWrapper> toList = fromToMap.get(key);\n\n        if (toList != null) {\n            ItemStack initial = slot.getItem().copy();\n\n            ItemStack remainder = slot.getItem();\n\n            for (IInventoryWrapper to : toList) {\n                InsertionResult result = to.insert(remainder);\n\n                if (result.getType() == InsertionResultType.STOP) {\n                    break;\n                } else if (result.getType() == InsertionResultType.CONTINUE_IF_POSSIBLE) {\n                    remainder = result.getValue();\n\n                    if (remainder.isEmpty()) {\n                        break;\n                    }\n                }\n            }\n\n            slot.set(remainder);\n            slot.setChanged();\n\n            if (API.instance().getComparer().isEqual(remainder, initial) && notFoundHandler != null) {\n                return notFoundHandler.apply(index);\n            }\n        } else if (notFoundHandler != null) {\n            return notFoundHandler.apply(index);\n        }\n\n        return ItemStack.EMPTY;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/datageneration/BlockEntityTagGenerator.java",
    "content": "package com.refinedmods.refinedstorage.datageneration;\n\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport net.minecraft.core.HolderLookup;\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.core.registries.Registries;\nimport net.minecraft.data.PackOutput;\nimport net.minecraft.data.tags.TagsProvider;\nimport net.minecraft.resources.ResourceKey;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.tags.TagKey;\nimport net.minecraft.world.level.block.entity.BlockEntityType;\nimport net.neoforged.neoforge.common.data.ExistingFileHelper;\nimport java.util.concurrent.CompletableFuture;\n\npublic class BlockEntityTagGenerator extends TagsProvider<BlockEntityType<?>> {\n    public BlockEntityTagGenerator(PackOutput output, String modId, CompletableFuture<HolderLookup.Provider> provider, ExistingFileHelper existingFileHelper) {\n        super(output, Registries.BLOCK_ENTITY_TYPE, provider, modId, existingFileHelper);\n    }\n\n    @Override\n    protected void addTags(HolderLookup.Provider provider) {\n        TagAppender<BlockEntityType<?>> packingTapeBlacklist = tag(\n            TagKey.create(Registries.BLOCK_ENTITY_TYPE, new ResourceLocation(\"packingtape:blacklist/problematic\"))\n        );\n        packingTapeBlacklist.add(\n            resourceKey(RSBlockEntities.CONTROLLER.get()),\n            resourceKey(RSBlockEntities.CREATIVE_CONTROLLER.get()),\n            resourceKey(RSBlockEntities.DETECTOR.get()),\n            resourceKey(RSBlockEntities.DISK_DRIVE.get()),\n            resourceKey(RSBlockEntities.EXPORTER.get()),\n            resourceKey(RSBlockEntities.EXTERNAL_STORAGE.get()),\n            resourceKey(RSBlockEntities.GRID.get()),\n            resourceKey(RSBlockEntities.CRAFTING_GRID.get()),\n            resourceKey(RSBlockEntities.PATTERN_GRID.get()),\n            resourceKey(RSBlockEntities.FLUID_GRID.get()),\n            resourceKey(RSBlockEntities.IMPORTER.get()),\n            resourceKey(RSBlockEntities.NETWORK_TRANSMITTER.get()),\n            resourceKey(RSBlockEntities.NETWORK_RECEIVER.get()),\n            resourceKey(RSBlockEntities.RELAY.get()),\n            resourceKey(RSBlockEntities.CABLE.get()),\n            resourceKey(RSBlockEntities.ONE_K_STORAGE_BLOCK.get()),\n            resourceKey(RSBlockEntities.FOUR_K_STORAGE_BLOCK.get()),\n            resourceKey(RSBlockEntities.SIXTEEN_K_STORAGE_BLOCK.get()),\n            resourceKey(RSBlockEntities.SIXTY_FOUR_K_STORAGE_BLOCK.get()),\n            resourceKey(RSBlockEntities.CREATIVE_STORAGE_BLOCK.get()),\n            resourceKey(RSBlockEntities.SIXTY_FOUR_K_FLUID_STORAGE_BLOCK.get()),\n            resourceKey(RSBlockEntities.TWO_HUNDRED_FIFTY_SIX_K_FLUID_STORAGE_BLOCK.get()),\n            resourceKey(RSBlockEntities.THOUSAND_TWENTY_FOUR_K_FLUID_STORAGE_BLOCK.get()),\n            resourceKey(RSBlockEntities.FOUR_THOUSAND_NINETY_SIX_K_FLUID_STORAGE_BLOCK.get()),\n            resourceKey(RSBlockEntities.CREATIVE_FLUID_STORAGE_BLOCK.get()),\n            resourceKey(RSBlockEntities.SECURITY_MANAGER.get()),\n            resourceKey(RSBlockEntities.INTERFACE.get()),\n            resourceKey(RSBlockEntities.FLUID_INTERFACE.get()),\n            resourceKey(RSBlockEntities.WIRELESS_TRANSMITTER.get()),\n            resourceKey(RSBlockEntities.STORAGE_MONITOR.get()),\n            resourceKey(RSBlockEntities.CONSTRUCTOR.get()),\n            resourceKey(RSBlockEntities.DESTRUCTOR.get()),\n            resourceKey(RSBlockEntities.DISK_MANIPULATOR.get()),\n            resourceKey(RSBlockEntities.PORTABLE_GRID.get()),\n            resourceKey(RSBlockEntities.CREATIVE_PORTABLE_GRID.get()),\n            resourceKey(RSBlockEntities.CRAFTER.get()),\n            resourceKey(RSBlockEntities.CRAFTER_MANAGER.get()),\n            resourceKey(RSBlockEntities.CRAFTING_MONITOR.get())\n        );\n    }\n\n    private ResourceKey<BlockEntityType<?>> resourceKey(BlockEntityType<?> type) {\n        return BuiltInRegistries.BLOCK_ENTITY_TYPE.getResourceKey(type).get();\n    }\n\n    @Override\n    public String getName() {\n        return \"Block Entity Type Tags\";\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/datageneration/BlockModelGenerator.java",
    "content": "package com.refinedmods.refinedstorage.datageneration;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.block.ControllerBlock;\nimport com.refinedmods.refinedstorage.block.DetectorBlock;\nimport com.refinedmods.refinedstorage.block.NetworkNodeBlock;\nimport com.refinedmods.refinedstorage.util.BlockColorMap;\nimport com.refinedmods.refinedstorage.util.ColorMap;\n\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.data.PackOutput;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.block.Block;\nimport net.neoforged.neoforge.client.model.generators.BlockStateProvider;\nimport net.neoforged.neoforge.client.model.generators.ModelFile;\nimport net.neoforged.neoforge.common.data.ExistingFileHelper;\n\npublic class BlockModelGenerator extends BlockStateProvider {\n    private static final ResourceLocation BOTTOM = new ResourceLocation(RS.ID, \"block/bottom\");\n\n    private final BlockModels models;\n\n    public BlockModelGenerator(PackOutput output, String id, ExistingFileHelper existingFileHelper) {\n        super(output, id, existingFileHelper);\n        models = new BlockModels(this);\n    }\n\n    @Override\n    protected void registerStatesAndModels() {\n        genNorthCutoutModels(RSBlocks.GRID, false);\n        genNorthCutoutModels(RSBlocks.CRAFTING_GRID, false);\n        genNorthCutoutModels(RSBlocks.PATTERN_GRID, false);\n        genNorthCutoutModels(RSBlocks.FLUID_GRID, false);\n        genNorthCutoutModels(RSBlocks.CRAFTING_MONITOR, false);\n        genNorthCutoutModels(RSBlocks.CRAFTER_MANAGER, false);\n        genNorthCutoutModels(RSBlocks.DISK_MANIPULATOR, true);\n        genControllerModels(RSBlocks.CONTROLLER);\n        genControllerModels(RSBlocks.CREATIVE_CONTROLLER);\n        genCrafterModels();\n        genCubeAllCutoutModels(RSBlocks.RELAY);\n        genCubeAllCutoutModels(RSBlocks.NETWORK_TRANSMITTER);\n        genCubeAllCutoutModels(RSBlocks.NETWORK_RECEIVER);\n        genSecurityManagerModels();\n        genDetectorModels();\n        genWirelessTransmitterModels();\n    }\n\n    private void genWirelessTransmitterModels() {\n        RSBlocks.WIRELESS_TRANSMITTER.forEach((color, registryObject) -> {\n            Block block = registryObject.get();\n            String folderName = RSBlocks.WIRELESS_TRANSMITTER.get(ColorMap.DEFAULT_COLOR).getId().getPath();\n\n            models.wirelessTransmitterBlock(block, state -> {\n                if (Boolean.FALSE.equals(state.getValue(NetworkNodeBlock.CONNECTED))) {\n                    return models.createWirelessTransmitterNonEmissiveModel(\n                            \"block/\" + folderName + \"/disconnected\",\n                            resourceLocation(folderName, \"cutouts/disconnected\")\n                    );\n                } else {\n                    ModelFile model = models.createWirelessTransmitterModel(\n                            \"block/\" + folderName + \"/\" + color,\n                            resourceLocation(folderName, \"cutouts/\" + color)\n                    );\n\n                    simpleBlockItem(block, model);\n                    return model;\n                }\n            }, 0);\n        });\n    }\n\n    private void genDetectorModels() {\n        RSBlocks.DETECTOR.forEach((color, registryObject) -> {\n            Block block = registryObject.get();\n            String folderName = RSBlocks.DETECTOR.get(ColorMap.DEFAULT_COLOR).getId().getPath();\n\n            models.simpleBlockStateModel(block, state -> {\n                if (Boolean.FALSE.equals(state.getValue(DetectorBlock.POWERED))) {\n                    return models.createDetectorNonEmissiveModel(\n                            \"block/\" + folderName + \"/off\",\n                            resourceLocation(folderName, \"cutouts/off\")\n                    );\n                } else {\n                    ModelFile model = models.createDetectorModel(\n                            \"block/\" + folderName + \"/\" + color,\n                            resourceLocation(folderName, \"cutouts/\" + color)\n                    );\n\n                    simpleBlockItem(block, model);\n                    return model;\n                }\n            });\n        });\n    }\n\n    private void genSecurityManagerModels() {\n        RSBlocks.SECURITY_MANAGER.forEach((color, registryObject) -> {\n            Block block = registryObject.get();\n            String folderName = RSBlocks.SECURITY_MANAGER.get(ColorMap.DEFAULT_COLOR).getId().getPath();\n\n            models.horizontalRSBlock(block, state -> {\n                if (Boolean.FALSE.equals(state.getValue(NetworkNodeBlock.CONNECTED))) {\n                    return models.createCubeCutoutNonEmissiveModel(\n                            \"block/\" + folderName + \"/disconnected\",\n                            BOTTOM,\n                            BOTTOM,\n                            resourceLocation(folderName, \"top\"),\n                            resourceLocation(folderName, \"cutouts/top_disconnected\"),\n                            resourceLocation(folderName, \"right\"),\n                            resourceLocation(folderName, \"cutouts/right_disconnected\"),\n                            resourceLocation(folderName, \"left\"),\n                            resourceLocation(folderName, \"cutouts/left_disconnected\"),\n                            resourceLocation(folderName, \"front\"),\n                            resourceLocation(folderName, \"cutouts/front_disconnected\"),\n                            resourceLocation(folderName, \"back\"),\n                            resourceLocation(folderName, \"cutouts/back_disconnected\")\n                    );\n                } else {\n                    ModelFile model = models.createCubeCutoutModel(\n                            \"block/\" + folderName + \"/\" + color,\n                            BOTTOM,\n                            BOTTOM,\n                            resourceLocation(folderName, \"top\"),\n                            resourceLocation(folderName, \"cutouts/top\" + \"_\" + color),\n                            resourceLocation(folderName, \"right\"),\n                            resourceLocation(folderName, \"cutouts/right\" + \"_\" + color),\n                            resourceLocation(folderName, \"left\"),\n                            resourceLocation(folderName, \"cutouts/left\" + \"_\" + color),\n                            resourceLocation(folderName, \"front\"),\n                            resourceLocation(folderName, \"cutouts/front\" + \"_\" + color),\n                            resourceLocation(folderName, \"back\"),\n                            resourceLocation(folderName, \"cutouts/back\" + \"_\" + color)\n                    );\n\n                    simpleBlockItem(block, model);\n                    return model;\n                }\n            }, 180);\n        });\n    }\n\n    private <T extends Block> void genCubeAllCutoutModels(BlockColorMap<T> blockMap) {\n        blockMap.forEach((color, registryObject) -> {\n            Block block = registryObject.get();\n            String folderName = blockMap.get(ColorMap.DEFAULT_COLOR).getId().getPath();\n\n            models.simpleBlockStateModel(block, state -> {\n                if (Boolean.FALSE.equals(state.getValue(NetworkNodeBlock.CONNECTED))) {\n                    return models.createCubeAllCutoutNonEmissiveModel(\n                            \"block/\" + folderName + \"/disconnected\",\n                            resourceLocation(folderName, folderName),\n                            resourceLocation(folderName, folderName),\n                            resourceLocation(folderName, \"cutouts/disconnected\")\n                    );\n                } else {\n                    ModelFile model = models.createCubeAllCutoutModel(\n                            \"block/\" + folderName + \"/\" + color,\n                            resourceLocation(folderName, folderName),\n                            resourceLocation(folderName, folderName),\n                            resourceLocation(folderName, \"cutouts/\" + color)\n                    );\n\n                    simpleBlockItem(block, model);\n                    return model;\n                }\n            });\n        });\n    }\n\n    private void genCrafterModels() {\n        RSBlocks.CRAFTER.forEach((color, registryObject) -> {\n            Block block = registryObject.get();\n            String folderName = RSBlocks.CRAFTER.get(ColorMap.DEFAULT_COLOR).getId().getPath();\n\n            models.anyDirectionalRSBlock(block, state -> {\n                if (Boolean.FALSE.equals(state.getValue(NetworkNodeBlock.CONNECTED))) {\n                    return models.createCubeCutoutNonEmissiveModel(\n                            \"block/\" + folderName + \"/disconnected\",\n                            BOTTOM,\n                            BOTTOM,\n                            resourceLocation(folderName, \"top\"),\n                            resourceLocation(folderName, \"cutouts/top_disconnected\"),\n                            resourceLocation(folderName, \"side\"),\n                            resourceLocation(folderName, \"cutouts/side_disconnected\"),\n                            resourceLocation(folderName, \"side\"),\n                            resourceLocation(folderName, \"cutouts/side_disconnected\"),\n                            resourceLocation(folderName, \"side\"),\n                            resourceLocation(folderName, \"cutouts/side_disconnected\"),\n                            resourceLocation(folderName, \"side\"),\n                            resourceLocation(folderName, \"cutouts/side_disconnected\")\n                    );\n                } else {\n                    ModelFile model = models.createCubeCutoutModel(\n                            \"block/\" + folderName + \"/\" + color,\n                            BOTTOM,\n                            BOTTOM,\n                            resourceLocation(folderName, \"top\"),\n                            resourceLocation(folderName, \"cutouts/top_\" + color),\n                            resourceLocation(folderName, \"side\"),\n                            resourceLocation(folderName, \"cutouts/side_\" + color),\n                            resourceLocation(folderName, \"side\"),\n                            resourceLocation(folderName, \"cutouts/side_\" + color),\n                            resourceLocation(folderName, \"side\"),\n                            resourceLocation(folderName, \"cutouts/side_\" + color),\n                            resourceLocation(folderName, \"side\"),\n                            resourceLocation(folderName, \"cutouts/side_\" + color)\n                    );\n\n                    simpleBlockItem(block, model);\n                    return model;\n                }\n            }, 180);\n        });\n    }\n\n    private <T extends Block> void genControllerModels(BlockColorMap<T> blockMap) {\n        blockMap.forEach((color, registryObject) -> {\n            Block block = registryObject.get();\n            String folderName = RSBlocks.CONTROLLER.get(ColorMap.DEFAULT_COLOR).getId().getPath();\n\n            models.simpleBlockStateModel(block, state -> {\n                if (state.getValue(ControllerBlock.ENERGY_TYPE).equals(ControllerBlock.EnergyType.OFF)) {\n                    return models.createCubeAllCutoutNonEmissiveModel(\n                            \"block/\" + folderName + \"/off\",\n                            resourceLocation(folderName, \"off\"),\n                            resourceLocation(folderName, \"off\"),\n                            resourceLocation(folderName, \"cutouts/off\")\n                    );\n                } else if (state.getValue(ControllerBlock.ENERGY_TYPE).equals(ControllerBlock.EnergyType.NEARLY_OFF)) {\n                    return models.createControllerNearlyCutoutModel(\n                            \"block/\" + folderName + \"/nearly_off\",\n                            resourceLocation(folderName, \"off\"),\n                            resourceLocation(folderName, \"on\"),\n                            resourceLocation(folderName, \"cutouts/nearly_off\"),\n                            resourceLocation(folderName, \"cutouts/nearly_off_gray\")\n                    );\n                } else if (state.getValue(ControllerBlock.ENERGY_TYPE).equals(ControllerBlock.EnergyType.NEARLY_ON)) {\n                    return models.createControllerNearlyCutoutModel(\n                            \"block/\" + folderName + \"/nearly_on\",\n                            resourceLocation(folderName, \"off\"),\n                            resourceLocation(folderName, \"on\"),\n                            resourceLocation(folderName, \"cutouts/nearly_on\"),\n                            resourceLocation(folderName, \"cutouts/nearly_on_gray\")\n                    );\n                } else {\n                    ModelFile model = models.createCubeAllCutoutModel(\n                            \"block/\" + folderName + \"/\" + color,\n                            resourceLocation(folderName, \"off\"),\n                            resourceLocation(folderName, \"on\"),\n                            resourceLocation(folderName, \"cutouts/\" + color)\n                    );\n\n                    final ResourceLocation energyType = new ResourceLocation(RS.ID, \"energy_type\");\n                    itemModels().getBuilder(BuiltInRegistries.BLOCK.getKey(block).getPath())\n                            .override()\n                            .predicate(energyType, 0)\n                            .model(models().getExistingFile(\n                                    new ResourceLocation(RS.ID, \"block/\" + folderName + \"/off\")\n                            )).end().override()\n                            .predicate(energyType, 1)\n                            .model(models().getExistingFile(\n                                    new ResourceLocation(RS.ID, \"block/\" + folderName + \"/nearly_off\")\n                            )).end().override()\n                            .predicate(energyType, 2)\n                            .model(models().getExistingFile(\n                                    new ResourceLocation(RS.ID, \"block/\" + folderName + \"/nearly_on\")\n                            )).end().override()\n                            .predicate(energyType, 3)\n                            .model(model).end();\n\n                    return model;\n                }\n            });\n        });\n    }\n\n    private <T extends Block> void genNorthCutoutModels(BlockColorMap<T> blockMap, boolean useLoader) {\n        blockMap.forEach((color, registryObject) -> {\n            Block block = registryObject.get();\n            String folderName = blockMap.get(ColorMap.DEFAULT_COLOR).getId().getPath();\n\n            ModelFile disconnected = models.createCubeNorthCutoutNonEmissiveModel(\n                    \"block/\" + folderName + \"/disconnected\",\n                    BOTTOM,\n                    resourceLocation(folderName, \"top\"),\n                    resourceLocation(folderName, \"front\"),\n                    resourceLocation(folderName, \"back\"),\n                    resourceLocation(folderName, \"right\"),\n                    resourceLocation(folderName, \"left\"),\n                    resourceLocation(folderName, \"right\"),\n                    resourceLocation(folderName, \"cutouts/disconnected\")\n            );\n            ModelFile connected = models.createCubeNorthCutoutModel(\n                    \"block/\" + folderName + \"/\" + color,\n                    BOTTOM,\n                    resourceLocation(folderName, \"top\"),\n                    resourceLocation(folderName, \"front\"),\n                    resourceLocation(folderName, \"back\"),\n                    resourceLocation(folderName, \"right\"),\n                    resourceLocation(folderName, \"left\"),\n                    resourceLocation(folderName, \"right\"),\n                    resourceLocation(folderName, \"cutouts/\" + color)\n            );\n\n            //generate Item Model\n            simpleBlockItem(block, connected);\n\n            if (useLoader) {\n                models.customLoaderRSBlock(block, resourceLocation(folderName, \"loader\"), connected, disconnected);\n            } else {\n                models.horizontalRSBlock(block, state -> {\n                    if (Boolean.FALSE.equals(state.getValue(NetworkNodeBlock.CONNECTED))) {\n                        return disconnected;\n                    } else {\n                        return connected;\n                    }\n                }, 180);\n            }\n        });\n    }\n\n    private ResourceLocation resourceLocation(String folderName, String name) {\n        return new ResourceLocation(RS.ID, \"block/\" + folderName + \"/\" + name);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/datageneration/BlockModels.java",
    "content": "package com.refinedmods.refinedstorage.datageneration;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.block.BlockDirection;\nimport net.minecraft.core.Direction;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.block.Block;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.model.generators.BlockModelBuilder;\nimport net.neoforged.neoforge.client.model.generators.ConfiguredModel;\nimport net.neoforged.neoforge.client.model.generators.CustomLoaderBuilder;\nimport net.neoforged.neoforge.client.model.generators.ModelFile;\nimport net.neoforged.neoforge.common.data.ExistingFileHelper;\nimport java.util.function.Function;\n\npublic class BlockModels {\n    private final BlockModelGenerator generator;\n\n    public BlockModels(BlockModelGenerator blockModelGenerator) {\n        this.generator = blockModelGenerator;\n    }\n\n    public void simpleBlockStateModel(Block block, Function<BlockState, ModelFile> model) {\n        generator.getVariantBuilder(block).forAllStates(state -> ConfiguredModel.builder().modelFile(model.apply(state)).build());\n    }\n\n    public void anyDirectionalRSBlock(Block block, Function<BlockState, ModelFile> modelFunc, int angleOffset) {\n        generator.getVariantBuilder(block)\n            .forAllStates(state -> {\n                Direction dir = state.getValue(BlockDirection.ANY.getProperty());\n\n                int xRotation = 0;\n                if (dir == Direction.DOWN) {\n                    xRotation = 180;\n                }\n                if (dir.getAxis().isHorizontal()) {\n                    xRotation = 90;\n                }\n\n                return ConfiguredModel.builder()\n                    .modelFile(modelFunc.apply(state))\n                    .rotationX(xRotation)\n                    .rotationY(dir.getAxis().isVertical() ? 0 : (((int) dir.toYRot()) + angleOffset) % 360)\n                    .build();\n            });\n    }\n\n    public void wirelessTransmitterBlock(Block block, Function<BlockState, ModelFile> modelFunc, int angleOffset) {\n        generator.getVariantBuilder(block)\n            .forAllStates(state -> {\n                Direction dir = state.getValue(BlockDirection.ANY.getProperty());\n\n                int xRotation;\n                if (dir.getAxis() == Direction.Axis.Y) {\n                    xRotation = dir == Direction.UP ? 180 : 0;\n                } else {\n                    xRotation = dir.getAxis().isHorizontal() ? 90 : 0;\n                }\n\n                return ConfiguredModel.builder()\n                    .modelFile(modelFunc.apply(state))\n                    .rotationX(xRotation)\n                    .rotationY(dir.getAxis().isVertical() ? 0 : (((int) dir.toYRot()) + angleOffset) % 360)\n                    .build();\n            });\n    }\n\n    public void horizontalRSBlock(Block block, Function<BlockState, ModelFile> modelFunc, int angleOffset) {\n        generator.getVariantBuilder(block)\n            .forAllStates(state -> ConfiguredModel.builder()\n                .modelFile(modelFunc.apply(state))\n                .rotationY(((int) state.getValue(BlockDirection.HORIZONTAL.getProperty()).toYRot() + angleOffset) % 360)\n                .build()\n            );\n    }\n\n    public void customLoaderRSBlock(Block block, ResourceLocation path, ModelFile connectedModel, ModelFile disconnectedModel) {\n        var model = generator.models().getBuilder(path.toString())\n            .renderType(\"cutout\").customLoader((builder, filehelper) ->\n                new CustomLoaderBuilderBasic(new ResourceLocation(RS.ID, \"disk_manipulator\"), builder, filehelper)).end();\n\n        generator.getVariantBuilder(block).setModels(generator.getVariantBuilder(block).partialState(),\n            ConfiguredModel.builder().modelFile(model).buildLast());\n    }\n\n    public BlockModelBuilder createDetectorModel(String name, ResourceLocation torch) {\n        return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, \"detector\"))\n            .texture(\"torch\", torch);\n    }\n\n    public BlockModelBuilder createDetectorNonEmissiveModel(String name, ResourceLocation torch) {\n        return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, \"detector_nonemissive\"))\n                .texture(\"torch\", torch);\n    }\n\n    public BlockModelBuilder createWirelessTransmitterModel(String name, ResourceLocation cutout) {\n        return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, \"wireless_transmitter\"))\n            .texture(\"cutout\", cutout);\n    }\n\n    public BlockModelBuilder createWirelessTransmitterNonEmissiveModel(String name, ResourceLocation cutout) {\n        return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, \"wireless_transmitter_nonemissive\"))\n                .texture(\"cutout\", cutout);\n    }\n\n    public BlockModelBuilder createCubeCutoutModel(String name, ResourceLocation down, ResourceLocation downCutout, ResourceLocation up, ResourceLocation upCutout, ResourceLocation east, ResourceLocation eastCutout, ResourceLocation west, ResourceLocation westCutout, ResourceLocation north, ResourceLocation northCutout, ResourceLocation south, ResourceLocation southCutout) {\n        return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, \"cube_cutout\"))\n            .texture(\"particle\", north)\n            .texture(\"east\", east)\n            .texture(\"south\", south)\n            .texture(\"west\", west)\n            .texture(\"up\", up)\n            .texture(\"down\", down)\n            .texture(\"north\", north)\n            .texture(\"cutout_down\", downCutout)\n            .texture(\"cutout_east\", eastCutout)\n            .texture(\"cutout_west\", westCutout)\n            .texture(\"cutout_south\", southCutout)\n            .texture(\"cutout_north\", northCutout)\n            .texture(\"cutout_up\", upCutout);\n    }\n\n    public BlockModelBuilder createCubeCutoutNonEmissiveModel(String name, ResourceLocation down, ResourceLocation downCutout, ResourceLocation up, ResourceLocation upCutout, ResourceLocation east, ResourceLocation eastCutout, ResourceLocation west, ResourceLocation westCutout, ResourceLocation north, ResourceLocation northCutout, ResourceLocation south, ResourceLocation southCutout) {\n        return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, \"cube_cutout_nonemissive\"))\n                .texture(\"particle\", north)\n                .texture(\"east\", east)\n                .texture(\"south\", south)\n                .texture(\"west\", west)\n                .texture(\"up\", up)\n                .texture(\"down\", down)\n                .texture(\"north\", north)\n                .texture(\"cutout_down\", downCutout)\n                .texture(\"cutout_east\", eastCutout)\n                .texture(\"cutout_west\", westCutout)\n                .texture(\"cutout_south\", southCutout)\n                .texture(\"cutout_north\", northCutout)\n                .texture(\"cutout_up\", upCutout);\n    }\n\n    public BlockModelBuilder createControllerNearlyCutoutModel(String name, ResourceLocation particle, ResourceLocation all, ResourceLocation grayCutout, ResourceLocation cutout) {\n        return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, \"block/controller_nearly\"))\n            .texture(\"particle\", particle)\n            .texture(\"all\", all)\n            .texture(\"cutout_gray\", grayCutout)\n            .texture(\"cutout\", cutout);\n    }\n\n    public BlockModelBuilder createCubeAllCutoutModel(String name, ResourceLocation particle, ResourceLocation all, ResourceLocation cutout) {\n        return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, \"cube_all_cutout\"))\n            .texture(\"particle\", particle)\n            .texture(\"all\", all)\n            .texture(\"cutout\", cutout);\n    }\n\n    public BlockModelBuilder createCubeAllCutoutNonEmissiveModel(String name, ResourceLocation particle, ResourceLocation all, ResourceLocation cutout) {\n        return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, \"cube_all_cutout_nonemissive\"))\n                .texture(\"particle\", particle)\n                .texture(\"all\", all)\n                .texture(\"cutout\", cutout);\n    }\n\n    public BlockModelBuilder createCubeNorthCutoutModel(String name, ResourceLocation down, ResourceLocation up, ResourceLocation north, ResourceLocation south, ResourceLocation east, ResourceLocation west, ResourceLocation particle, ResourceLocation cutout) {\n        return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, \"cube_north_cutout\"))\n            .texture(\"particle\", particle)\n            .texture(\"east\", east)\n            .texture(\"south\", south)\n            .texture(\"west\", west)\n            .texture(\"up\", up)\n            .texture(\"down\", down)\n            .texture(\"north\", north)\n            .texture(\"cutout\", cutout);\n    }\n\n    public BlockModelBuilder createCubeNorthCutoutNonEmissiveModel(String name, ResourceLocation down, ResourceLocation up, ResourceLocation north, ResourceLocation south, ResourceLocation east, ResourceLocation west, ResourceLocation particle, ResourceLocation cutout) {\n        return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, \"cube_north_cutout_nonemissive\"))\n                .texture(\"particle\", particle)\n                .texture(\"east\", east)\n                .texture(\"south\", south)\n                .texture(\"west\", west)\n                .texture(\"up\", up)\n                .texture(\"down\", down)\n                .texture(\"north\", north)\n                .texture(\"cutout\", cutout);\n    }\n\n    class CustomLoaderBuilderBasic extends CustomLoaderBuilder<BlockModelBuilder> {\n        protected CustomLoaderBuilderBasic(ResourceLocation loaderId, BlockModelBuilder parent, ExistingFileHelper existingFileHelper) {\n            super(loaderId, parent, existingFileHelper);\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/datageneration/BlockTagGenerator.java",
    "content": "package com.refinedmods.refinedstorage.datageneration;\n\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport net.minecraft.core.HolderLookup;\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.data.PackOutput;\nimport net.minecraft.resources.ResourceKey;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.tags.BlockTags;\nimport net.minecraft.world.level.block.Block;\nimport net.neoforged.neoforge.common.data.BlockTagsProvider;\nimport net.neoforged.neoforge.common.data.ExistingFileHelper;\nimport javax.annotation.Nullable;\nimport java.util.concurrent.CompletableFuture;\n\npublic class BlockTagGenerator extends BlockTagsProvider {\n    public BlockTagGenerator(PackOutput output, CompletableFuture<HolderLookup.Provider> lookupProvider, String modId, @Nullable ExistingFileHelper existingFileHelper) {\n        super(output, lookupProvider, modId, existingFileHelper);\n    }\n\n    @Override\n    protected void addTags(HolderLookup.Provider provider) {\n        TagAppender<Block> noRelocationTag = tag(BlockTags.create(new ResourceLocation(\"forge:relocation_not_supported\")));\n\n        RSBlocks.COLORED_BLOCK_TAGS.forEach((tag, map) -> {\n            map.values().forEach(block -> tag(tag).add(block.get()));\n            noRelocationTag.addTags(tag);\n        });\n        RSBlocks.STORAGE_BLOCKS.forEach((tag, block) -> noRelocationTag.add(resourceKey(block.get())));\n        RSBlocks.FLUID_STORAGE_BLOCKS.forEach((tag, block) -> noRelocationTag.add(resourceKey(block.get())));\n\n        noRelocationTag.add(\n            resourceKey(RSBlocks.IMPORTER.get()),\n            resourceKey(RSBlocks.EXPORTER.get()),\n            resourceKey(RSBlocks.EXTERNAL_STORAGE.get()),\n            resourceKey(RSBlocks.DISK_DRIVE.get()),\n            resourceKey(RSBlocks.INTERFACE.get()),\n            resourceKey(RSBlocks.FLUID_INTERFACE.get()),\n            resourceKey(RSBlocks.STORAGE_MONITOR.get()),\n            resourceKey(RSBlocks.CONSTRUCTOR.get()),\n            resourceKey(RSBlocks.DESTRUCTOR.get()),\n            resourceKey(RSBlocks.PORTABLE_GRID.get()),\n            resourceKey(RSBlocks.CREATIVE_PORTABLE_GRID.get())\n        );\n    }\n\n    private ResourceKey<Block> resourceKey(Block block) {\n        return BuiltInRegistries.BLOCK.getResourceKey(block).get();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/datageneration/DataGenerators.java",
    "content": "package com.refinedmods.refinedstorage.datageneration;\n\nimport com.refinedmods.refinedstorage.RS;\nimport net.minecraft.data.loot.LootTableProvider;\nimport net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;\nimport net.neoforged.bus.api.SubscribeEvent;\nimport net.neoforged.neoforge.common.data.BlockTagsProvider;\nimport net.neoforged.neoforge.data.event.GatherDataEvent;\nimport java.util.List;\nimport java.util.Set;\n\npublic class DataGenerators {\n    @SubscribeEvent\n    public void runDataGeneration(GatherDataEvent event) {\n        event.getGenerator().addProvider(event.includeClient(), new BlockModelGenerator(event.getGenerator().getPackOutput(), RS.ID, event.getExistingFileHelper()));\n        event.getGenerator().addProvider(event.includeServer(), new RecipeGenerator(event.getGenerator().getPackOutput()));\n        BlockTagGenerator blockTagGenerator = new BlockTagGenerator(\n            event.getGenerator().getPackOutput(),\n            event.getLookupProvider(),\n            RS.ID,\n            event.getExistingFileHelper()\n        );\n        final BlockTagsProvider blockTagsProvider = event.getGenerator().addProvider(event.includeServer(), blockTagGenerator);\n        event.getGenerator().addProvider(event.includeServer(), new ItemTagGenerator(\n            event.getGenerator().getPackOutput(),\n            event.getLookupProvider(),\n            blockTagsProvider.contentsGetter(),\n            RS.ID,\n            event.getExistingFileHelper()\n        ));\n        event.getGenerator().addProvider(event.includeServer(), new BlockEntityTagGenerator(\n            event.getGenerator().getPackOutput(),\n            RS.ID,\n            event.getLookupProvider(),\n            event.getExistingFileHelper()\n        ));\n        event.getGenerator().addProvider(event.includeServer(), new LootTableProvider(\n            event.getGenerator().getPackOutput(),\n            Set.of(),\n            List.of(new LootTableProvider.SubProviderEntry(\n                LootTableGenerator::new,\n                LootContextParamSets.BLOCK\n            ))\n        ));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/datageneration/ItemTagGenerator.java",
    "content": "package com.refinedmods.refinedstorage.datageneration;\n\nimport com.refinedmods.refinedstorage.RSItems;\n\nimport java.util.concurrent.CompletableFuture;\n\nimport net.minecraft.core.HolderLookup;\nimport net.minecraft.data.PackOutput;\nimport net.minecraft.data.tags.ItemTagsProvider;\nimport net.minecraft.data.tags.TagsProvider;\nimport net.minecraft.world.level.block.Block;\nimport net.neoforged.neoforge.common.data.ExistingFileHelper;\n\npublic class ItemTagGenerator extends ItemTagsProvider {\n    public ItemTagGenerator(PackOutput output, CompletableFuture<HolderLookup.Provider> lookup,\n                            CompletableFuture<TagsProvider.TagLookup<Block>> p_275322_, String modId,\n                            ExistingFileHelper existingFileHelper) {\n        super(output, lookup, p_275322_, modId, existingFileHelper);\n    }\n\n    @Override\n    protected void addTags(HolderLookup.Provider provider) {\n        RSItems.COLORED_ITEM_TAGS.forEach((tag, map) -> map.values().forEach(item -> tag(tag).add(item.get())));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/datageneration/LootTableGenerator.java",
    "content": "package com.refinedmods.refinedstorage.datageneration;\n\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.loottable.ControllerLootFunction;\nimport com.refinedmods.refinedstorage.loottable.CrafterLootFunction;\nimport net.minecraft.data.loot.BlockLootSubProvider;\nimport net.minecraft.world.flag.FeatureFlags;\nimport net.minecraft.world.level.block.Block;\nimport net.minecraft.world.level.storage.loot.LootPool;\nimport net.minecraft.world.level.storage.loot.LootTable;\nimport net.minecraft.world.level.storage.loot.entries.LootItem;\nimport net.minecraft.world.level.storage.loot.functions.LootItemFunction;\nimport net.minecraft.world.level.storage.loot.predicates.ExplosionCondition;\nimport net.minecraft.world.level.storage.loot.providers.number.ConstantValue;\nimport net.neoforged.neoforge.registries.DeferredHolder;\n\nimport java.util.Collections;\nimport java.util.stream.Collectors;\n\npublic class LootTableGenerator extends BlockLootSubProvider {\n    public LootTableGenerator() {\n        super(Collections.emptySet(), FeatureFlags.REGISTRY.allFlags());\n    }\n\n    @Override\n    protected void generate() {\n        RSBlocks.CONTROLLER.values().forEach(block -> genBlockItemLootTableWithFunction(block.get(), ControllerLootFunction::new));\n        RSBlocks.CREATIVE_CONTROLLER.values().forEach(block -> dropSelf(block.get()));\n        RSBlocks.CRAFTER.values().forEach(block -> genBlockItemLootTableWithFunction(block.get(),\n            CrafterLootFunction::new));\n        RSBlocks.GRID.values().forEach(block -> dropSelf(block.get()));\n        RSBlocks.CRAFTING_GRID.values().forEach(block -> dropSelf(block.get()));\n        RSBlocks.FLUID_GRID.values().forEach(block -> dropSelf(block.get()));\n        RSBlocks.PATTERN_GRID.values().forEach(block -> dropSelf(block.get()));\n        RSBlocks.SECURITY_MANAGER.values().forEach(block -> dropSelf(block.get()));\n        RSBlocks.WIRELESS_TRANSMITTER.values().forEach(block -> dropSelf(block.get()));\n        RSBlocks.RELAY.values().forEach(block -> dropSelf(block.get()));\n        RSBlocks.NETWORK_TRANSMITTER.values().forEach(block -> dropSelf(block.get()));\n        RSBlocks.NETWORK_RECEIVER.values().forEach(block -> dropSelf(block.get()));\n        RSBlocks.DISK_MANIPULATOR.values().forEach(block -> dropSelf(block.get()));\n        RSBlocks.CRAFTING_MONITOR.values().forEach(block -> dropSelf(block.get()));\n        RSBlocks.CRAFTER_MANAGER.values().forEach(block -> dropSelf(block.get()));\n        RSBlocks.DETECTOR.values().forEach(block -> dropSelf(block.get()));\n    }\n\n    @Override\n    protected Iterable<Block> getKnownBlocks() {\n        return RSBlocks.COLORED_BLOCKS.stream().map(DeferredHolder::get).collect(Collectors.toList());\n    }\n\n    private void genBlockItemLootTableWithFunction(Block block, LootItemFunction.Builder builder) {\n        add(block, LootTable.lootTable().withPool(\n            LootPool.lootPool()\n                .setRolls(ConstantValue.exactly(1))\n                .add(LootItem.lootTableItem(block)\n                    .apply(builder))\n                .when(ExplosionCondition.survivesExplosion())));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/datageneration/RecipeGenerator.java",
    "content": "package com.refinedmods.refinedstorage.datageneration;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.item.ProcessorItem;\nimport com.refinedmods.refinedstorage.util.ColorMap;\nimport net.minecraft.advancements.critereon.InventoryChangeTrigger;\nimport net.minecraft.data.PackOutput;\nimport net.minecraft.data.recipes.RecipeCategory;\nimport net.minecraft.data.recipes.RecipeOutput;\nimport net.minecraft.data.recipes.RecipeProvider;\nimport net.minecraft.data.recipes.ShapelessRecipeBuilder;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.tags.ItemTags;\nimport net.minecraft.world.item.Items;\n\npublic class RecipeGenerator extends RecipeProvider {\n    private static final String GRID_ID = RS.ID + \":grid\";\n\n    public RecipeGenerator(PackOutput output) {\n        super(output);\n    }\n\n    @Override\n    protected void buildRecipes(RecipeOutput output) {\n        // Tag + Color -> Colored Block\n        RSItems.COLORED_ITEM_TAGS.forEach((tag, map) -> map.forEach((color, item) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, item.get())\n            .requires(tag)\n            .requires(color.getTag())\n            .group(RS.ID)\n            .unlockedBy(\"refinedstorage:controller\", InventoryChangeTrigger.TriggerInstance.hasItems(RSItems.CONTROLLER.get(ColorMap.DEFAULT_COLOR).get()))\n            .save(output, new ResourceLocation(RS.ID, \"coloring_recipes/\" + item.getId().getPath()))\n        ));\n\n        // Crafting Grid\n        RSItems.CRAFTING_GRID.forEach((color, item) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, item.get())\n            .requires(RSItems.GRID.get(color).get())\n            .requires(RSItems.PROCESSORS.get(ProcessorItem.Type.ADVANCED).get())\n            .requires(ItemTags.create(new ResourceLocation(RS.ID, \"crafting_tables\")))\n            .unlockedBy(GRID_ID, InventoryChangeTrigger.TriggerInstance.hasItems(RSItems.GRID.get(ColorMap.DEFAULT_COLOR).get()))\n            .save(output, new ResourceLocation(RS.ID, \"crafting_grid/\" + item.getId().getPath()))\n        );\n\n        // Fluid Grid\n        RSItems.FLUID_GRID.forEach((color, item) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, item.get())\n            .requires(RSItems.GRID.get(color).get())\n            .requires(RSItems.PROCESSORS.get(ProcessorItem.Type.ADVANCED).get())\n            .requires(Items.BUCKET)\n            .unlockedBy(GRID_ID, InventoryChangeTrigger.TriggerInstance.hasItems(RSItems.GRID.get(ColorMap.DEFAULT_COLOR).get()))\n            .save(output, new ResourceLocation(RS.ID, \"fluid_grid/\" + item.getId().getPath()))\n        );\n\n        // Pattern Grid\n        RSItems.PATTERN_GRID.forEach((color, item) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, item.get())\n            .requires(RSItems.GRID.get(color).get())\n            .requires(RSItems.PROCESSORS.get(ProcessorItem.Type.ADVANCED).get())\n            .requires(RSItems.PATTERN.get())\n            .unlockedBy(GRID_ID, InventoryChangeTrigger.TriggerInstance.hasItems(RSItems.GRID.get(ColorMap.DEFAULT_COLOR).get()))\n            .save(output, new ResourceLocation(RS.ID, \"pattern_grid/\" + item.getId().getPath()))\n        );\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/energy/BaseEnergyStorage.java",
    "content": "package com.refinedmods.refinedstorage.energy;\n\nimport net.neoforged.neoforge.energy.EnergyStorage;\n\npublic class BaseEnergyStorage extends EnergyStorage {\n    public BaseEnergyStorage(int capacity, int maxReceive, int maxExtract) {\n        super(capacity, maxReceive, maxExtract);\n    }\n\n    // @Volatile: Impl from EnergyStorage#extractEnergy, without the canExtract check\n    public void extractEnergyBypassCanExtract(int maxExtract, boolean simulate) {\n        int energyExtracted = Math.min(energy, maxExtract);\n\n        if (!simulate) {\n            energy -= energyExtracted;\n        }\n    }\n\n    public void setStored(int energy) {\n        this.energy = energy;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/energy/ItemEnergyStorage.java",
    "content": "package com.refinedmods.refinedstorage.energy;\n\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.energy.EnergyStorage;\n\npublic class ItemEnergyStorage extends EnergyStorage {\n    private static final String NBT_ENERGY = \"Energy\";\n\n    private final ItemStack stack;\n\n    public ItemEnergyStorage(ItemStack stack, int capacity) {\n        super(capacity, Integer.MAX_VALUE, Integer.MAX_VALUE);\n\n        this.stack = stack;\n        this.energy = stack.hasTag() && stack.getTag().contains(NBT_ENERGY) ? stack.getTag().getInt(NBT_ENERGY) : 0;\n    }\n\n    @Override\n    public int receiveEnergy(int maxReceive, boolean simulate) {\n        int received = super.receiveEnergy(maxReceive, simulate);\n\n        if (received > 0 && !simulate) {\n            if (!stack.hasTag()) {\n                stack.setTag(new CompoundTag());\n            }\n\n            stack.getTag().putInt(NBT_ENERGY, getEnergyStored());\n        }\n\n        return received;\n    }\n\n    @Override\n    public int extractEnergy(int maxExtract, boolean simulate) {\n        int extracted = super.extractEnergy(maxExtract, simulate);\n\n        if (extracted > 0 && !simulate) {\n            if (!stack.hasTag()) {\n                stack.setTag(new CompoundTag());\n            }\n\n            stack.getTag().putInt(NBT_ENERGY, getEnergyStored());\n        }\n\n        return extracted;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/integration/craftingtweaks/CraftingTweaksIntegration.java",
    "content": "package com.refinedmods.refinedstorage.integration.craftingtweaks;\n\nimport com.refinedmods.refinedstorage.api.network.grid.GridType;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport com.refinedmods.refinedstorage.container.slot.grid.CraftingGridSlot;\nimport net.minecraft.nbt.CompoundTag;\nimport net.neoforged.fml.InterModComms;\nimport net.neoforged.fml.ModList;\nimport java.util.function.Function;\nimport java.util.function.Predicate;\n\npublic final class CraftingTweaksIntegration {\n    private static final String ID = \"craftingtweaks\";\n\n    private CraftingTweaksIntegration() {\n    }\n\n    public static boolean isLoaded() {\n        return ModList.get().isLoaded(ID);\n    }\n\n    public static boolean isCraftingTweaksClass(Class<?> clazz) {\n        return clazz.getName().startsWith(\"net.blay09.mods.craftingtweaks\");\n    }\n\n    public static void register() {\n        CompoundTag tag = new CompoundTag();\n\n        tag.putString(\"ContainerClass\", GridContainerMenu.class.getName());\n        tag.putString(\"ValidContainerPredicate\", ValidContainerPredicate.class.getName());\n        tag.putString(\"GetGridStartFunction\", GetGridStartFunction.class.getName());\n        tag.putString(\"AlignToGrid\", \"left\");\n\n        InterModComms.sendTo(ID, \"RegisterProvider\", () -> tag);\n    }\n\n    public static class ValidContainerPredicate implements Predicate<GridContainerMenu> {\n        @Override\n        public boolean test(GridContainerMenu containerGrid) {\n            return containerGrid.getGrid().getGridType() == GridType.CRAFTING;\n        }\n    }\n\n    public static class GetGridStartFunction implements Function<GridContainerMenu, Integer> {\n        @Override\n        public Integer apply(GridContainerMenu containerGrid) {\n            for (int i = 0; i < containerGrid.slots.size(); i++) {\n                if (containerGrid.slots.get(i) instanceof CraftingGridSlot) {\n                    return i;\n                }\n            }\n\n            return 0;\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/integration/curios/CuriosIntegration.java",
    "content": "package com.refinedmods.refinedstorage.integration.curios;\n\nimport net.neoforged.bus.api.SubscribeEvent;\nimport net.neoforged.fml.InterModComms;\nimport net.neoforged.fml.ModList;\nimport net.neoforged.fml.event.lifecycle.InterModEnqueueEvent;\nimport top.theillusivec4.curios.api.SlotTypeMessage;\nimport top.theillusivec4.curios.api.SlotTypePreset;\n\npublic class CuriosIntegration {\n    private static final String ID = \"curios\";\n\n    public CuriosIntegration() {\n    }\n\n    public static boolean isLoaded() {\n        return ModList.get().isLoaded(ID);\n    }\n\n    @SubscribeEvent\n    public void registerSlots(InterModEnqueueEvent event) {\n        InterModComms.sendTo(ID, SlotTypeMessage.REGISTER_TYPE, () -> SlotTypePreset.BELT.getMessageBuilder().build());\n        InterModComms.sendTo(ID, SlotTypeMessage.REGISTER_TYPE, () -> SlotTypePreset.BODY.getMessageBuilder().build());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/integration/inventorysorter/InventorySorterIntegration.java",
    "content": "package com.refinedmods.refinedstorage.integration.inventorysorter;\n\nimport com.refinedmods.refinedstorage.RS;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.fml.InterModComms;\nimport net.neoforged.fml.ModList;\n\npublic class InventorySorterIntegration {\n    private static final String ID = \"inventorysorter\";\n\n    private InventorySorterIntegration() {\n    }\n\n    public static boolean isLoaded() {\n        return ModList.get().isLoaded(ID);\n    }\n\n    public static void register() {\n        // Prevent items moving while scrolling through slots with Inventory Sorter in the Crafter Manager\n        InterModComms.sendTo(\"inventorysorter\", \"slotblacklist\", () -> \"com.refinedmods.refinedstorage.container.slot.CrafterManagerSlot\");\n        InterModComms.sendTo(\"inventorysorter\", \"containerblacklist\", () -> new ResourceLocation(RS.ID, \"crafter\"));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/integration/inventorytweaks/InventoryTweaksIntegration.java",
    "content": "package com.refinedmods.refinedstorage.integration.inventorytweaks;\n\nimport net.neoforged.fml.ModList;\n\npublic class InventoryTweaksIntegration {\n    private InventoryTweaksIntegration() {\n    }\n\n    public static boolean isLoaded() {\n        return ModList.get().isLoaded(\"inventorytweaks\");\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/integration/jei/CoverCraftingCategoryExtension.java",
    "content": "package com.refinedmods.refinedstorage.integration.jei;\n\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;\nimport com.refinedmods.refinedstorage.item.CoverItem;\nimport com.refinedmods.refinedstorage.recipe.CoverRecipe;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\nimport com.google.common.collect.Streams;\nimport mezz.jei.api.gui.builder.IRecipeLayoutBuilder;\nimport mezz.jei.api.gui.builder.IRecipeSlotBuilder;\nimport mezz.jei.api.gui.ingredient.ICraftingGridHelper;\nimport mezz.jei.api.recipe.IFocusGroup;\nimport mezz.jei.api.recipe.category.extensions.vanilla.crafting.ICraftingCategoryExtension;\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.Items;\nimport net.minecraft.world.item.crafting.RecipeHolder;\nimport net.minecraft.world.level.block.Block;\nimport net.neoforged.neoforge.common.Tags;\n\npublic class CoverCraftingCategoryExtension implements ICraftingCategoryExtension<CoverRecipe> {\n    @Override\n    public void setRecipe(RecipeHolder<CoverRecipe> recipe, IRecipeLayoutBuilder builder,\n                          ICraftingGridHelper craftingGridHelper, IFocusGroup focuses) {\n        List<ItemStack> input = new ArrayList<>();\n        List<ItemStack> output = new ArrayList<>();\n        for (Block block : BuiltInRegistries.BLOCK) {\n            Item item = Item.BY_BLOCK.get(block);\n            if (item == null || item == Items.AIR) {\n                continue;\n            }\n            ItemStack itemStack = new ItemStack(item);\n            if (CoverManager.isValidCover(itemStack)) {\n                input.add(itemStack);\n                ItemStack coverStack = new ItemStack(RSItems.COVER.get());\n                CoverItem.setItem(coverStack, itemStack);\n                output.add(coverStack);\n            }\n        }\n\n        final var nuggetTag = BuiltInRegistries.ITEM.getTagOrEmpty(Tags.Items.NUGGETS_IRON);\n        List<ItemStack> nuggets = Streams.stream(nuggetTag).map(ItemStack::new).toList();\n        List<List<ItemStack>> inputs = new ArrayList<>(Collections.nCopies(9, new ArrayList<>()));\n        inputs.set(3, nuggets);\n        inputs.set(4, input);\n        List<IRecipeSlotBuilder> inputSlots = craftingGridHelper.createAndSetInputs(builder, inputs, 3, 3);\n        IRecipeSlotBuilder outputSlot = craftingGridHelper.createAndSetOutputs(builder, output);\n\n        builder.createFocusLink(inputSlots.get(4), outputSlot);\n    }\n\n    @Override\n    public int getWidth(RecipeHolder<CoverRecipe> recipe) {\n        return 3;\n    }\n\n    @Override\n    public int getHeight(RecipeHolder<CoverRecipe> recipe) {\n        return 3;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/integration/jei/GhostIngredientHandler.java",
    "content": "package com.refinedmods.refinedstorage.integration.jei;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.container.slot.filter.FilterSlot;\nimport com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot;\nimport com.refinedmods.refinedstorage.container.slot.legacy.LegacyFilterSlot;\nimport com.refinedmods.refinedstorage.network.SetFilterSlotMessage;\nimport com.refinedmods.refinedstorage.network.SetFluidFilterSlotMessage;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport mezz.jei.api.gui.handlers.IGhostIngredientHandler;\nimport mezz.jei.api.ingredients.ITypedIngredient;\nimport net.minecraft.client.renderer.Rect2i;\nimport net.minecraft.world.inventory.Slot;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.fluids.FluidType;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class GhostIngredientHandler implements IGhostIngredientHandler<BaseScreen> {\n    @Override\n    public <I> List<Target<I>> getTargetsTyped(BaseScreen gui, ITypedIngredient<I> ingredient, boolean doStart) {\n        List<Target<I>> targets = new ArrayList<>();\n\n        for (Slot slot : gui.getMenu().slots) {\n            if (!slot.isActive()) {\n                continue;\n            }\n\n            Rect2i bounds = new Rect2i(gui.getGuiLeft() + slot.x, gui.getGuiTop() + slot.y, 17, 17);\n\n            if (ingredient.getIngredient() instanceof ItemStack && (slot instanceof LegacyFilterSlot || slot instanceof FilterSlot)) {\n                targets.add(new Target<I>() {\n                    @Override\n                    public Rect2i getArea() {\n                        return bounds;\n                    }\n\n                    @Override\n                    public void accept(I ingredient) {\n                        slot.set((ItemStack) ingredient);\n\n                        RS.NETWORK_HANDLER.sendToServer(new SetFilterSlotMessage(slot.index, (ItemStack) ingredient));\n                    }\n                });\n            } else if (ingredient instanceof FluidStack && slot instanceof FluidFilterSlot) {\n                targets.add(new Target<>() {\n                    @Override\n                    public Rect2i getArea() {\n                        return bounds;\n                    }\n\n                    @Override\n                    public void accept(I ingredient) {\n                        RS.NETWORK_HANDLER.sendToServer(new SetFluidFilterSlotMessage(slot.index, StackUtils.copy((FluidStack) ingredient, FluidType.BUCKET_VOLUME)));\n                    }\n                });\n            }\n        }\n\n        return targets;\n    }\n\n    @Override\n    public void onComplete() {\n        // NO OP\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/integration/jei/GridRecipeTransferHandler.java",
    "content": "package com.refinedmods.refinedstorage.integration.jei;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSContainerMenus;\nimport com.refinedmods.refinedstorage.api.network.grid.GridType;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport com.refinedmods.refinedstorage.network.grid.GridCraftingPreviewRequestMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridProcessingTransferMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridTransferMessage;\nimport com.refinedmods.refinedstorage.screen.grid.GridScreen;\nimport mezz.jei.api.gui.ingredient.IRecipeSlotView;\nimport mezz.jei.api.gui.ingredient.IRecipeSlotsView;\nimport mezz.jei.api.neoforge.NeoForgeTypes;\nimport mezz.jei.api.recipe.RecipeIngredientRole;\nimport mezz.jei.api.recipe.RecipeType;\nimport mezz.jei.api.recipe.transfer.IRecipeTransferError;\nimport mezz.jei.api.recipe.transfer.IRecipeTransferHandler;\nimport net.minecraft.client.gui.screens.Screen;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.MenuType;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.crafting.RecipeHolder;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport org.jetbrains.annotations.Nullable;\n\nimport java.util.ArrayList;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.stream.Collectors;\n\npublic class GridRecipeTransferHandler implements IRecipeTransferHandler<GridContainerMenu, Object> {\n    public static final GridRecipeTransferHandler INSTANCE = new GridRecipeTransferHandler();\n\n    private static final long TRANSFER_SCROLLBAR_DELAY_MS = 200;\n\n    private long lastTransferTimeMs;\n\n    private GridRecipeTransferHandler() {\n    }\n\n    @Override\n    public Class<GridContainerMenu> getContainerClass() {\n        return GridContainerMenu.class;\n    }\n\n    @Override\n    public Optional<MenuType<GridContainerMenu>> getMenuType() {\n        return Optional.of(RSContainerMenus.GRID.get());\n    }\n\n    @Override\n    public RecipeType<Object> getRecipeType() {\n        // This is not actually used, as we register with JEI as a universal handler\n        return null;\n    }\n\n    @Override\n    public @Nullable IRecipeTransferError transferRecipe(GridContainerMenu container, Object recipe, IRecipeSlotsView recipeSlots, Player player, boolean maxTransfer, boolean doTransfer) {\n        if (!(container.getScreenInfoProvider() instanceof GridScreen gridScreen)) {\n            return null;\n        }\n\n        //When JEI is open the screen no longer ticks and doesn't run Actions. However, we do still want to run the actions that update the grid to keep the stored items up to date\n        gridScreen.runActions();\n\n        Ingredient.IngredientList ingredientList = new Ingredient.IngredientList();\n        for (IRecipeSlotView slotView : recipeSlots.getSlotViews(RecipeIngredientRole.INPUT)) {\n            Optional<ItemStack> firstStack = slotView.getItemStacks().findAny();\n            ingredientList.add(new Ingredient(slotView, firstStack.map(ItemStack::getCount).orElse(0)));\n        }\n\n        IngredientTracker tracker = IngredientTracker.getTracker(container);\n        tracker.updateAvailability(ingredientList, container, player);\n\n        GridType type = container.getGrid().getGridType();\n\n        if (type == GridType.CRAFTING) {\n            return transferRecipeForCraftingGrid(container, recipe, recipeSlots, player, doTransfer, ingredientList);\n        } else if (type == GridType.PATTERN) {\n            return transferRecipeForPatternGrid(container, recipe, recipeSlots, player, doTransfer, ingredientList);\n        }\n\n        return null;\n    }\n\n    private RecipeTransferCraftingGridError transferRecipeForCraftingGrid(GridContainerMenu container, Object recipe, IRecipeSlotsView recipeLayout, Player player, boolean doTransfer, Ingredient.IngredientList ingredientList) {\n\n        if (doTransfer) {\n            if (ingredientList.hasMissingButAutocraftingAvailable() && Screen.hasControlDown()) {\n                ingredientList.createCraftingRequests().forEach((id, count) -> RS.NETWORK_HANDLER.sendToServer(\n                    new GridCraftingPreviewRequestMessage(\n                        id,\n                        count,\n                        Screen.hasShiftDown(),\n                        false\n                    )\n                ));\n            } else {\n                moveItems(container, recipe, recipeLayout, player);\n            }\n        } else {\n            if (ingredientList.hasMissing()) {\n                return new RecipeTransferCraftingGridError(ingredientList);\n            }\n        }\n\n        return null;\n    }\n\n    private IRecipeTransferError transferRecipeForPatternGrid(GridContainerMenu container, Object recipe, IRecipeSlotsView recipeLayout, Player player, boolean doTransfer, Ingredient.IngredientList ingredientList) {\n        if (doTransfer) {\n            moveItems(container, recipe, recipeLayout, player);\n        } else {\n            if (ingredientList.isAutocraftingAvailable()) {\n                return new RecipeTransferPatternGridError(ingredientList);\n            }\n        }\n\n        return null;\n    }\n\n    public boolean hasTransferredRecently() {\n        return System.currentTimeMillis() - lastTransferTimeMs <= TRANSFER_SCROLLBAR_DELAY_MS;\n    }\n\n    private void moveItems(GridContainerMenu gridContainer, Object recipe, IRecipeSlotsView recipeLayout, Player player) {\n        this.lastTransferTimeMs = System.currentTimeMillis();\n\n        boolean isCraftingRecipe = false;\n        if (recipe instanceof RecipeHolder<?> castRecipe) {\n            isCraftingRecipe = castRecipe.value().getType() == net.minecraft.world.item.crafting.RecipeType.CRAFTING;\n        }\n\n        if (gridContainer.getGrid().getGridType() == GridType.PATTERN && !isCraftingRecipe) {\n            moveForProcessing(recipeLayout, gridContainer, player);\n        } else {\n            move(recipeLayout);\n        }\n    }\n\n    private void move(IRecipeSlotsView recipeSlotsView) {\n        List<List<ItemStack>> inputs = recipeSlotsView.getSlotViews(RecipeIngredientRole.INPUT).stream().map(view -> {\n            //Creating a mutable list\n            List<ItemStack> stacks = view.getItemStacks().collect(Collectors.toCollection(ArrayList::new));\n\n            //moving the displayed stack to first\n            Optional<ItemStack> displayStack = view.getDisplayedItemStack();\n            displayStack.ifPresent(stack -> {\n                int index = stacks.indexOf(stack);\n                if (index > -1) {\n                    stacks.remove(index);\n                    stacks.add(0, stack);\n                }\n            });\n            return stacks;\n        }).toList();\n\n        final ItemStack[][] inputsArray = new ItemStack[inputs.size()][];\n        for (int i = 0; i < inputs.size(); i++) {\n            inputsArray[i] = inputs.get(i).toArray(new ItemStack[0]);\n        }\n\n        RS.NETWORK_HANDLER.sendToServer(new GridTransferMessage(inputsArray));\n    }\n\n    private void moveForProcessing(IRecipeSlotsView recipeLayout, GridContainerMenu gridContainer, Player player) {\n        List<ItemStack> inputs = new LinkedList<>();\n        List<ItemStack> outputs = new LinkedList<>();\n\n        List<FluidStack> fluidInputs = new LinkedList<>();\n        List<FluidStack> fluidOutputs = new LinkedList<>();\n\n        List<IRecipeSlotView> inputSlots = recipeLayout.getSlotViews(RecipeIngredientRole.INPUT);\n        for (IRecipeSlotView view : inputSlots) {\n            handleItemIngredient(inputs, view, gridContainer, player);\n            handleFluidIngredient(fluidInputs, view);\n        }\n\n        List<IRecipeSlotView> outputSlots = recipeLayout.getSlotViews(RecipeIngredientRole.OUTPUT);\n        for (IRecipeSlotView view : outputSlots) {\n            handleItemIngredient(outputs, view, gridContainer, player);\n            handleFluidIngredient(fluidOutputs, view);\n        }\n\n        RS.NETWORK_HANDLER.sendToServer(new GridProcessingTransferMessage(inputs, outputs, fluidInputs, fluidOutputs));\n    }\n\n    private void handleFluidIngredient(List<FluidStack> list, IRecipeSlotView slotView) {\n        if (slotView != null) {\n            slotView.getDisplayedIngredient(NeoForgeTypes.FLUID_STACK).ifPresent(list::add);\n        }\n    }\n\n    private void handleItemIngredient(List<ItemStack> list, IRecipeSlotView slotView, GridContainerMenu gridContainer, Player player) {\n        if (slotView != null && slotView.getItemStacks().findAny().isPresent()) {\n            ItemStack stack = IngredientTracker.getTracker(gridContainer).findBestMatch(gridContainer, player, slotView.getItemStacks().toList());\n\n            if (stack.isEmpty() && slotView.getDisplayedItemStack().isPresent()) {\n                stack = slotView.getDisplayedItemStack().get();\n            }\n            if (!stack.isEmpty()) {\n                list.add(stack);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/integration/jei/GuiContainerHandler.java",
    "content": "package com.refinedmods.refinedstorage.integration.jei;\n\nimport com.refinedmods.refinedstorage.container.BaseContainerMenu;\nimport com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.screen.grid.GridScreen;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.SideButton;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport mezz.jei.api.gui.handlers.IGuiContainerHandler;\nimport mezz.jei.api.runtime.IClickableIngredient;\nimport net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;\nimport net.minecraft.client.renderer.Rect2i;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Optional;\n\npublic class GuiContainerHandler implements IGuiContainerHandler<AbstractContainerScreen<?>> {\n    private final JeiHelper jeiHelper;\n\n    public GuiContainerHandler(JeiHelper jeiHelper) {\n        this.jeiHelper = jeiHelper;\n    }\n\n    @Override\n    public List<Rect2i> getGuiExtraAreas(AbstractContainerScreen<?> screen) {\n        if (screen instanceof BaseScreen) {\n            List<SideButton> sideButtons = ((BaseScreen) screen).getSideButtons();\n\n            List<Rect2i> rectangles = new ArrayList<>();\n            for (SideButton sideButton : sideButtons) {\n                rectangles.add(new Rect2i(sideButton.getX(), sideButton.getY(), sideButton.getWidth(), sideButton.getHeight()));\n            }\n\n            return rectangles;\n        }\n\n        return Collections.emptyList();\n    }\n\n    @Override\n    public Optional<IClickableIngredient<?>> getClickableIngredientUnderMouse(AbstractContainerScreen screen, double mouseX, double mouseY) {\n        mouseX -= screen.getGuiLeft();\n        mouseY -= screen.getGuiTop();\n\n        if (screen instanceof GridScreen) {\n            GridScreen grid = (GridScreen) screen;\n\n            if (!grid.getSearchField().isFocused() && grid.isOverSlotArea(mouseX, mouseY)) {\n                boolean inRange = grid.getSlotNumber() >= 0 && grid.getSlotNumber() < grid.getView().getStacks().size();\n                Rect2i area = new Rect2i(grid.getSlotNumberX(), grid.getSlotNumberY(), 18, 18);\n                return inRange\n                    ? jeiHelper.makeClickableIngredient(grid.getView().getStacks().get(grid.getSlotNumber()).getIngredient(), area)\n                    : Optional.empty();\n            }\n        }\n\n        if (screen.getMenu() instanceof BaseContainerMenu) {\n            for (FluidFilterSlot slot : ((BaseContainerMenu) screen.getMenu()).getFluidSlots()) {\n                FluidStack fluidInSlot = slot.getFluidInventory().getFluid(slot.getSlotIndex());\n\n                if (!fluidInSlot.isEmpty() && RenderUtils.inBounds(slot.x, slot.y, 18, 18, mouseX, mouseY)) {\n                    Rect2i area = new Rect2i(slot.x, slot.y, 18, 18);\n                    return jeiHelper.makeClickableIngredient(fluidInSlot, area);\n                }\n            }\n        }\n\n        return Optional.empty();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/integration/jei/HollowCoverCraftingCategoryExtension.java",
    "content": "package com.refinedmods.refinedstorage.integration.jei;\n\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;\nimport com.refinedmods.refinedstorage.item.CoverItem;\nimport com.refinedmods.refinedstorage.recipe.HollowCoverRecipe;\nimport mezz.jei.api.gui.builder.IRecipeLayoutBuilder;\nimport mezz.jei.api.gui.builder.IRecipeSlotBuilder;\nimport mezz.jei.api.gui.ingredient.ICraftingGridHelper;\nimport mezz.jei.api.recipe.IFocusGroup;\nimport mezz.jei.api.recipe.category.extensions.vanilla.crafting.ICraftingCategoryExtension;\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.Items;\nimport net.minecraft.world.item.crafting.RecipeHolder;\nimport net.minecraft.world.level.block.Block;\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class HollowCoverCraftingCategoryExtension implements ICraftingCategoryExtension<HollowCoverRecipe> {\n    @Override\n    public void setRecipe(RecipeHolder<HollowCoverRecipe> recipe, IRecipeLayoutBuilder builder, ICraftingGridHelper craftingGridHelper, IFocusGroup focuses) {\n        List<List<ItemStack>> stacks = new ArrayList<>(Collections.nCopies(9, new ArrayList<>()));\n        List<ItemStack> input = new ArrayList<>();\n        List<ItemStack> output = new ArrayList<>();\n        for (Block block : BuiltInRegistries.BLOCK) {\n            Item item = Item.BY_BLOCK.get(block);\n            if (item == null || item == Items.AIR) {\n                continue;\n            }\n            ItemStack itemStack = new ItemStack(item);\n            if (CoverManager.isValidCover(itemStack)) {\n                ItemStack fullCover = new ItemStack(RSItems.COVER.get());\n                CoverItem.setItem(fullCover, itemStack);\n                input.add(fullCover);\n                ItemStack hollowCover = new ItemStack(RSItems.HOLLOW_COVER.get());\n                CoverItem.setItem(hollowCover, itemStack);\n                output.add(hollowCover);\n            }\n        }\n\n        stacks.set(4, input);\n        List<IRecipeSlotBuilder> inputSlots = craftingGridHelper.createAndSetInputs(builder, stacks, 0, 0);\n        IRecipeSlotBuilder outputSlot = craftingGridHelper.createAndSetOutputs(builder, output);\n        builder.createFocusLink(inputSlots.get(4), outputSlot);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/integration/jei/Ingredient.java",
    "content": "package com.refinedmods.refinedstorage.integration.jei;\n\nimport mezz.jei.api.gui.ingredient.IRecipeSlotView;\n\nimport java.util.*;\n\nclass Ingredient {\n    private final IRecipeSlotView slotView;\n    private final int required;\n    private UUID craftStackId;\n    private int fulfilled;\n\n    public Ingredient(IRecipeSlotView view, int count) {\n        this.slotView = view;\n        this.required = count;\n    }\n\n    public boolean isAvailable() {\n        return getMissingAmount() <= 0;\n    }\n\n    public int getMissingAmount() {\n        return required - fulfilled;\n    }\n\n    public boolean isCraftable() {\n        return craftStackId != null;\n    }\n\n    public IRecipeSlotView getSlotView() {\n        return slotView;\n    }\n\n    public UUID getCraftStackId() {\n        return craftStackId;\n    }\n\n    public void setCraftStackId(UUID craftStackId) {\n        this.craftStackId = craftStackId;\n    }\n\n    public void fulfill(int amount) {\n        fulfilled += amount;\n    }\n\n    static class IngredientList {\n        List<Ingredient> ingredients = new ArrayList<>();\n\n        void add(Ingredient ingredient) {\n            ingredients.add(ingredient);\n        }\n\n        public boolean hasMissing() {\n            return ingredients.stream().anyMatch(ingredient -> !ingredient.isAvailable());\n        }\n\n        public boolean hasMissingButAutocraftingAvailable() {\n            return ingredients.stream().anyMatch(ingredient -> !ingredient.isAvailable() && ingredient.isCraftable());\n        }\n\n        public boolean isAutocraftingAvailable() {\n            return ingredients.stream().anyMatch(Ingredient::isCraftable);\n        }\n\n        public Map<UUID, Integer> createCraftingRequests() {\n            Map<UUID, Integer> toRequest = new HashMap<>();\n\n            for (Ingredient ingredient : ingredients) {\n                if (!ingredient.isAvailable() && ingredient.isCraftable()) {\n                    toRequest.merge(ingredient.getCraftStackId(), ingredient.getMissingAmount(), Integer::sum);\n                }\n            }\n\n            return toRequest;\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/integration/jei/IngredientTracker.java",
    "content": "package com.refinedmods.refinedstorage.integration.jei;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternProvider;\nimport com.refinedmods.refinedstorage.api.network.grid.GridType;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport com.refinedmods.refinedstorage.item.PatternItem;\nimport com.refinedmods.refinedstorage.screen.grid.GridScreen;\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.view.IGridView;\nimport com.refinedmods.refinedstorage.util.ItemStackKey;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.CraftingContainer;\nimport net.minecraft.world.item.ItemStack;\nimport java.util.*;\n\npublic class IngredientTracker {\n\n    private static IngredientTracker INSTANCE;\n\n    private final Map<ItemStackKey, Integer> storedItems = new HashMap<>();\n    private final Map<ItemStackKey, Integer> patternItems = new HashMap<>();\n    private final Map<ItemStackKey, UUID> craftableItems = new HashMap<>();\n\n    public static IngredientTracker getTracker(GridContainerMenu gridContainer) {\n        if (INSTANCE == null) {\n            INSTANCE = new IngredientTracker(gridContainer);\n        }\n        return INSTANCE;\n    }\n\n    public static void invalidate() {\n        INSTANCE = null;\n    }\n\n    public IngredientTracker(GridContainerMenu gridContainer) {\n\n        // Using IGridView#getStacks will return a *filtered* list of items in the view,\n        // which will cause problems - especially if the user uses JEI synchronised searching.\n        // Instead, we will use IGridView#getAllStacks which provides an unordered view of all GridStacks.\n        IGridView view = ((GridScreen) gridContainer.getScreenInfoProvider()).getView();\n\n        //Existing stacks are synced by the fact that they are both referencing the same object. However, new stacks need to be added.\n        view.addDeltaListener((iGridStack -> {\n            if (iGridStack instanceof ItemGridStack stack) {\n                if (stack.isCraftable()) {\n                    craftableItems.put(new ItemStackKey(stack.getStack()), stack.getId());\n                } else {\n                    addStack(stack.getStack());\n                }\n\n            }\n        }));\n        Collection<IGridStack> gridStacks = view.getAllStacks();\n\n        // Check grid\n        if (gridContainer.getGrid().isGridActive()) {\n            for (IGridStack gridStack : gridStacks) {\n                if (gridStack instanceof ItemGridStack stackInGrid) {\n\n                    // for craftables we should easily be able to take the hit from hashing the nbt\n                    if (stackInGrid.isCraftable()) {\n                        craftableItems.put(new ItemStackKey(stackInGrid.getStack()), gridStack.getId());\n                    } else { // for non-craftables we don't hash nbt to avoid the performance hit\n                        addStack(stackInGrid.getStack());\n                    }\n                }\n            }\n        }\n    }\n\n    public void addStack(ItemStack stack) {\n        if (stack.isEmpty()) {\n            return;\n        }\n        if (stack.getItem() instanceof ICraftingPatternProvider) {\n            ICraftingPattern pattern = PatternItem.fromCache(Minecraft.getInstance().level, stack);\n            if (pattern.isValid()) {\n                for (ItemStack outputStack : pattern.getOutputs()) {\n                    patternItems.merge(new ItemStackKey(outputStack), 1, Integer::sum);\n                }\n            }\n\n        } else {\n            storedItems.merge(new ItemStackKey(stack), stack.getCount(), Integer::sum);\n        }\n\n    }\n\n\n    public ItemStack findBestMatch(GridContainerMenu gridContainer, Player player, List<ItemStack> list) {\n        ItemStack resultStack = ItemStack.EMPTY;\n        int count = 0;\n\n\n        for (ItemStack listStack : list) {\n\n            //check crafting matrix\n            if (gridContainer.getGrid().getGridType().equals(GridType.CRAFTING)) {\n                CraftingContainer craftingMatrix = gridContainer.getGrid().getCraftingMatrix();\n                if (craftingMatrix != null) {\n                    for (int matrixSlot = 0; matrixSlot < craftingMatrix.getContainerSize(); matrixSlot++) {\n                        ItemStack stackInSlot = craftingMatrix.getItem(matrixSlot);\n                        if (API.instance().getComparer().isEqual(listStack, stackInSlot, IComparer.COMPARE_NBT)) {\n                            if (stackInSlot.getCount() > count) {\n                                count = stackInSlot.getCount();\n                                resultStack = stackInSlot;\n                            }\n                        }\n                    }\n                }\n            }\n\n            //check inventory\n            for (int inventorySlot = 0; inventorySlot < player.getInventory().getContainerSize(); inventorySlot++) {\n                ItemStack stackInSlot = player.getInventory().getItem(inventorySlot);\n                if (API.instance().getComparer().isEqual(listStack, stackInSlot, IComparer.COMPARE_NBT)) {\n                    if (stackInSlot.getCount() > count) {\n                        count = stackInSlot.getCount();\n                        resultStack = stackInSlot;\n                    }\n                }\n            }\n\n            //check storage\n            var stored = storedItems.get(new ItemStackKey(listStack));\n            if (stored != null) {\n                if (stored > count) {\n                    resultStack = listStack;\n                    count = stored;\n                }\n            }\n        }\n\n        //If the item is not in storage check patterns autocrafting\n        if (count == 0) {\n            for (ItemStack itemStack : list) {\n                ItemStackKey key = new ItemStackKey(itemStack);\n                if (craftableItems.get(key) != null) {\n                    resultStack = itemStack;\n                    break;\n                } else if (patternItems.get(key) != null) {\n                    resultStack = itemStack;\n                    break;\n                }\n            }\n        }\n\n        return resultStack;\n    }\n\n    public void updateAvailability(Ingredient.IngredientList ingredientList, GridContainerMenu gridContainer, Player player) {\n        Map<Integer, Integer> usedMatrixStacks = new HashMap<>();\n        Map<Integer, Integer> usedInventoryStacks = new HashMap<>();\n        Map<ItemStackKey, Integer> usedStoredStacks = new HashMap<>();\n\n        //Gather available Stacks\n        for (Ingredient ingredient : ingredientList.ingredients) {\n            ingredient.getSlotView().getItemStacks().takeWhile(stack -> !ingredient.isAvailable()).forEach(stack -> {\n\n                if(ingredient.getCraftStackId() == null) {\n                    ingredient.setCraftStackId(craftableItems.get(new ItemStackKey(stack)));\n                }\n                // Check grid crafting slots\n                if (gridContainer.getGrid().getGridType().equals(GridType.CRAFTING)) {\n                    CraftingContainer craftingMatrix = gridContainer.getGrid().getCraftingMatrix();\n                    if (craftingMatrix != null) {\n                        for (int matrixSlot = 0; matrixSlot < craftingMatrix.getContainerSize(); matrixSlot++) {\n                            if (checkStack(usedMatrixStacks, ingredient, stack, matrixSlot, craftingMatrix.getItem(matrixSlot))) {\n                                return;\n                            }\n                        }\n                    }\n                }\n\n                //read inventory\n                for (int inventorySlot = 0; inventorySlot < player.getInventory().getContainerSize(); inventorySlot++) {\n                    if (checkStack(usedInventoryStacks, ingredient, stack, inventorySlot, player.getInventory().getItem(inventorySlot))) {\n                        return;\n                    }\n                }\n\n                //Check Stored Stacks\n                ItemStackKey key = new ItemStackKey(stack);\n                Integer stored = storedItems.get(key);\n                if (stored != null) {\n                    Integer used = usedStoredStacks.get(key);\n                    int amount = Math.min(ingredient.getMissingAmount(), used == null ? stored : stored - used);\n                    if (amount > 0) {\n                        ingredient.fulfill(amount);\n                        usedStoredStacks.put(key, used == null ? amount : used + amount);\n                    }\n                }\n            });\n        }\n    }\n\n    private boolean checkStack(Map<Integer, Integer> usedMatrixStacks, Ingredient ingredient, ItemStack stack, int slot, ItemStack stackInSlot) {\n        if (API.instance().getComparer().isEqual(stack, stackInSlot, IComparer.COMPARE_NBT)) {\n            Integer used = usedMatrixStacks.get(slot);\n            int amount = Math.min(ingredient.getMissingAmount(), used == null ? stackInSlot.getCount() : stackInSlot.getCount() - used);\n            if (amount > 0) {\n                ingredient.fulfill(amount);\n                usedMatrixStacks.put(slot, used == null ? amount : used + amount);\n            }\n            return ingredient.isAvailable();\n        }\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/integration/jei/JeiHelper.java",
    "content": "package com.refinedmods.refinedstorage.integration.jei;\n\nimport mezz.jei.api.ingredients.ITypedIngredient;\nimport mezz.jei.api.runtime.IClickableIngredient;\nimport mezz.jei.api.runtime.IIngredientManager;\nimport net.minecraft.client.renderer.Rect2i;\nimport java.util.Optional;\n\npublic class JeiHelper {\n    private final IIngredientManager ingredientManager;\n\n    public JeiHelper(IIngredientManager ingredientManager) {\n        this.ingredientManager = ingredientManager;\n    }\n\n    public Optional<IClickableIngredient<?>> makeClickableIngredient(Object ingredient, Rect2i area) {\n        return ingredientManager.createTypedIngredient(ingredient).map(ti -> new ClickableIngredient<>(ti, area));\n    }\n\n    private record ClickableIngredient<T>(ITypedIngredient<T> ingredient,\n                                          Rect2i area) implements IClickableIngredient<T> {\n        @Override\n        public ITypedIngredient<T> getTypedIngredient() {\n            return ingredient;\n        }\n\n        @Override\n        public Rect2i getArea() {\n            return area;\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/integration/jei/JeiIntegration.java",
    "content": "package com.refinedmods.refinedstorage.integration.jei;\n\nimport net.neoforged.fml.ModList;\n\npublic final class JeiIntegration {\n    private JeiIntegration() {\n    }\n\n    public static boolean isLoaded() {\n        return ModList.get().isLoaded(\"jei\");\n    }\n}\n\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/integration/jei/RSJeiPlugin.java",
    "content": "package com.refinedmods.refinedstorage.integration.jei;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.recipe.CoverRecipe;\nimport com.refinedmods.refinedstorage.recipe.HollowCoverRecipe;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport mezz.jei.api.IModPlugin;\nimport mezz.jei.api.JeiPlugin;\nimport mezz.jei.api.registration.IGuiHandlerRegistration;\nimport mezz.jei.api.registration.IRecipeTransferRegistration;\nimport mezz.jei.api.registration.ISubtypeRegistration;\nimport mezz.jei.api.registration.IVanillaCategoryExtensionRegistration;\nimport mezz.jei.api.runtime.IJeiRuntime;\nimport net.minecraft.resources.ResourceLocation;\n\n@JeiPlugin\npublic class RSJeiPlugin implements IModPlugin {\n    private static final ResourceLocation ID = new ResourceLocation(RS.ID, \"plugin\");\n\n    private static IJeiRuntime runtime;\n\n    public static IJeiRuntime getRuntime() {\n        return runtime;\n    }\n\n    @Override\n    public ResourceLocation getPluginUid() {\n        return ID;\n    }\n\n    @Override\n    public void registerRecipeTransferHandlers(IRecipeTransferRegistration registration) {\n        registration.addUniversalRecipeTransferHandler(GridRecipeTransferHandler.INSTANCE);\n    }\n\n    @Override\n    public void registerGuiHandlers(IGuiHandlerRegistration registration) {\n        JeiHelper jeiHelper = new JeiHelper(registration.getJeiHelpers().getIngredientManager());\n        registration.addGenericGuiContainerHandler(BaseScreen.class, new GuiContainerHandler(jeiHelper));\n        registration.addGhostIngredientHandler(BaseScreen.class, new GhostIngredientHandler());\n    }\n\n    @Override\n    public void onRuntimeAvailable(IJeiRuntime runtime) {\n        RSJeiPlugin.runtime = runtime;\n    }\n\n    @Override\n    public void registerItemSubtypes(ISubtypeRegistration registration) {\n        registration.useNbtForSubtypes(RSItems.COVER.get(), RSItems.HOLLOW_COVER.get());\n    }\n\n    @Override\n    public void registerVanillaCategoryExtensions(IVanillaCategoryExtensionRegistration registration) {\n        registration.getCraftingCategory().addExtension(CoverRecipe.class, new CoverCraftingCategoryExtension());\n        registration.getCraftingCategory().addExtension(HollowCoverRecipe.class, new HollowCoverCraftingCategoryExtension());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/integration/jei/RecipeTransferCraftingGridError.java",
    "content": "package com.refinedmods.refinedstorage.integration.jei;\n\nimport mezz.jei.api.gui.ingredient.IRecipeSlotsView;\nimport mezz.jei.api.recipe.transfer.IRecipeTransferError;\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.network.chat.Component;\n\nimport java.awt.*;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class RecipeTransferCraftingGridError implements IRecipeTransferError {\n    protected static final Color AUTOCRAFTING_HIGHLIGHT_COLOR = new Color(0.0f, 0.0f, 1.0f, 0.4f);\n    private static final Color MISSING_HIGHLIGHT_COLOR = new Color(1.0f, 0.0f, 0.0f, 0.4f);\n    private static final boolean HOST_OS_IS_MACOS = System.getProperty(\"os.name\").equals(\"Mac OS X\");\n    protected final Ingredient.IngredientList ingredientList;\n\n\n    public RecipeTransferCraftingGridError(Ingredient.IngredientList ingredientList) {\n        this.ingredientList = ingredientList;\n    }\n\n    @Override\n    public Type getType() {\n        return Type.COSMETIC;\n    }\n\n    @Override\n    public int getButtonHighlightColor() {\n        if (ingredientList.hasMissingButAutocraftingAvailable()) {\n            return AUTOCRAFTING_HIGHLIGHT_COLOR.getRGB();\n        } else if (ingredientList.hasMissing()) {\n            return MISSING_HIGHLIGHT_COLOR.getRGB();\n        }\n        return IRecipeTransferError.super.getButtonHighlightColor();\n    }\n\n    @Override\n    public void showError(GuiGraphics graphics, int mouseX, int mouseY, IRecipeSlotsView recipeSlotsView, int recipeX, int recipeY) {\n        graphics.pose().translate(recipeX, recipeY, 0);\n        List<Component> message = drawIngredientHighlights(graphics, recipeX, recipeY);\n        graphics.renderComponentTooltip(Minecraft.getInstance().font, message, mouseX, mouseY);\n    }\n\n    protected List<Component> drawIngredientHighlights(GuiGraphics graphics, int recipeX, int recipeY) {\n        List<Component> message = new ArrayList<>();\n        message.add(Component.translatable(\"jei.tooltip.transfer\"));\n\n        boolean craftMessage = false;\n        boolean missingMessage = false;\n\n        for (Ingredient ingredient : ingredientList.ingredients) {\n            if (!ingredient.isAvailable()) {\n                if (ingredient.isCraftable()) {\n                    ingredient.getSlotView().drawHighlight(graphics, AUTOCRAFTING_HIGHLIGHT_COLOR.getRGB());\n                    craftMessage = true;\n                } else {\n                    ingredient.getSlotView().drawHighlight(graphics, MISSING_HIGHLIGHT_COLOR.getRGB());\n                    missingMessage = true;\n                }\n            }\n        }\n\n        if (missingMessage) {\n            message.add(Component.translatable(\"jei.tooltip.error.recipe.transfer.missing\").withStyle(ChatFormatting.RED));\n        }\n\n        if (craftMessage) {\n            if (HOST_OS_IS_MACOS) {\n                message.add(Component.translatable(\"gui.refinedstorage.jei.transfer.request_autocrafting_mac\").withStyle(ChatFormatting.BLUE));\n            } else {\n                message.add(Component.translatable(\"gui.refinedstorage.jei.transfer.request_autocrafting\").withStyle(ChatFormatting.BLUE));\n            }\n        }\n\n        return message;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/integration/jei/RecipeTransferPatternGridError.java",
    "content": "package com.refinedmods.refinedstorage.integration.jei;\n\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.network.chat.Component;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class RecipeTransferPatternGridError extends RecipeTransferCraftingGridError {\n    public RecipeTransferPatternGridError(Ingredient.IngredientList ingredients) {\n        super(ingredients);\n    }\n\n    @Override\n    protected List<Component> drawIngredientHighlights(GuiGraphics graphics, int recipeX, int recipeY) {\n        List<Component> message = new ArrayList<>();\n        message.add(Component.translatable(\"jei.tooltip.transfer\"));\n\n        boolean craftMessage = false;\n\n        for (Ingredient ingredient : ingredientList.ingredients) {\n            if (ingredient.isCraftable()) {\n                ingredient.getSlotView().drawHighlight(graphics, AUTOCRAFTING_HIGHLIGHT_COLOR.getRGB());\n                craftMessage = true;\n            }\n        }\n\n        if (craftMessage) {\n            message.add(Component.translatable(\"gui.refinedstorage.jei.transfer.autocrafting_available\").withStyle(ChatFormatting.BLUE));\n        }\n\n        return message;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/inventory/fluid/ConfiguredFluidsInFilterItemHandler.java",
    "content": "package com.refinedmods.refinedstorage.inventory.fluid;\n\nimport com.refinedmods.refinedstorage.item.FilterItem;\nimport net.minecraft.core.NonNullList;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\n\npublic class ConfiguredFluidsInFilterItemHandler extends FluidInventory {\n    public ConfiguredFluidsInFilterItemHandler(ItemStack stack) {\n        super(27, Integer.MAX_VALUE);\n\n        this.addListener((handler, slot, reading) -> {\n            if (!stack.hasTag()) {\n                stack.setTag(new CompoundTag());\n            }\n\n            stack.getTag().put(FilterItem.NBT_FLUID_FILTERS, writeToNbt());\n        });\n\n        if (stack.hasTag() && stack.getTag().contains(FilterItem.NBT_FLUID_FILTERS)) {\n            readFromNbt(stack.getTag().getCompound(FilterItem.NBT_FLUID_FILTERS));\n        }\n    }\n\n    public NonNullList<FluidStack> getConfiguredFluids() {\n        NonNullList<FluidStack> list = NonNullList.create();\n\n        for (FluidStack fluid : this.getFluids()) {\n            if (fluid != null) {\n                list.add(fluid);\n            }\n        }\n\n        return list;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/inventory/fluid/ConfiguredIconInFluidFilterItemHandler.java",
    "content": "package com.refinedmods.refinedstorage.inventory.fluid;\n\nimport com.refinedmods.refinedstorage.item.FilterItem;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\n\npublic class ConfiguredIconInFluidFilterItemHandler extends FluidInventory {\n    public ConfiguredIconInFluidFilterItemHandler(ItemStack stack) {\n        super(1, Integer.MAX_VALUE);\n\n        this.addListener((handler, slot, reading) -> {\n            if (!stack.hasTag()) {\n                stack.setTag(new CompoundTag());\n            }\n\n            FilterItem.setFluidIcon(stack, getFluid(slot));\n        });\n\n        FluidStack icon = FilterItem.getFluidIcon(stack);\n        if (!icon.isEmpty()) {\n            setFluid(0, icon);\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/inventory/fluid/FluidInventory.java",
    "content": "package com.refinedmods.refinedstorage.inventory.fluid;\n\nimport com.refinedmods.refinedstorage.inventory.listener.InventoryListener;\nimport net.minecraft.nbt.CompoundTag;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nonnull;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class FluidInventory {\n    private static final String NBT_SLOT = \"Slot_%d\";\n\n    private final List<InventoryListener<FluidInventory>> listeners = new ArrayList<>();\n\n    private final FluidStack[] fluids;\n    private final int maxAmount;\n    private boolean empty = true;\n\n    public FluidInventory(int size, int maxAmount) {\n        this.fluids = new FluidStack[size];\n\n        for (int i = 0; i < size; ++i) {\n            fluids[i] = FluidStack.EMPTY;\n        }\n\n        this.maxAmount = maxAmount;\n    }\n\n    public FluidInventory(int size) {\n        this(size, Integer.MAX_VALUE);\n    }\n\n    public FluidInventory addListener(InventoryListener<FluidInventory> listener) {\n        listeners.add(listener);\n\n        return this;\n    }\n\n    public int getSlots() {\n        return fluids.length;\n    }\n\n    public int getMaxAmount() {\n        return maxAmount;\n    }\n\n    public FluidStack[] getFluids() {\n        return fluids;\n    }\n\n    @Nonnull\n    public FluidStack getFluid(int slot) {\n        return fluids[slot];\n    }\n\n    public void setFluid(int slot, @Nonnull FluidStack stack) {\n        if (stack.getAmount() > maxAmount) {\n            throw new IllegalArgumentException(\"Fluid size is invalid (given: \" + stack.getAmount() + \", max size: \" + maxAmount + \")\");\n        }\n\n        fluids[slot] = stack;\n\n        onChanged(slot);\n    }\n\n    public void onChanged(int slot) {\n        listeners.forEach(l -> l.onChanged(this, slot, false));\n        updateEmptyState();\n    }\n\n    public CompoundTag writeToNbt() {\n        CompoundTag tag = new CompoundTag();\n\n        for (int i = 0; i < getSlots(); ++i) {\n            FluidStack stack = getFluid(i);\n\n            if (!stack.isEmpty()) {\n                tag.put(String.format(NBT_SLOT, i), stack.writeToNBT(new CompoundTag()));\n            }\n        }\n\n        return tag;\n    }\n\n    public void readFromNbt(CompoundTag tag) {\n        for (int i = 0; i < getSlots(); ++i) {\n            String key = String.format(NBT_SLOT, i);\n\n            if (tag.contains(key)) {\n                fluids[i] = FluidStack.loadFluidStackFromNBT(tag.getCompound(key));\n            }\n        }\n\n        updateEmptyState();\n    }\n\n    private void updateEmptyState() {\n        this.empty = true;\n\n        for (FluidStack fluid : fluids) {\n            if (!fluid.isEmpty()) {\n                this.empty = false;\n\n                return;\n            }\n        }\n    }\n\n    public boolean isEmpty() {\n        return empty;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/inventory/fluid/ProxyFluidHandler.java",
    "content": "package com.refinedmods.refinedstorage.inventory.fluid;\n\nimport javax.annotation.Nonnull;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.fluids.capability.IFluidHandler;\nimport net.neoforged.neoforge.fluids.capability.templates.FluidTank;\n\npublic class ProxyFluidHandler implements IFluidHandler {\n    private final FluidTank insertHandler;\n    private final FluidTank extractHandler;\n\n    public ProxyFluidHandler(FluidTank insertHandler, FluidTank extractHandler) {\n        this.insertHandler = insertHandler;\n        this.extractHandler = extractHandler;\n    }\n\n    @Override\n    public int getTanks() {\n        return 2;\n    }\n\n    @Nonnull\n    @Override\n    public FluidStack getFluidInTank(int tank) {\n        return tank == 0 ? insertHandler.getFluidInTank(0) : extractHandler.getFluidInTank(0);\n    }\n\n    @Override\n    public int getTankCapacity(int tank) {\n        return tank == 0 ? insertHandler.getTankCapacity(0) : extractHandler.getTankCapacity(0);\n    }\n\n    @Override\n    public boolean isFluidValid(int tank, @Nonnull FluidStack stack) {\n        return tank == 0 ? insertHandler.isFluidValid(0, stack) : extractHandler.isFluidValid(0, stack);\n\n    }\n\n    @Override\n    public int fill(FluidStack resource, FluidAction action) {\n        return insertHandler.fill(resource, action);\n    }\n\n    @Nonnull\n    @Override\n    public FluidStack drain(FluidStack resource, FluidAction action) {\n        return extractHandler.drain(resource, action);\n    }\n\n    @Nonnull\n    @Override\n    public FluidStack drain(int maxDrain, FluidAction action) {\n        return extractHandler.drain(maxDrain, action);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/inventory/item/BaseItemHandler.java",
    "content": "package com.refinedmods.refinedstorage.inventory.item;\n\nimport com.refinedmods.refinedstorage.inventory.listener.InventoryListener;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.ItemStackHandler;\nimport javax.annotation.Nonnull;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.function.Predicate;\n\npublic class BaseItemHandler extends ItemStackHandler {\n    private final List<InventoryListener<BaseItemHandler>> listeners = new ArrayList<>();\n    private final List<Predicate<ItemStack>> validators = new ArrayList<>();\n\n    private boolean empty = true;\n    private boolean reading;\n\n    public BaseItemHandler(int size) {\n        super(size);\n    }\n\n    public BaseItemHandler addValidator(Predicate<ItemStack> validator) {\n        validators.add(validator);\n\n        return this;\n    }\n\n    public BaseItemHandler addListener(InventoryListener<BaseItemHandler> listener) {\n        listeners.add(listener);\n\n        return this;\n    }\n\n    @Override\n    @Nonnull\n    public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) {\n        if (!validators.isEmpty()) {\n            for (Predicate<ItemStack> validator : validators) {\n                if (validator.test(stack)) {\n                    return super.insertItem(slot, stack, simulate);\n                }\n            }\n\n            return stack;\n        }\n\n        return super.insertItem(slot, stack, simulate);\n    }\n\n    @Override\n    protected void onContentsChanged(int slot) {\n        super.onContentsChanged(slot);\n\n        onChanged(slot);\n    }\n\n    public void onChanged(int slot) {\n        this.empty = stacks.stream().allMatch(ItemStack::isEmpty);\n        this.listeners.forEach(l -> l.onChanged(this, slot, reading));\n    }\n\n    @Override\n    public void deserializeNBT(CompoundTag tag) {\n        super.deserializeNBT(tag);\n\n        this.empty = stacks.stream().allMatch(ItemStack::isEmpty);\n    }\n\n    public boolean isEmpty() {\n        return empty;\n    }\n\n    public void setReading(boolean reading) {\n        this.reading = reading;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/inventory/item/ConfiguredIconInFilterItemHandler.java",
    "content": "package com.refinedmods.refinedstorage.inventory.item;\n\nimport com.refinedmods.refinedstorage.item.FilterItem;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.ItemStackHandler;\n\npublic class ConfiguredIconInFilterItemHandler extends ItemStackHandler {\n    private final ItemStack filterItem;\n\n    public ConfiguredIconInFilterItemHandler(ItemStack filterItem) {\n        super(1);\n\n        this.filterItem = filterItem;\n\n        setStackInSlot(0, FilterItem.getIcon(filterItem));\n    }\n\n    @Override\n    protected void onContentsChanged(int slot) {\n        super.onContentsChanged(slot);\n\n        FilterItem.setIcon(filterItem, getStackInSlot(0));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/inventory/item/ConfiguredItemsInFilterItemHandler.java",
    "content": "package com.refinedmods.refinedstorage.inventory.item;\n\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.core.NonNullList;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.ItemStackHandler;\n\npublic class ConfiguredItemsInFilterItemHandler extends ItemStackHandler {\n    private final ItemStack stack;\n\n    public ConfiguredItemsInFilterItemHandler(ItemStack stack) {\n        super(27);\n\n        this.stack = stack;\n\n        if (stack.hasTag()) {\n            StackUtils.readItems(this, 0, stack.getTag());\n        }\n    }\n\n    @Override\n    protected void onContentsChanged(int slot) {\n        super.onContentsChanged(slot);\n\n        if (!stack.hasTag()) {\n            stack.setTag(new CompoundTag());\n        }\n\n        StackUtils.writeItems(this, 0, stack.getTag());\n    }\n\n    public NonNullList<ItemStack> getConfiguredItems() {\n        return stacks;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/inventory/item/FilterItemHandler.java",
    "content": "package com.refinedmods.refinedstorage.inventory.item;\n\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.api.network.grid.IGridTab;\nimport com.refinedmods.refinedstorage.api.util.IFilter;\nimport com.refinedmods.refinedstorage.apiimpl.network.grid.GridTab;\nimport com.refinedmods.refinedstorage.apiimpl.util.FluidFilter;\nimport com.refinedmods.refinedstorage.apiimpl.util.ItemFilter;\nimport com.refinedmods.refinedstorage.inventory.fluid.ConfiguredFluidsInFilterItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.validator.ItemValidator;\nimport com.refinedmods.refinedstorage.item.FilterItem;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.screen.grid.GridScreen;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.fml.LogicalSide;\nimport net.neoforged.fml.util.thread.EffectiveSide;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class FilterItemHandler extends BaseItemHandler {\n    private final List<IFilter> filters;\n    private final List<IGridTab> tabs;\n\n    public FilterItemHandler(List<IFilter> filters, List<IGridTab> tabs) {\n        super(4);\n\n        this.filters = filters;\n        this.tabs = tabs;\n\n        this.addValidator(new ItemValidator(RSItems.FILTER.get()));\n    }\n\n    @Override\n    protected void onContentsChanged(int slot) {\n        super.onContentsChanged(slot);\n\n        filters.clear();\n        tabs.clear();\n\n        for (int i = 0; i < getSlots(); ++i) {\n            ItemStack filterItem = getStackInSlot(i);\n            if (!filterItem.isEmpty()) {\n                handleFilterItem(filterItem);\n            }\n        }\n\n        if (EffectiveSide.get() == LogicalSide.CLIENT) {\n            BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort());\n        }\n    }\n\n    private void handleFilterItem(ItemStack filterItem) {\n        ItemStack icon = FilterItem.getIcon(filterItem);\n        FluidStack fluidIcon = FilterItem.getFluidIcon(filterItem);\n        int compare = FilterItem.getCompare(filterItem);\n        int mode = FilterItem.getMode(filterItem);\n        boolean modFilter = FilterItem.isModFilter(filterItem);\n\n        List<IFilter> foundFilters = new ArrayList<>();\n\n        for (ItemStack stack : new ConfiguredItemsInFilterItemHandler(filterItem).getConfiguredItems()) {\n            if (stack.getItem() == RSItems.FILTER.get()) {\n                handleFilterItem(stack);\n            } else if (!stack.isEmpty()) {\n                foundFilters.add(new ItemFilter(stack, compare, mode, modFilter));\n            }\n        }\n\n        for (FluidStack stack : new ConfiguredFluidsInFilterItemHandler(filterItem).getConfiguredFluids()) {\n            foundFilters.add(new FluidFilter(stack, compare, mode, modFilter));\n        }\n\n        if (icon.isEmpty() && fluidIcon.isEmpty()) {\n            filters.addAll(foundFilters);\n        } else {\n            tabs.add(new GridTab(foundFilters, FilterItem.getFilterName(filterItem), icon, fluidIcon));\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/inventory/item/ProxyItemHandler.java",
    "content": "package com.refinedmods.refinedstorage.inventory.item;\n\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport javax.annotation.Nonnull;\n\npublic class ProxyItemHandler implements IItemHandler {\n    private final IItemHandler insertHandler;\n    private final IItemHandler extractHandler;\n\n    public ProxyItemHandler(IItemHandler insertHandler, IItemHandler extractHandler) {\n        this.insertHandler = insertHandler;\n        this.extractHandler = extractHandler;\n    }\n\n    @Override\n    public int getSlots() {\n        return insertHandler.getSlots() + extractHandler.getSlots();\n    }\n\n    @Nonnull\n    @Override\n    public ItemStack getStackInSlot(int slot) {\n        return slot < insertHandler.getSlots() ? insertHandler.getStackInSlot(slot) : extractHandler.getStackInSlot(slot - insertHandler.getSlots());\n    }\n\n    @Nonnull\n    @Override\n    public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) {\n        return slot < insertHandler.getSlots() ? insertHandler.insertItem(slot, stack, simulate) : stack;\n    }\n\n    @Nonnull\n    @Override\n    public ItemStack extractItem(int slot, int amount, boolean simulate) {\n        return slot >= insertHandler.getSlots() ? extractHandler.extractItem(slot - insertHandler.getSlots(), amount, simulate) : ItemStack.EMPTY;\n    }\n\n    @Override\n    public int getSlotLimit(int slot) {\n        return slot < insertHandler.getSlots() ? insertHandler.getSlotLimit(slot) : extractHandler.getSlotLimit(slot - insertHandler.getSlots());\n    }\n\n    @Override\n    public boolean isItemValid(int slot, @Nonnull ItemStack stack) {\n        return slot < insertHandler.getSlots() ? insertHandler.isItemValid(slot, stack) : extractHandler.isItemValid(slot - extractHandler.getSlots(), stack);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/inventory/item/UpgradeItemHandler.java",
    "content": "package com.refinedmods.refinedstorage.inventory.item;\n\nimport com.refinedmods.refinedstorage.inventory.item.validator.UpgradeItemValidator;\nimport com.refinedmods.refinedstorage.item.UpgradeItem;\nimport net.minecraft.world.item.ItemStack;\n\npublic class UpgradeItemHandler extends BaseItemHandler {\n    public UpgradeItemHandler(int size, UpgradeItem.Type... supportedUpgrades) {\n        super(size);\n\n        for (UpgradeItem.Type supportedUpgrade : supportedUpgrades) {\n            addValidator(new UpgradeItemValidator(supportedUpgrade));\n        }\n    }\n\n    public int getSpeed() {\n        return getSpeed(9, 2);\n    }\n\n    public int getSpeed(int speed, int speedIncrease) {\n        for (int i = 0; i < getSlots(); ++i) {\n            ItemStack slot = getStackInSlot(i);\n\n            if (slot.getItem() instanceof UpgradeItem && ((UpgradeItem) slot.getItem()).getType() == UpgradeItem.Type.SPEED) {\n                speed -= speedIncrease;\n            }\n        }\n\n        return speed;\n    }\n\n    public boolean hasUpgrade(UpgradeItem.Type type) {\n        for (int i = 0; i < getSlots(); ++i) {\n            ItemStack slot = getStackInSlot(i);\n\n            if (slot.getItem() instanceof UpgradeItem && ((UpgradeItem) slot.getItem()).getType() == type) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public int getUpgradeCount(UpgradeItem.Type type) {\n        int upgrades = 0;\n\n        for (int i = 0; i < getSlots(); ++i) {\n            ItemStack slot = getStackInSlot(i);\n\n            if (slot.getItem() instanceof UpgradeItem && ((UpgradeItem) slot.getItem()).getType() == type) {\n                upgrades++;\n            }\n        }\n\n        return upgrades;\n    }\n\n    public int getEnergyUsage() {\n        int usage = 0;\n\n        for (int i = 0; i < getSlots(); ++i) {\n            ItemStack slot = getStackInSlot(i);\n\n            if (slot.getItem() instanceof UpgradeItem) {\n                usage += ((UpgradeItem) slot.getItem()).getType().getEnergyUsage();\n            }\n        }\n\n        return usage;\n    }\n\n    public int getStackInteractCount() {\n        return hasUpgrade(UpgradeItem.Type.STACK) ? 64 : 1;\n    }\n\n    @Override\n    public int getSlotLimit(int slot) {\n        return 1;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/inventory/item/validator/ItemValidator.java",
    "content": "package com.refinedmods.refinedstorage.inventory.item.validator;\n\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\n\nimport java.util.function.Predicate;\n\npublic class ItemValidator implements Predicate<ItemStack> {\n    private final Item item;\n\n    public ItemValidator(Item item) {\n        this.item = item;\n    }\n\n    @Override\n    public boolean test(ItemStack stack) {\n        return stack.getItem() == item;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/inventory/item/validator/PatternItemValidator.java",
    "content": "package com.refinedmods.refinedstorage.inventory.item.validator;\n\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternProvider;\nimport com.refinedmods.refinedstorage.item.PatternItem;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\n\nimport java.util.function.Predicate;\n\npublic class PatternItemValidator implements Predicate<ItemStack> {\n    private final Level level;\n\n    public PatternItemValidator(Level level) {\n        this.level = level;\n    }\n\n    @Override\n    public boolean test(ItemStack stack) {\n        if (stack.getItem() == RSItems.PATTERN.get()) {\n            return PatternItem.fromCache(level, stack).isValid();\n        }\n        return stack.getItem() instanceof ICraftingPatternProvider && ((ICraftingPatternProvider) stack.getItem()).create(level, stack, null).isValid();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/inventory/item/validator/StorageDiskItemValidator.java",
    "content": "package com.refinedmods.refinedstorage.inventory.item.validator;\n\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskProvider;\nimport net.minecraft.world.item.ItemStack;\n\nimport java.util.function.Predicate;\n\npublic class StorageDiskItemValidator implements Predicate<ItemStack> {\n    @Override\n    public boolean test(ItemStack stack) {\n        return stack.getItem() instanceof IStorageDiskProvider && ((IStorageDiskProvider) stack.getItem()).isValid(stack);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/inventory/item/validator/UpgradeItemValidator.java",
    "content": "package com.refinedmods.refinedstorage.inventory.item.validator;\n\nimport com.refinedmods.refinedstorage.item.UpgradeItem;\nimport net.minecraft.world.item.ItemStack;\n\nimport java.util.function.Predicate;\n\npublic class UpgradeItemValidator implements Predicate<ItemStack> {\n    private final UpgradeItem.Type type;\n\n    public UpgradeItemValidator(UpgradeItem.Type type) {\n        this.type = type;\n    }\n\n    @Override\n    public boolean test(ItemStack stack) {\n        return stack.getItem() instanceof UpgradeItem && ((UpgradeItem) stack.getItem()).getType() == type;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/inventory/listener/BlockEntityInventoryListener.java",
    "content": "package com.refinedmods.refinedstorage.inventory.listener;\n\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport net.minecraft.world.level.block.entity.BlockEntity;\n\npublic class BlockEntityInventoryListener implements InventoryListener<BaseItemHandler> {\n    private final BlockEntity blockEntity;\n\n    public BlockEntityInventoryListener(BlockEntity blockEntity) {\n        this.blockEntity = blockEntity;\n    }\n\n    @Override\n    public void onChanged(BaseItemHandler handler, int slot, boolean reading) {\n        if (!reading) {\n            blockEntity.setChanged();\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/inventory/listener/InventoryListener.java",
    "content": "package com.refinedmods.refinedstorage.inventory.listener;\n\npublic interface InventoryListener<T> {\n    void onChanged(T handler, int slot, boolean reading);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/inventory/listener/NetworkNodeFluidInventoryListener.java",
    "content": "package com.refinedmods.refinedstorage.inventory.listener;\n\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\n\npublic class NetworkNodeFluidInventoryListener implements InventoryListener<FluidInventory> {\n    private final INetworkNode node;\n\n    public NetworkNodeFluidInventoryListener(INetworkNode node) {\n        this.node = node;\n    }\n\n    @Override\n    public void onChanged(FluidInventory handler, int slot, boolean reading) {\n        if (!reading) {\n            node.markDirty();\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/inventory/listener/NetworkNodeInventoryListener.java",
    "content": "package com.refinedmods.refinedstorage.inventory.listener;\n\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\n\npublic class NetworkNodeInventoryListener implements InventoryListener<BaseItemHandler> {\n    private final INetworkNode node;\n\n    public NetworkNodeInventoryListener(INetworkNode node) {\n        this.node = node;\n    }\n\n    @Override\n    public void onChanged(BaseItemHandler handler, int slot, boolean reading) {\n        if (!reading) {\n            node.markDirty();\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/inventory/player/PlayerSlot.java",
    "content": "package com.refinedmods.refinedstorage.inventory.player;\n\nimport com.refinedmods.refinedstorage.integration.curios.CuriosIntegration;\nimport com.refinedmods.refinedstorage.util.PacketBufferUtils;\n\nimport java.util.Optional;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport top.theillusivec4.curios.api.CuriosApi;\nimport top.theillusivec4.curios.api.type.capability.ICuriosItemHandler;\nimport top.theillusivec4.curios.api.type.inventory.ICurioStacksHandler;\n\npublic class PlayerSlot {\n    int slot;\n    String curioSlot;\n\n    public PlayerSlot(int slot, String curioSlot) {\n        this.slot = slot;\n        this.curioSlot = curioSlot;\n    }\n\n    public PlayerSlot(int slot) {\n        this.slot = slot;\n    }\n\n    public PlayerSlot(FriendlyByteBuf buffer) {\n        slot = buffer.readInt();\n\n        if (buffer.readBoolean()) {\n            curioSlot = PacketBufferUtils.readString(buffer);\n        }\n    }\n\n    public static PlayerSlot getSlotForHand(Player player, InteractionHand hand) {\n        if (hand == InteractionHand.MAIN_HAND) {\n            return new PlayerSlot(player.getInventory().selected);\n        }\n        return new PlayerSlot(Inventory.SLOT_OFFHAND);\n    }\n\n    public ItemStack getStackFromSlot(Player player) {\n        if (curioSlot == null || !CuriosIntegration.isLoaded()) {\n            return player.getInventory().getItem(slot);\n        }\n\n        Optional<ICuriosItemHandler> curiosInventory = CuriosApi.getCuriosInventory(player);\n\n        Optional<ICurioStacksHandler> stacksHandler = curiosInventory.flatMap((handler ->\n            handler.getStacksHandler(curioSlot)\n        ));\n\n        Optional<ItemStack> stack = stacksHandler.map(handler -> handler.getStacks().getStackInSlot(slot));\n\n        return stack.orElse(ItemStack.EMPTY);\n    }\n\n    public void writePlayerSlot(FriendlyByteBuf buffer) {\n        buffer.writeInt(slot);\n        buffer.writeBoolean(curioSlot != null);\n        if (curioSlot != null) {\n            buffer.writeUtf(curioSlot);\n        }\n    }\n\n    public int getSlotIdInPlayerInventory() {\n        if (curioSlot != null) {\n            return -1;\n        }\n        return slot;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/CoreItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport net.minecraft.world.item.Item;\n\npublic class CoreItem extends Item {\n    public CoreItem() {\n        super(new Item.Properties());\n    }\n\n    public enum Type {\n        CONSTRUCTION,\n        DESTRUCTION\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/CoverItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport com.refinedmods.refinedstorage.api.network.node.ICoverable;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.Cover;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverType;\nimport com.refinedmods.refinedstorage.block.CableBlock;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.TooltipFlag;\nimport net.minecraft.world.item.context.UseOnContext;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.List;\n\npublic class CoverItem extends Item {\n    private static final String NBT_ITEM = \"Item\";\n\n    public CoverItem() {\n        super(new Item.Properties());\n    }\n\n    public static void setItem(ItemStack cover, ItemStack item) {\n        if (!cover.hasTag()) {\n            cover.setTag(new CompoundTag());\n        }\n        ItemStack result = item.copy();\n        result.setCount(1);\n        cover.getTag().put(NBT_ITEM, result.save(new CompoundTag()));\n    }\n\n    @Nonnull\n    public static ItemStack getItem(ItemStack cover) {\n        if (!cover.hasTag() || !cover.getTag().contains(NBT_ITEM)) {\n            return ItemStack.EMPTY;\n        }\n\n        return ItemStack.of(cover.getTag().getCompound(NBT_ITEM));\n    }\n\n    @Override\n    public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {\n        super.appendHoverText(stack, level, tooltip, flag);\n        ItemStack item = getItem(stack);\n\n        if (!item.isEmpty()) {\n            tooltip.add(item.getItem().getName(item).copy().withStyle(ChatFormatting.GRAY));\n        }\n    }\n\n    @Override\n    public InteractionResult useOn(UseOnContext context) {\n        BlockPos pos = context.getClickedPos();\n        Direction facing = context.getClickedFace();\n        Level level = context.getLevel();\n\n        ItemStack stack = context.getPlayer().getItemInHand(context.getHand());\n\n        BlockEntity blockEntity = level.getBlockEntity(pos);\n\n        // Support placing on the bottom side without too much hassle.\n        if (!canPlaceOn(level, pos, facing)) {\n            pos = pos.above();\n\n            facing = Direction.DOWN;\n\n            blockEntity = level.getBlockEntity(pos);\n        }\n\n        if (canPlaceOn(level, pos, facing)) {\n            if (level.isClientSide) {\n                level.getModelDataManager().requestRefresh(blockEntity);\n                return InteractionResult.SUCCESS;\n            }\n\n            INetworkNode node = ((NetworkNodeBlockEntity<?>) blockEntity).getNode();\n\n            if (node.getNetwork() != null && !node.getNetwork().getSecurityManager().hasPermission(Permission.BUILD, context.getPlayer())) {\n                LevelUtils.sendNoPermissionMessage(context.getPlayer());\n\n                return InteractionResult.FAIL;\n            }\n\n            if (((ICoverable) node).getCoverManager().setCover(facing, createCover(getItem(stack)))) {\n                context.getPlayer().getItemInHand(context.getHand()).shrink(1);\n\n                LevelUtils.updateBlock(level, pos);\n                API.instance().getNetworkNodeManager((ServerLevel) level).markForSaving();\n                return InteractionResult.SUCCESS;\n            }\n\n            return InteractionResult.FAIL;\n        }\n\n        return InteractionResult.PASS;\n    }\n\n    private boolean canPlaceOn(Level level, BlockPos pos, Direction facing) {\n        return level.getBlockEntity(pos) instanceof NetworkNodeBlockEntity\n            && ((NetworkNodeBlockEntity<?>) level.getBlockEntity(pos)).getNode() instanceof ICoverable\n            && !CableBlock.hasVisualConnectionOnSide(level.getBlockState(pos), facing);\n    }\n\n    protected Cover createCover(ItemStack stack) {\n        return new Cover(stack, CoverType.NORMAL);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/EnergyItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport com.refinedmods.refinedstorage.energy.ItemEnergyStorage;\nimport com.refinedmods.refinedstorage.render.Styles;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.util.Mth;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.TooltipFlag;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.capabilities.Capabilities;\nimport net.neoforged.neoforge.energy.EnergyStorage;\nimport net.neoforged.neoforge.energy.IEnergyStorage;\nimport javax.annotation.Nullable;\nimport java.util.List;\nimport java.util.function.Supplier;\n\npublic abstract class EnergyItem extends Item {\n    private final Supplier<Integer> energyCapacity;\n    private final boolean creative;\n\n    protected EnergyItem(Item.Properties properties, boolean creative, Supplier<Integer> energyCapacity) {\n        super(properties);\n\n        this.creative = creative;\n        this.energyCapacity = energyCapacity;\n    }\n\n    public EnergyStorage createEnergyStorage(ItemStack stack) {\n        return new ItemEnergyStorage(stack, energyCapacity.get());\n    }\n\n    @Override\n    public boolean isBarVisible(ItemStack stack) {\n        return !creative;\n    }\n\n    @Override\n    public int getBarWidth(ItemStack stack) {\n        IEnergyStorage energy = stack.getCapability(Capabilities.EnergyStorage.ITEM);\n        if (energy == null) {\n            return 0;\n        }\n        float stored = (float) energy.getEnergyStored() / (float) energy.getMaxEnergyStored();\n        return Math.round(stored * 13F);\n    }\n\n    @Override\n    public int getBarColor(ItemStack stack) {\n        IEnergyStorage energy = stack.getCapability(Capabilities.EnergyStorage.ITEM);\n        if (energy == null) {\n            return super.getBarColor(stack);\n        }\n        return Mth.hsvToRgb(Math.max(0.0F, (float) energy.getEnergyStored() / (float) energy.getMaxEnergyStored()) / 3.0F, 1.0F, 1.0F);\n    }\n\n    @Override\n    public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {\n        super.appendHoverText(stack, level, tooltip, flag);\n\n        if (!creative) {\n            final IEnergyStorage energy = stack.getCapability(Capabilities.EnergyStorage.ITEM);\n            if (energy == null) {\n                return;\n            }\n            tooltip.add(Component.translatable(\"misc.refinedstorage.energy_stored\", energy.getEnergyStored(), energy.getMaxEnergyStored()).setStyle(Styles.GRAY));\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/FilterItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.api.util.IFilter;\nimport com.refinedmods.refinedstorage.container.FilterContainerMenu;\nimport com.refinedmods.refinedstorage.inventory.fluid.ConfiguredFluidsInFilterItemHandler;\nimport com.refinedmods.refinedstorage.inventory.item.ConfiguredItemsInFilterItemHandler;\nimport com.refinedmods.refinedstorage.render.Styles;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.chat.Component;\n\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.InteractionResultHolder;\nimport net.minecraft.world.MenuProvider;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.TooltipFlag;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.List;\n\npublic class FilterItem extends Item {\n    public static final String NBT_FLUID_FILTERS = \"FluidFilters\";\n    private static final String NBT_COMPARE = \"Compare\";\n    private static final String NBT_MODE = \"Mode\";\n    private static final String NBT_MOD_FILTER = \"ModFilter\";\n    private static final String NBT_NAME = \"Name\";\n    private static final String NBT_ICON = \"Icon\";\n    private static final String NBT_FLUID_ICON = \"FluidIcon\";\n    private static final String NBT_TYPE = \"Type\";\n\n    public FilterItem() {\n        super(new Item.Properties().stacksTo(1));\n    }\n\n    public static int getCompare(ItemStack stack) {\n        return (stack.hasTag() && stack.getTag().contains(NBT_COMPARE)) ? stack.getTag().getInt(NBT_COMPARE) : IComparer.COMPARE_NBT;\n    }\n\n    public static void setCompare(ItemStack stack, int compare) {\n        if (!stack.hasTag()) {\n            stack.setTag(new CompoundTag());\n        }\n\n        stack.getTag().putInt(NBT_COMPARE, compare);\n    }\n\n    public static int getMode(ItemStack stack) {\n        return (stack.hasTag() && stack.getTag().contains(NBT_MODE)) ? stack.getTag().getInt(NBT_MODE) : IFilter.MODE_WHITELIST;\n    }\n\n    public static void setMode(ItemStack stack, int mode) {\n        if (!stack.hasTag()) {\n            stack.setTag(new CompoundTag());\n        }\n\n        stack.getTag().putInt(NBT_MODE, mode);\n    }\n\n    public static boolean isModFilter(ItemStack stack) {\n        return stack.hasTag() && stack.getTag().contains(NBT_MOD_FILTER) && stack.getTag().getBoolean(NBT_MOD_FILTER);\n    }\n\n    public static void setModFilter(ItemStack stack, boolean modFilter) {\n        if (!stack.hasTag()) {\n            stack.setTag(new CompoundTag());\n        }\n\n        stack.getTag().putBoolean(NBT_MOD_FILTER, modFilter);\n    }\n\n    public static String getFilterName(ItemStack stack) {\n        return stack.hasTag() && stack.getTag().contains(NBT_NAME) ? stack.getTag().getString(NBT_NAME) : \"\";\n    }\n\n    public static void setName(ItemStack stack, String name) {\n        if (!stack.hasTag()) {\n            stack.setTag(new CompoundTag());\n        }\n\n        stack.getTag().putString(NBT_NAME, name);\n    }\n\n    @Nonnull\n    public static ItemStack getIcon(ItemStack stack) {\n        return stack.hasTag() && stack.getTag().contains(NBT_ICON) ? ItemStack.of(stack.getTag().getCompound(NBT_ICON)) : ItemStack.EMPTY;\n    }\n\n    public static void setIcon(ItemStack stack, ItemStack icon) {\n        if (!stack.hasTag()) {\n            stack.setTag(new CompoundTag());\n        }\n\n        stack.getTag().put(NBT_ICON, icon.save(new CompoundTag()));\n    }\n\n    public static void setFluidIcon(ItemStack stack, @Nullable FluidStack icon) {\n        if (!stack.hasTag()) {\n            stack.setTag(new CompoundTag());\n        }\n\n        if (icon == null) {\n            stack.getTag().remove(NBT_FLUID_ICON);\n        } else {\n            stack.getTag().put(NBT_FLUID_ICON, icon.writeToNBT(new CompoundTag()));\n        }\n    }\n\n    @Nonnull\n    public static FluidStack getFluidIcon(ItemStack stack) {\n        return stack.hasTag() && stack.getTag().contains(NBT_FLUID_ICON) ? FluidStack.loadFluidStackFromNBT(stack.getTag().getCompound(NBT_FLUID_ICON)) : FluidStack.EMPTY;\n    }\n\n    public static int getType(ItemStack stack) {\n        return stack.hasTag() && stack.getTag().contains(NBT_TYPE) ? stack.getTag().getInt(NBT_TYPE) : IType.ITEMS;\n    }\n\n    public static void setType(ItemStack stack, int type) {\n        if (!stack.hasTag()) {\n            stack.setTag(new CompoundTag());\n        }\n\n        stack.getTag().putInt(NBT_TYPE, type);\n    }\n\n    @Override\n    public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {\n        ItemStack stack = player.getItemInHand(hand);\n\n        if (!level.isClientSide) {\n            if (player.isCrouching()) {\n                return new InteractionResultHolder<>(InteractionResult.SUCCESS, new ItemStack(RSItems.FILTER.get()));\n            }\n\n            player.openMenu(new MenuProvider() {\n                @Override\n                public Component getDisplayName() {\n                    return Component.translatable(\"gui.refinedstorage.filter\");\n                }\n\n                @Override\n                public AbstractContainerMenu createMenu(int windowId, Inventory inventory, Player player) {\n                    return new FilterContainerMenu(player, inventory.getSelected(), windowId);\n                }\n            });\n        }\n\n        return new InteractionResultHolder<>(InteractionResult.CONSUME, stack);\n    }\n\n    @Override\n    public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {\n        super.appendHoverText(stack, level, tooltip, flag);\n\n        tooltip.add(Component.translatable(\"sidebutton.refinedstorage.mode.\" + (getMode(stack) == IFilter.MODE_WHITELIST ? \"whitelist\" : \"blacklist\")).setStyle(Styles.YELLOW));\n\n        if (isModFilter(stack)) {\n            tooltip.add(Component.translatable(\"gui.refinedstorage.filter.mod_filter\").setStyle(Styles.BLUE));\n        }\n\n        RenderUtils.addCombinedItemsToTooltip(tooltip, false, new ConfiguredItemsInFilterItemHandler(stack).getConfiguredItems());\n        RenderUtils.addCombinedFluidsToTooltip(tooltip, false, new ConfiguredFluidsInFilterItemHandler(stack).getConfiguredFluids());\n    }\n\n    @Override\n    public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {\n        return false;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/FluidStorageDiskItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.api.storage.StorageType;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskProvider;\nimport com.refinedmods.refinedstorage.api.storage.disk.StorageDiskSyncData;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType;\nimport com.refinedmods.refinedstorage.render.Styles;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.Containers;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.InteractionResultHolder;\nimport net.minecraft.world.entity.Entity;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.TooltipFlag;\nimport net.minecraft.world.level.Level;\n\nimport javax.annotation.Nullable;\nimport java.util.List;\nimport java.util.UUID;\n\npublic class FluidStorageDiskItem extends Item implements IStorageDiskProvider {\n    private static final String NBT_ID = \"Id\";\n\n    private final FluidStorageType type;\n\n    public FluidStorageDiskItem(FluidStorageType type) {\n        super(new Item.Properties().stacksTo(1));\n\n        this.type = type;\n    }\n\n    @Override\n    public void inventoryTick(ItemStack stack, Level level, Entity entity, int slot, boolean selected) {\n        super.inventoryTick(stack, level, entity, slot, selected);\n\n        if (!level.isClientSide && !stack.hasTag() && entity instanceof Player) {\n            UUID id = UUID.randomUUID();\n\n            API.instance().getStorageDiskManager((ServerLevel) level).set(id, API.instance().createDefaultFluidDisk((ServerLevel) level, getCapacity(stack), (Player) entity));\n            API.instance().getStorageDiskManager((ServerLevel) level).markForSaving();\n\n            setId(stack, id);\n        }\n    }\n\n    @Override\n    public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {\n        super.appendHoverText(stack, level, tooltip, flag);\n\n        if (isValid(stack)) {\n            UUID id = getId(stack);\n\n            API.instance().getStorageDiskSync().sendRequest(id);\n\n            StorageDiskSyncData data = API.instance().getStorageDiskSync().getData(id);\n            if (data != null) {\n                if (data.getCapacity() == -1) {\n                    tooltip.add(Component.translatable(\"misc.refinedstorage.storage.stored\", API.instance().getQuantityFormatter().format(data.getStored())).setStyle(Styles.GRAY));\n                } else {\n                    tooltip.add(Component.translatable(\"misc.refinedstorage.storage.stored_capacity\", API.instance().getQuantityFormatter().format(data.getStored()), API.instance().getQuantityFormatter().format(data.getCapacity())).setStyle(Styles.GRAY));\n                }\n            }\n\n            if (flag.isAdvanced()) {\n                tooltip.add(Component.literal(id.toString()).setStyle(Styles.GRAY));\n            }\n        }\n    }\n\n    @Override\n    public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {\n        ItemStack diskStack = player.getItemInHand(hand);\n\n        if (!level.isClientSide && player.isCrouching() && type != FluidStorageType.CREATIVE) {\n            IStorageDisk disk = API.instance().getStorageDiskManager((ServerLevel) level).getByStack(diskStack);\n\n            if (disk != null && disk.getStored() == 0) {\n                ItemStack storagePart = new ItemStack(FluidStoragePartItem.getByType(type), diskStack.getCount());\n\n                if (!player.getInventory().add(storagePart.copy())) {\n                    Containers.dropItemStack(level, player.getX(), player.getY(), player.getZ(), storagePart);\n                }\n\n                API.instance().getStorageDiskManager((ServerLevel) level).remove(getId(diskStack));\n                API.instance().getStorageDiskManager((ServerLevel) level).markForSaving();\n\n                return new InteractionResultHolder<>(InteractionResult.SUCCESS, new ItemStack(RSItems.STORAGE_HOUSING.get()));\n            }\n        }\n\n        return new InteractionResultHolder<>(InteractionResult.PASS, diskStack);\n    }\n\n    @Override\n    public int getEntityLifespan(ItemStack stack, Level level) {\n        return Integer.MAX_VALUE;\n    }\n\n    @Override\n    public UUID getId(ItemStack disk) {\n        return disk.getTag().getUUID(NBT_ID);\n    }\n\n    @Override\n    public void setId(ItemStack disk, UUID id) {\n        disk.setTag(new CompoundTag());\n        disk.getTag().putUUID(NBT_ID, id);\n    }\n\n    @Override\n    public boolean isValid(ItemStack disk) {\n        return disk.hasTag() && disk.getTag().hasUUID(NBT_ID);\n    }\n\n    @Override\n    public int getCapacity(ItemStack disk) {\n        return type.getCapacity();\n    }\n\n    @Override\n    public StorageType getType() {\n        return StorageType.FLUID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/FluidStoragePartItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType;\nimport net.minecraft.world.item.Item;\n\npublic class FluidStoragePartItem extends Item {\n    public FluidStoragePartItem() {\n        super(new Item.Properties());\n    }\n\n    public static FluidStoragePartItem getByType(FluidStorageType type) {\n        return RSItems.FLUID_STORAGE_PARTS.get(type).get();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/HollowCoverItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.Cover;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverType;\nimport net.minecraft.world.item.ItemStack;\n\npublic class HollowCoverItem extends CoverItem {\n\n    public HollowCoverItem() {\n        super();\n    }\n\n    @Override\n    protected Cover createCover(ItemStack stack) {\n        return new Cover(stack, CoverType.HOLLOW);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/NetworkCardItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport com.refinedmods.refinedstorage.block.NetworkReceiverBlock;\nimport com.refinedmods.refinedstorage.render.Styles;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.registries.Registries;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceKey;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.TooltipFlag;\nimport net.minecraft.world.item.context.UseOnContext;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.Block;\n\nimport javax.annotation.Nullable;\nimport java.util.List;\n\npublic class NetworkCardItem extends Item {\n    private static final String NBT_RECEIVER_X = \"ReceiverX\";\n    private static final String NBT_RECEIVER_Y = \"ReceiverY\";\n    private static final String NBT_RECEIVER_Z = \"ReceiverZ\";\n    private static final String NBT_DIMENSION = \"Dimension\";\n\n    public NetworkCardItem() {\n        super(new Item.Properties().stacksTo(1));\n    }\n\n    @Nullable\n    public static BlockPos getReceiver(ItemStack stack) {\n        if (stack.hasTag() &&\n            stack.getTag().contains(NBT_RECEIVER_X) &&\n            stack.getTag().contains(NBT_RECEIVER_Y) &&\n            stack.getTag().contains(NBT_RECEIVER_Z)) {\n            return new BlockPos(\n                stack.getTag().getInt(NBT_RECEIVER_X),\n                stack.getTag().getInt(NBT_RECEIVER_Y),\n                stack.getTag().getInt(NBT_RECEIVER_Z)\n            );\n        }\n\n        return null;\n    }\n\n    @Nullable\n    public static ResourceKey<Level> getDimension(ItemStack stack) {\n        if (stack.hasTag() && stack.getTag().contains(NBT_DIMENSION)) {\n            ResourceLocation name = ResourceLocation.tryParse(stack.getTag().getString(NBT_DIMENSION));\n            if (name == null) {\n                return null;\n            }\n            return ResourceKey.create(Registries.DIMENSION, name);\n        }\n\n        return null;\n    }\n\n    @Override\n    public InteractionResult useOn(UseOnContext ctx) {\n        Block block = ctx.getLevel().getBlockState(ctx.getClickedPos()).getBlock();\n\n        if (block instanceof NetworkReceiverBlock) {\n            CompoundTag tag = new CompoundTag();\n\n            tag.putInt(NBT_RECEIVER_X, ctx.getClickedPos().getX());\n            tag.putInt(NBT_RECEIVER_Y, ctx.getClickedPos().getY());\n            tag.putInt(NBT_RECEIVER_Z, ctx.getClickedPos().getZ());\n            tag.putString(NBT_DIMENSION, ctx.getLevel().dimension().location().toString());\n\n            ctx.getPlayer().getItemInHand(ctx.getHand()).setTag(tag);\n\n            return InteractionResult.SUCCESS;\n        }\n\n        return InteractionResult.PASS;\n    }\n\n    @Override\n    public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {\n        super.appendHoverText(stack, level, tooltip, flag);\n\n        BlockPos pos = getReceiver(stack);\n        ResourceKey<Level> type = getDimension(stack);\n\n        if (pos != null && type != null) {\n            tooltip.add(Component.translatable(\n                \"misc.refinedstorage.network_card.tooltip\",\n                pos.getX(),\n                pos.getY(),\n                pos.getZ(),\n                type.location().toString()\n            ).setStyle(Styles.GRAY));\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/NetworkItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.item.INetworkItemProvider;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport com.refinedmods.refinedstorage.render.Styles;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.registries.Registries;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.network.chat.MutableComponent;\nimport net.minecraft.resources.ResourceKey;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.MinecraftServer;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.InteractionResultHolder;\nimport net.minecraft.world.entity.LivingEntity;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.TooltipFlag;\nimport net.minecraft.world.item.context.UseOnContext;\nimport net.minecraft.world.level.Level;\n\nimport javax.annotation.Nullable;\nimport java.util.List;\nimport java.util.function.Consumer;\nimport java.util.function.Supplier;\n\npublic abstract class NetworkItem extends EnergyItem implements INetworkItemProvider {\n    private static final String NBT_NODE_X = \"NodeX\";\n    private static final String NBT_NODE_Y = \"NodeY\";\n    private static final String NBT_NODE_Z = \"NodeZ\";\n    private static final String NBT_DIMENSION = \"Dimension\";\n\n    protected NetworkItem(Item.Properties item, boolean creative, Supplier<Integer> energyCapacity) {\n        super(item, creative, energyCapacity);\n    }\n\n    @Nullable\n    public static ResourceKey<Level> getDimension(ItemStack stack) {\n        if (stack.hasTag() && stack.getTag().contains(NBT_DIMENSION)) {\n            ResourceLocation name = ResourceLocation.tryParse(stack.getTag().getString(NBT_DIMENSION));\n            if (name == null) {\n                return null;\n            }\n            return ResourceKey.create(Registries.DIMENSION, name);\n        }\n\n        return null;\n    }\n\n    public static int getX(ItemStack stack) {\n        return stack.getTag().getInt(NBT_NODE_X);\n    }\n\n    public static int getY(ItemStack stack) {\n        return stack.getTag().getInt(NBT_NODE_Y);\n    }\n\n    public static int getZ(ItemStack stack) {\n        return stack.getTag().getInt(NBT_NODE_Z);\n    }\n\n    public static boolean isValid(ItemStack stack) {\n        return stack.hasTag()\n            && stack.getTag().contains(NBT_NODE_X)\n            && stack.getTag().contains(NBT_NODE_Y)\n            && stack.getTag().contains(NBT_NODE_Z)\n            && stack.getTag().contains(NBT_DIMENSION);\n    }\n\n    @Override\n    public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {\n        ItemStack stack = player.getItemInHand(hand);\n\n        if (!level.isClientSide) {\n            applyNetwork(level.getServer(), stack, n -> n.getNetworkItemManager().open(player, player.getItemInHand(hand), PlayerSlot.getSlotForHand(player, hand)), player::sendSystemMessage);\n        }\n\n        return InteractionResultHolder.success(stack);\n    }\n\n    public void applyNetwork(MinecraftServer server, ItemStack stack, Consumer<INetwork> onNetwork, Consumer<Component> onError) {\n        MutableComponent notFound = Component.translatable(\"misc.refinedstorage.network_item.not_found\");\n\n        if (!isValid(stack)) {\n            onError.accept(notFound);\n            return;\n        }\n\n        ResourceKey<Level> dimension = getDimension(stack);\n        if (dimension == null) {\n            onError.accept(notFound);\n            return;\n        }\n\n        Level nodeLevel = server.getLevel(dimension);\n        if (nodeLevel == null) {\n            onError.accept(notFound);\n            return;\n        }\n\n        BlockPos pos = new BlockPos(getX(stack), getY(stack), getZ(stack));\n        if (!nodeLevel.isLoaded(pos)) {\n            onError.accept(notFound);\n            return;\n        }\n\n        INetwork network = NetworkUtils.getNetworkFromNode(NetworkUtils.getNodeFromBlockEntity(nodeLevel.getBlockEntity(pos)));\n        if (network == null) {\n            onError.accept(notFound);\n            return;\n        }\n\n        onNetwork.accept(network);\n    }\n\n    @Override\n    public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {\n        super.appendHoverText(stack, level, tooltip, flag);\n\n        if (isValid(stack)) {\n            tooltip.add(Component.translatable(\"misc.refinedstorage.network_item.tooltip\", getX(stack), getY(stack), getZ(stack)).setStyle(Styles.GRAY));\n        }\n    }\n\n    @Override\n    public InteractionResult interactLivingEntity(ItemStack stack, Player playerIn, LivingEntity target, InteractionHand hand) {\n        return super.interactLivingEntity(stack, playerIn, target, hand);\n    }\n\n    @Override\n    public InteractionResult useOn(UseOnContext ctx) {\n        ItemStack stack = ctx.getPlayer().getItemInHand(ctx.getHand());\n\n        INetwork network = NetworkUtils.getNetworkFromNode(NetworkUtils.getNodeFromBlockEntity(ctx.getLevel().getBlockEntity(ctx.getClickedPos())));\n        if (network != null) {\n            CompoundTag tag = stack.getTag();\n\n            if (tag == null) {\n                tag = new CompoundTag();\n            }\n\n            tag.putInt(NBT_NODE_X, network.getPosition().getX());\n            tag.putInt(NBT_NODE_Y, network.getPosition().getY());\n            tag.putInt(NBT_NODE_Z, network.getPosition().getZ());\n            tag.putString(NBT_DIMENSION, ctx.getLevel().dimension().location().toString());\n\n            stack.setTag(tag);\n\n            return InteractionResult.SUCCESS;\n        }\n\n        return InteractionResult.PASS;\n    }\n\n    @Override\n    public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {\n        return false;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/PatternItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternProvider;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.AllowedTagList;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.CraftingPattern;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.CraftingPatternFactory;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode;\nimport com.refinedmods.refinedstorage.render.Styles;\nimport com.refinedmods.refinedstorage.render.blockentity.PatternItemBlockEntityRenderer;\nimport com.refinedmods.refinedstorage.util.ItemStackKey;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.client.gui.screens.Screen;\nimport net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.InteractionResultHolder;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.TooltipFlag;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.client.extensions.common.IClientItemExtensions;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.function.Consumer;\nimport java.util.stream.Collectors;\n\npublic class PatternItem extends Item implements ICraftingPatternProvider {\n    private static final Map<ItemStackKey, ICraftingPattern> CACHE = new HashMap<>();\n\n    private static final String NBT_VERSION = \"Version\";\n    private static final String NBT_INPUT_SLOT = \"Input_%d\";\n    private static final String NBT_OUTPUT_SLOT = \"Output_%d\";\n    private static final String NBT_FLUID_INPUT_SLOT = \"FluidInput_%d\";\n    private static final String NBT_FLUID_OUTPUT_SLOT = \"FluidOutput_%d\";\n    private static final String NBT_EXACT = \"Exact\";\n    private static final String NBT_PROCESSING = \"Processing\";\n    private static final String NBT_ALLOWED_TAGS = \"AllowedTags\";\n\n    private static final int VERSION = 1;\n\n    public PatternItem() {\n        super(new Item.Properties());\n    }\n\n    public static ICraftingPattern fromCache(Level level, ItemStack stack) {\n        ICraftingPattern pattern = CACHE.computeIfAbsent(\n            new ItemStackKey(stack),\n            s -> CraftingPatternFactory.INSTANCE.create(level, null, s.getStack())\n        );\n\n        // A number that is not too crazy but hopefully is not normally reachable,\n        // just reset the cache to keep its size limited so this is not a memory leak\n        if (CACHE.size() > 16384) {\n            CACHE.clear();\n        }\n\n        return pattern;\n    }\n\n    public static void setInputSlot(ItemStack pattern, int slot, ItemStack stack) {\n        if (!pattern.hasTag()) {\n            pattern.setTag(new CompoundTag());\n        }\n\n        pattern.getTag().put(String.format(NBT_INPUT_SLOT, slot), stack.save(new CompoundTag()));\n    }\n\n    @Nonnull\n    public static ItemStack getInputSlot(ItemStack pattern, int slot) {\n        String id = String.format(NBT_INPUT_SLOT, slot);\n\n        if (!pattern.hasTag() || !pattern.getTag().contains(id)) {\n            return ItemStack.EMPTY;\n        }\n\n        return ItemStack.of(pattern.getTag().getCompound(id));\n    }\n\n    public static void setOutputSlot(ItemStack pattern, int slot, ItemStack stack) {\n        if (!pattern.hasTag()) {\n            pattern.setTag(new CompoundTag());\n        }\n\n        pattern.getTag().put(String.format(NBT_OUTPUT_SLOT, slot), stack.save(new CompoundTag()));\n    }\n\n    @Nonnull\n    public static ItemStack getOutputSlot(ItemStack pattern, int slot) {\n        String id = String.format(NBT_OUTPUT_SLOT, slot);\n\n        if (!pattern.hasTag() || !pattern.getTag().contains(id)) {\n            return ItemStack.EMPTY;\n        }\n\n        return ItemStack.of(pattern.getTag().getCompound(id));\n    }\n\n    public static void setFluidInputSlot(ItemStack pattern, int slot, FluidStack stack) {\n        if (!pattern.hasTag()) {\n            pattern.setTag(new CompoundTag());\n        }\n\n        pattern.getTag().put(String.format(NBT_FLUID_INPUT_SLOT, slot), stack.writeToNBT(new CompoundTag()));\n    }\n\n    public static FluidStack getFluidInputSlot(ItemStack pattern, int slot) {\n        String id = String.format(NBT_FLUID_INPUT_SLOT, slot);\n\n        if (!pattern.hasTag() || !pattern.getTag().contains(id)) {\n            return FluidStack.EMPTY;\n        }\n\n        return FluidStack.loadFluidStackFromNBT(pattern.getTag().getCompound(id));\n    }\n\n    public static void setFluidOutputSlot(ItemStack pattern, int slot, FluidStack stack) {\n        if (!pattern.hasTag()) {\n            pattern.setTag(new CompoundTag());\n        }\n\n        pattern.getTag().put(String.format(NBT_FLUID_OUTPUT_SLOT, slot), stack.writeToNBT(new CompoundTag()));\n    }\n\n    public static FluidStack getFluidOutputSlot(ItemStack pattern, int slot) {\n        String id = String.format(NBT_FLUID_OUTPUT_SLOT, slot);\n\n        if (!pattern.hasTag() || !pattern.getTag().contains(id)) {\n            return FluidStack.EMPTY;\n        }\n\n        return FluidStack.loadFluidStackFromNBT(pattern.getTag().getCompound(id));\n    }\n\n    public static boolean isProcessing(ItemStack pattern) {\n        return pattern.hasTag() && pattern.getTag().contains(NBT_PROCESSING) && pattern.getTag().getBoolean(NBT_PROCESSING);\n    }\n\n    public static void setProcessing(ItemStack pattern, boolean processing) {\n        if (!pattern.hasTag()) {\n            pattern.setTag(new CompoundTag());\n        }\n\n        pattern.getTag().putBoolean(NBT_PROCESSING, processing);\n    }\n\n    public static boolean isExact(ItemStack pattern) {\n        if (!pattern.hasTag() || !pattern.getTag().contains(NBT_EXACT)) {\n            return false;\n        }\n\n        return pattern.getTag().getBoolean(NBT_EXACT);\n    }\n\n    public static void setExact(ItemStack pattern, boolean exact) {\n        if (!pattern.hasTag()) {\n            pattern.setTag(new CompoundTag());\n        }\n\n        pattern.getTag().putBoolean(NBT_EXACT, exact);\n    }\n\n    public static void setToCurrentVersion(ItemStack pattern) {\n        if (!pattern.hasTag()) {\n            pattern.setTag(new CompoundTag());\n        }\n\n        pattern.getTag().putInt(NBT_VERSION, VERSION);\n    }\n\n    public static void setAllowedTags(ItemStack pattern, AllowedTagList allowedTagList) {\n        if (!pattern.hasTag()) {\n            pattern.setTag(new CompoundTag());\n        }\n\n        pattern.getTag().put(NBT_ALLOWED_TAGS, allowedTagList.writeToNbt());\n    }\n\n    @Nullable\n    public static AllowedTagList getAllowedTags(ItemStack pattern) {\n        if (!pattern.hasTag() || !pattern.getTag().contains(NBT_ALLOWED_TAGS)) {\n            return null;\n        }\n\n        AllowedTagList allowedTagList = new AllowedTagList(null, GridNetworkNode.PROCESSING_MATRIX_SIZE);\n\n        allowedTagList.readFromNbt(pattern.getTag().getCompound(NBT_ALLOWED_TAGS));\n\n        return allowedTagList;\n    }\n\n    @Override\n    public void initializeClient(Consumer<IClientItemExtensions> consumer) {\n        super.initializeClient(consumer);\n        consumer.accept(new IClientItemExtensions() {\n            @Override\n            public BlockEntityWithoutLevelRenderer getCustomRenderer() {\n                return PatternItemBlockEntityRenderer.getInstance();\n            }\n        });\n    }\n\n    @Override\n    public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {\n        super.appendHoverText(stack, level, tooltip, flag);\n\n        if (!stack.hasTag() || level == null) {\n            return;\n        }\n\n        ICraftingPattern pattern = fromCache(level, stack);\n\n        if (pattern.isValid()) {\n            if (Screen.hasShiftDown() || isProcessing(stack)) {\n                tooltip.add(Component.translatable(\"misc.refinedstorage.pattern.inputs\").setStyle(Styles.YELLOW));\n\n                RenderUtils.addCombinedItemsToTooltip(tooltip, true, pattern.getInputs().stream().map(i -> !i.isEmpty() ? i.get(0) : ItemStack.EMPTY).collect(Collectors.toList()));\n                RenderUtils.addCombinedFluidsToTooltip(tooltip, true, pattern.getFluidInputs().stream().map(i -> !i.isEmpty() ? i.get(0) : FluidStack.EMPTY).collect(Collectors.toList()));\n\n                tooltip.add(Component.translatable(\"misc.refinedstorage.pattern.outputs\").setStyle(Styles.YELLOW));\n            }\n\n            RenderUtils.addCombinedItemsToTooltip(tooltip, true, pattern.getOutputs());\n            RenderUtils.addCombinedFluidsToTooltip(tooltip, true, pattern.getFluidOutputs());\n\n            if (pattern instanceof CraftingPattern && ((CraftingPattern) pattern).getAllowedTagList() != null) {\n                addAllowedTags(tooltip, (CraftingPattern) pattern);\n            }\n\n            if (isExact(stack)) {\n                tooltip.add(Component.translatable(\"misc.refinedstorage.pattern.exact\").setStyle(Styles.BLUE));\n            }\n\n            if (isProcessing(stack)) {\n                tooltip.add(Component.translatable(\"misc.refinedstorage.processing\").setStyle(Styles.BLUE));\n            }\n        } else {\n            tooltip.add(Component.translatable(\"misc.refinedstorage.pattern.invalid\").setStyle(Styles.RED));\n            tooltip.add(pattern.getErrorMessage().plainCopy().setStyle(Styles.GRAY));\n        }\n    }\n\n    public void addAllowedTags(List<Component> tooltip, CraftingPattern pattern) {\n        for (int i = 0; i < pattern.getAllowedTagList().getAllowedItemTags().size(); ++i) {\n            Set<ResourceLocation> allowedTags = pattern.getAllowedTagList().getAllowedItemTags().get(i);\n\n            for (ResourceLocation tag : allowedTags) {\n                tooltip.add(Component.translatable(\n                    \"misc.refinedstorage.pattern.allowed_item_tag\",\n                    tag.toString(),\n                    pattern.getInputs().get(i).get(0).getHoverName()\n                ).setStyle(Styles.AQUA));\n            }\n        }\n\n        for (int i = 0; i < pattern.getAllowedTagList().getAllowedFluidTags().size(); ++i) {\n            Set<ResourceLocation> allowedTags = pattern.getAllowedTagList().getAllowedFluidTags().get(i);\n\n            for (ResourceLocation tag : allowedTags) {\n                tooltip.add(Component.translatable(\n                    \"misc.refinedstorage.pattern.allowed_fluid_tag\",\n                    tag.toString(),\n                    pattern.getFluidInputs().get(i).get(0).getDisplayName()\n                ).setStyle(Styles.AQUA));\n            }\n        }\n    }\n\n    @Override\n    public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {\n        if (!level.isClientSide && player.isCrouching()) {\n            return new InteractionResultHolder<>(InteractionResult.SUCCESS, new ItemStack(RSItems.PATTERN.get(), player.getItemInHand(hand).getCount()));\n        }\n\n        return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand));\n    }\n\n    @Override\n    @Nonnull\n    public ICraftingPattern create(Level level, ItemStack stack, ICraftingPatternContainer container) {\n        return CraftingPatternFactory.INSTANCE.create(level, container, stack);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/ProcessorBindingItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport net.minecraft.world.item.Item;\n\npublic class ProcessorBindingItem extends Item {\n    public ProcessorBindingItem() {\n        super(new Item.Properties());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/ProcessorItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport net.minecraft.world.item.Item;\n\npublic class ProcessorItem extends Item {\n    public ProcessorItem() {\n        super(new Item.Properties());\n    }\n\n    public enum Type {\n        RAW_BASIC(\"raw_basic\"),\n        RAW_IMPROVED(\"raw_improved\"),\n        RAW_ADVANCED(\"raw_advanced\"),\n        BASIC(\"basic\"),\n        IMPROVED(\"improved\"),\n        ADVANCED(\"advanced\");\n\n        final String name;\n\n        Type(String name) {\n            this.name = name;\n        }\n\n        public String getName() {\n            return name;\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/QuartzEnrichedIronItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport net.minecraft.world.item.Item;\n\npublic class QuartzEnrichedIronItem extends Item {\n    public QuartzEnrichedIronItem() {\n        super(new Item.Properties());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/SecurityCardItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.render.Styles;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResultHolder;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.TooltipFlag;\nimport net.minecraft.world.level.Level;\n\nimport javax.annotation.Nullable;\nimport java.util.List;\nimport java.util.UUID;\n\npublic class SecurityCardItem extends Item {\n    private static final String NBT_OWNER = \"Owner\";\n    private static final String NBT_OWNER_NAME = \"OwnerName\";\n    private static final String NBT_PERMISSION = \"Permission_%d\";\n\n    public SecurityCardItem() {\n        super(new Item.Properties().stacksTo(1));\n    }\n\n    @Nullable\n    public static UUID getOwner(ItemStack stack) {\n        if (stack.hasTag() && stack.getTag().contains(NBT_OWNER)) {\n            return UUID.fromString(stack.getTag().getString(NBT_OWNER));\n        }\n\n        return null;\n    }\n\n    public static boolean hasPermission(ItemStack stack, Permission permission) {\n        String id = String.format(NBT_PERMISSION, permission.getId());\n\n        if (stack.hasTag() && stack.getTag().contains(id)) {\n            return stack.getTag().getBoolean(id);\n        }\n\n        return false;\n    }\n\n    public static void setPermission(ItemStack stack, Permission permission, boolean state) {\n        if (!stack.hasTag()) {\n            stack.setTag(new CompoundTag());\n        }\n\n        stack.getTag().putBoolean(String.format(NBT_PERMISSION, permission.getId()), state);\n    }\n\n    public static boolean isValid(ItemStack stack) {\n        return stack.hasTag() && stack.getTag().contains(NBT_OWNER);\n    }\n\n    @Override\n    public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {\n        ItemStack stack = player.getItemInHand(hand);\n\n        if (!level.isClientSide) {\n            stack.setTag(new CompoundTag());\n\n            stack.getTag().putString(NBT_OWNER, player.getGameProfile().getId().toString());\n            stack.getTag().putString(NBT_OWNER_NAME, player.getGameProfile().getName());\n        }\n\n        return InteractionResultHolder.success(stack);\n    }\n\n    @Override\n    public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {\n        super.appendHoverText(stack, level, tooltip, flag);\n\n        if (stack.hasTag() && stack.getTag().contains(NBT_OWNER_NAME)) {\n            tooltip.add(Component.translatable(\"item.refinedstorage.security_card.owner\", stack.getTag().getString(NBT_OWNER_NAME)).setStyle(Styles.GRAY));\n        }\n\n        for (Permission permission : Permission.values()) {\n            if (hasPermission(stack, permission)) {\n                tooltip.add(Component.literal(\"- \").append(Component.translatable(\"gui.refinedstorage.security_manager.permission.\" + permission.getId())).setStyle(Styles.GRAY));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/SiliconItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport net.minecraft.world.item.Item;\n\npublic class SiliconItem extends Item {\n    public SiliconItem() {\n        super(new Item.Properties());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/StorageDiskItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.api.storage.StorageType;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskProvider;\nimport com.refinedmods.refinedstorage.api.storage.disk.StorageDiskSyncData;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType;\nimport com.refinedmods.refinedstorage.render.Styles;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.Containers;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.InteractionResultHolder;\nimport net.minecraft.world.entity.Entity;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.TooltipFlag;\nimport net.minecraft.world.level.Level;\n\nimport javax.annotation.Nullable;\nimport java.util.List;\nimport java.util.UUID;\n\npublic class StorageDiskItem extends Item implements IStorageDiskProvider {\n    private static final String NBT_ID = \"Id\";\n\n    private final ItemStorageType type;\n\n    public StorageDiskItem(ItemStorageType type) {\n        super(new Item.Properties().stacksTo(1));\n\n        this.type = type;\n    }\n\n    @Override\n    public void inventoryTick(ItemStack stack, Level level, Entity entity, int slot, boolean selected) {\n        super.inventoryTick(stack, level, entity, slot, selected);\n\n        if (!level.isClientSide && !stack.hasTag() && entity instanceof Player) {\n            UUID id = UUID.randomUUID();\n\n            API.instance().getStorageDiskManager((ServerLevel) level).set(id, API.instance().createDefaultItemDisk((ServerLevel) level, getCapacity(stack), (Player) entity));\n            API.instance().getStorageDiskManager((ServerLevel) level).markForSaving();\n\n            setId(stack, id);\n        }\n    }\n\n    @Override\n    public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {\n        super.appendHoverText(stack, level, tooltip, flag);\n\n        if (isValid(stack)) {\n            UUID id = getId(stack);\n\n            API.instance().getStorageDiskSync().sendRequest(id);\n\n            StorageDiskSyncData data = API.instance().getStorageDiskSync().getData(id);\n            if (data != null) {\n                if (data.getCapacity() == -1) {\n                    tooltip.add(Component.translatable(\"misc.refinedstorage.storage.stored\", API.instance().getQuantityFormatter().format(data.getStored())).setStyle(Styles.GRAY));\n                } else {\n                    tooltip.add(Component.translatable(\"misc.refinedstorage.storage.stored_capacity\", API.instance().getQuantityFormatter().format(data.getStored()), API.instance().getQuantityFormatter().format(data.getCapacity())).setStyle(Styles.GRAY));\n                }\n            }\n\n            if (flag.isAdvanced()) {\n                tooltip.add(Component.literal(id.toString()).setStyle(Styles.GRAY));\n            }\n        }\n    }\n\n    @Override\n    public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {\n        ItemStack diskStack = player.getItemInHand(hand);\n\n        if (!level.isClientSide && player.isCrouching() && type != ItemStorageType.CREATIVE) {\n            IStorageDisk disk = API.instance().getStorageDiskManager((ServerLevel) level).getByStack(diskStack);\n\n            if (disk != null && disk.getStored() == 0) {\n                ItemStack storagePart = new ItemStack(StoragePartItem.getByType(type), diskStack.getCount());\n\n                if (!player.getInventory().add(storagePart.copy())) {\n                    Containers.dropItemStack(level, player.getX(), player.getY(), player.getZ(), storagePart);\n                }\n\n                API.instance().getStorageDiskManager((ServerLevel) level).remove(getId(diskStack));\n                API.instance().getStorageDiskManager((ServerLevel) level).markForSaving();\n\n                return new InteractionResultHolder<>(InteractionResult.SUCCESS, new ItemStack(RSItems.STORAGE_HOUSING.get()));\n            }\n        }\n\n        return new InteractionResultHolder<>(InteractionResult.PASS, diskStack);\n    }\n\n    @Override\n    public int getEntityLifespan(ItemStack stack, Level level) {\n        return Integer.MAX_VALUE;\n    }\n\n    @Override\n    public UUID getId(ItemStack disk) {\n        return disk.getTag().getUUID(NBT_ID);\n    }\n\n    @Override\n    public void setId(ItemStack disk, UUID id) {\n        disk.setTag(new CompoundTag());\n        disk.getTag().putUUID(NBT_ID, id);\n    }\n\n    @Override\n    public boolean isValid(ItemStack disk) {\n        return disk.hasTag() && disk.getTag().hasUUID(NBT_ID);\n    }\n\n    @Override\n    public int getCapacity(ItemStack disk) {\n        return type.getCapacity();\n    }\n\n    @Override\n    public StorageType getType() {\n        return StorageType.ITEM;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/StorageHousingItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport net.minecraft.world.item.Item;\n\npublic class StorageHousingItem extends Item {\n    public StorageHousingItem() {\n        super(new Item.Properties());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/StoragePartItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType;\nimport net.minecraft.world.item.Item;\n\npublic class StoragePartItem extends Item {\n    public StoragePartItem() {\n        super(new Item.Properties());\n    }\n\n    public static StoragePartItem getByType(ItemStorageType type) {\n        return RSItems.ITEM_STORAGE_PARTS.get(type).get();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/UpgradeItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.render.Styles;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.TooltipFlag;\nimport net.minecraft.world.level.Level;\n\nimport javax.annotation.Nullable;\nimport java.util.List;\n\npublic class UpgradeItem extends Item {\n    private final Type type;\n\n    public UpgradeItem(Type type) {\n        super(new Item.Properties());\n\n        this.type = type;\n    }\n\n    @Override\n    public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {\n        super.appendHoverText(stack, level, tooltip, flag);\n\n        if (type.getFortuneLevel() > 0) {\n            tooltip.add(\n                Component.translatable(\"enchantment.minecraft.fortune\")\n                    .append(\" \")\n                    .append(Component.translatable(\"enchantment.level.\" + type.getFortuneLevel()))\n                    .setStyle(Styles.GRAY)\n            );\n        }\n    }\n\n    @Override\n    public boolean isFoil(ItemStack stack) {\n        return type == Type.SILK_TOUCH ||\n            type == Type.FORTUNE_1 ||\n            type == Type.FORTUNE_2 ||\n            type == Type.FORTUNE_3;\n    }\n\n    public Type getType() {\n        return type;\n    }\n\n    public enum Type {\n        NORMAL(\"normal\"),\n        SPEED(\"speed\"),\n        RANGE(\"range\"),\n        CRAFTING(\"crafting\"),\n        STACK(\"stack\"),\n        SILK_TOUCH(\"silk_touch\"),\n        FORTUNE_1(\"fortune_1\"),\n        FORTUNE_2(\"fortune_2\"),\n        FORTUNE_3(\"fortune_3\"),\n        REGULATOR(\"regulator\");\n\n        private final String name;\n\n        Type(String name) {\n            this.name = name;\n        }\n\n        public String getName() {\n            return name;\n        }\n\n        public int getEnergyUsage() {\n            switch (this) {\n                case NORMAL:\n                    return 0;\n                case RANGE:\n                    return RS.SERVER_CONFIG.getUpgrades().getRangeUpgradeUsage();\n                case SPEED:\n                    return RS.SERVER_CONFIG.getUpgrades().getSpeedUpgradeUsage();\n                case CRAFTING:\n                    return RS.SERVER_CONFIG.getUpgrades().getCraftingUpgradeUsage();\n                case STACK:\n                    return RS.SERVER_CONFIG.getUpgrades().getStackUpgradeUsage();\n                case SILK_TOUCH:\n                    return RS.SERVER_CONFIG.getUpgrades().getSilkTouchUpgradeUsage();\n                case FORTUNE_1:\n                    return RS.SERVER_CONFIG.getUpgrades().getFortune1UpgradeUsage();\n                case FORTUNE_2:\n                    return RS.SERVER_CONFIG.getUpgrades().getFortune2UpgradeUsage();\n                case FORTUNE_3:\n                    return RS.SERVER_CONFIG.getUpgrades().getFortune3UpgradeUsage();\n                case REGULATOR:\n                    return RS.SERVER_CONFIG.getUpgrades().getRegulatorUpgradeUsage();\n                default:\n                    throw new IllegalStateException(\"What even am I?\");\n            }\n        }\n\n        public int getFortuneLevel() {\n            switch (this) {\n                case FORTUNE_1:\n                    return 1;\n                case FORTUNE_2:\n                    return 2;\n                case FORTUNE_3:\n                    return 3;\n                default:\n                    return 0;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/WirelessCraftingMonitorItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.item.INetworkItem;\nimport com.refinedmods.refinedstorage.api.network.item.INetworkItemManager;\nimport com.refinedmods.refinedstorage.apiimpl.network.item.WirelessCraftingMonitorNetworkItem;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\n\nimport javax.annotation.Nonnull;\nimport java.util.Optional;\nimport java.util.UUID;\n\npublic class WirelessCraftingMonitorItem extends NetworkItem {\n    public static final String NBT_TAB_SELECTED = \"TabSelected\";\n    public static final String NBT_TAB_PAGE = \"TabPage\";\n    private final Type type;\n\n    public WirelessCraftingMonitorItem(Type type) {\n        super(new Item.Properties().stacksTo(1), type == Type.CREATIVE, () -> RS.SERVER_CONFIG.getWirelessCraftingMonitor().getCapacity());\n\n        this.type = type;\n    }\n\n    public static Optional<UUID> getTabSelected(ItemStack stack) {\n        if (stack.hasTag() && stack.getTag().hasUUID(NBT_TAB_SELECTED)) {\n            return Optional.of(stack.getTag().getUUID(NBT_TAB_SELECTED));\n        }\n\n        return Optional.empty();\n    }\n\n    public static void setTabSelected(ItemStack stack, Optional<UUID> tabSelected) {\n        if (!stack.hasTag()) {\n            stack.setTag(new CompoundTag());\n        }\n\n        if (tabSelected.isPresent()) {\n            stack.getTag().putUUID(NBT_TAB_SELECTED, tabSelected.get());\n        } else {\n            stack.getTag().remove(NBT_TAB_SELECTED + \"Least\");\n            stack.getTag().remove(NBT_TAB_SELECTED + \"Most\");\n        }\n    }\n\n    public static int getTabPage(ItemStack stack) {\n        if (stack.hasTag() && stack.getTag().contains(NBT_TAB_PAGE)) {\n            return stack.getTag().getInt(NBT_TAB_PAGE);\n        }\n\n        return 0;\n    }\n\n    public static void setTabPage(ItemStack stack, int tabPage) {\n        if (!stack.hasTag()) {\n            stack.setTag(new CompoundTag());\n        }\n\n        stack.getTag().putInt(NBT_TAB_PAGE, tabPage);\n    }\n\n    public Type getType() {\n        return type;\n    }\n\n    @Nonnull\n    @Override\n    public INetworkItem provide(INetworkItemManager handler, Player player, ItemStack stack, PlayerSlot slot) {\n        return new WirelessCraftingMonitorNetworkItem(handler, player, stack, slot);\n    }\n\n    public enum Type {\n        NORMAL,\n        CREATIVE\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/WirelessFluidGridItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.api.network.item.INetworkItem;\nimport com.refinedmods.refinedstorage.api.network.item.INetworkItemManager;\nimport com.refinedmods.refinedstorage.apiimpl.network.item.WirelessFluidGridNetworkItem;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\n\nimport javax.annotation.Nonnull;\n\npublic class WirelessFluidGridItem extends NetworkItem {\n    private final Type type;\n\n    public WirelessFluidGridItem(Type type) {\n        super(new Item.Properties().stacksTo(1), type == Type.CREATIVE, () -> RS.SERVER_CONFIG.getWirelessFluidGrid().getCapacity());\n\n        this.type = type;\n    }\n\n    public static int getSortingType(ItemStack stack) {\n        return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_SORTING_TYPE)) ? stack.getTag().getInt(GridNetworkNode.NBT_SORTING_TYPE) : IGrid.SORTING_TYPE_QUANTITY;\n    }\n\n    public static int getSortingDirection(ItemStack stack) {\n        return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_SORTING_DIRECTION)) ? stack.getTag().getInt(GridNetworkNode.NBT_SORTING_DIRECTION) : IGrid.SORTING_DIRECTION_DESCENDING;\n    }\n\n    public static int getSearchBoxMode(ItemStack stack) {\n        return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_SEARCH_BOX_MODE)) ? stack.getTag().getInt(GridNetworkNode.NBT_SEARCH_BOX_MODE) : IGrid.SEARCH_BOX_MODE_NORMAL;\n    }\n\n    public static int getTabSelected(ItemStack stack) {\n        return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_TAB_SELECTED)) ? stack.getTag().getInt(GridNetworkNode.NBT_TAB_SELECTED) : -1;\n    }\n\n    public static int getTabPage(ItemStack stack) {\n        return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_TAB_PAGE)) ? stack.getTag().getInt(GridNetworkNode.NBT_TAB_PAGE) : 0;\n    }\n\n    public static int getSize(ItemStack stack) {\n        return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_SIZE)) ? stack.getTag().getInt(GridNetworkNode.NBT_SIZE) : IGrid.SIZE_STRETCH;\n    }\n\n    public Type getType() {\n        return type;\n    }\n\n    @Nonnull\n    @Override\n    public INetworkItem provide(INetworkItemManager handler, Player player, ItemStack stack, PlayerSlot slot) {\n        return new WirelessFluidGridNetworkItem(handler, player, stack, slot);\n    }\n\n    public enum Type {\n        NORMAL,\n        CREATIVE\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/WirelessGridItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.api.network.item.INetworkItem;\nimport com.refinedmods.refinedstorage.api.network.item.INetworkItemManager;\nimport com.refinedmods.refinedstorage.apiimpl.network.item.WirelessGridNetworkItem;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\n\nimport javax.annotation.Nonnull;\n\npublic class WirelessGridItem extends NetworkItem {\n    private final Type type;\n\n    public WirelessGridItem(Type type) {\n        super(new Item.Properties().stacksTo(1), type == Type.CREATIVE, () -> RS.SERVER_CONFIG.getWirelessGrid().getCapacity());\n\n        this.type = type;\n    }\n\n    public static int getViewType(ItemStack stack) {\n        return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_VIEW_TYPE)) ? stack.getTag().getInt(GridNetworkNode.NBT_VIEW_TYPE) : IGrid.VIEW_TYPE_NORMAL;\n    }\n\n    public static int getSortingType(ItemStack stack) {\n        return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_SORTING_TYPE)) ? stack.getTag().getInt(GridNetworkNode.NBT_SORTING_TYPE) : IGrid.SORTING_TYPE_QUANTITY;\n    }\n\n    public static int getSortingDirection(ItemStack stack) {\n        return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_SORTING_DIRECTION)) ? stack.getTag().getInt(GridNetworkNode.NBT_SORTING_DIRECTION) : IGrid.SORTING_DIRECTION_DESCENDING;\n    }\n\n    public static int getSearchBoxMode(ItemStack stack) {\n        return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_SEARCH_BOX_MODE)) ? stack.getTag().getInt(GridNetworkNode.NBT_SEARCH_BOX_MODE) : IGrid.SEARCH_BOX_MODE_NORMAL;\n    }\n\n    public static int getTabSelected(ItemStack stack) {\n        return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_TAB_SELECTED)) ? stack.getTag().getInt(GridNetworkNode.NBT_TAB_SELECTED) : -1;\n    }\n\n    public static int getTabPage(ItemStack stack) {\n        return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_TAB_PAGE)) ? stack.getTag().getInt(GridNetworkNode.NBT_TAB_PAGE) : 0;\n    }\n\n    public static int getSize(ItemStack stack) {\n        return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_SIZE)) ? stack.getTag().getInt(GridNetworkNode.NBT_SIZE) : IGrid.SIZE_STRETCH;\n    }\n\n    public Type getType() {\n        return type;\n    }\n\n    @Override\n    @Nonnull\n    public INetworkItem provide(INetworkItemManager handler, Player player, ItemStack stack, PlayerSlot slot) {\n        return new WirelessGridNetworkItem(handler, player, stack, slot);\n    }\n\n    public enum Type {\n        NORMAL,\n        CREATIVE\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/WrenchItem.java",
    "content": "package com.refinedmods.refinedstorage.item;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.node.ICoverable;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.Cover;\nimport com.refinedmods.refinedstorage.util.NetworkUtils;\nimport com.refinedmods.refinedstorage.util.LevelUtils;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.context.UseOnContext;\nimport net.minecraft.world.level.block.Rotation;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\n\npublic class WrenchItem extends Item {\n    public WrenchItem() {\n        super(new Item.Properties().stacksTo(1));\n    }\n\n    @Override\n    public InteractionResult onItemUseFirst(ItemStack stack, UseOnContext ctx) {\n        if (ctx.getLevel().isClientSide) {\n            return InteractionResult.CONSUME;\n        }\n\n        INetworkNode node = NetworkUtils.getNodeFromBlockEntity(ctx.getLevel().getBlockEntity(ctx.getClickedPos()));\n        INetwork network = NetworkUtils.getNetworkFromNode(node);\n        if (network != null && !network.getSecurityManager().hasPermission(Permission.BUILD, ctx.getPlayer())) {\n            LevelUtils.sendNoPermissionMessage(ctx.getPlayer());\n\n            return InteractionResult.FAIL;\n        }\n        BlockState state = ctx.getLevel().getBlockState(ctx.getClickedPos());\n\n        if (node instanceof ICoverable && ((ICoverable) node).getCoverManager().hasCover(ctx.getClickedFace())) {\n            Cover cover = ((ICoverable) node).getCoverManager().removeCover(ctx.getClickedFace());\n            if (cover != null) {\n                ItemStack stack1 = cover.getType().createStack();\n                CoverItem.setItem(stack1, cover.getStack());\n                ItemHandlerHelper.giveItemToPlayer(ctx.getPlayer(), stack1);\n                ctx.getLevel().sendBlockUpdated(ctx.getClickedPos(), state, state, 3);\n                ctx.getLevel().updateNeighborsAt(ctx.getClickedPos(), ctx.getLevel().getBlockState(ctx.getClickedPos()).getBlock());\n                return InteractionResult.SUCCESS;\n            }\n        }\n\n        ctx.getLevel().setBlockAndUpdate(ctx.getClickedPos(), state.rotate(ctx.getLevel(), ctx.getClickedPos(), Rotation.CLOCKWISE_90));\n\n        return InteractionResult.CONSUME;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/blockitem/BaseBlockItem.java",
    "content": "package com.refinedmods.refinedstorage.item.blockitem;\n\nimport com.refinedmods.refinedstorage.block.BaseBlock;\nimport com.refinedmods.refinedstorage.block.BlockDirection;\nimport net.minecraft.world.item.BlockItem;\nimport net.minecraft.world.item.context.BlockPlaceContext;\nimport net.minecraft.world.level.block.state.BlockState;\n\npublic class BaseBlockItem extends BlockItem {\n    private final BaseBlock block;\n\n    public BaseBlockItem(BaseBlock block, Properties builder) {\n        super(block, builder);\n\n        this.block = block;\n    }\n\n    @Override\n    protected boolean placeBlock(BlockPlaceContext context, BlockState state) {\n        boolean result = super.placeBlock(context, state);\n\n        if (result && block.getDirection() != BlockDirection.NONE) {\n            context.getLevel().setBlockAndUpdate(context.getClickedPos(), state.setValue(block.getDirection().getProperty(), block.getDirection().getFrom(\n                context.getClickedFace(),\n                context.getClickedPos(),\n                context.getPlayer()\n            )));\n        }\n\n        return result;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/blockitem/ColoredBlockItem.java",
    "content": "package com.refinedmods.refinedstorage.item.blockitem;\n\nimport com.refinedmods.refinedstorage.block.BaseBlock;\nimport com.refinedmods.refinedstorage.util.ColorMap;\nimport net.minecraft.network.chat.Component;\n\nimport net.minecraft.world.item.DyeColor;\nimport net.minecraft.world.item.ItemStack;\n\npublic class ColoredBlockItem extends BaseBlockItem {\n    private final Component displayName;\n\n    public ColoredBlockItem(BaseBlock block, Properties builder, DyeColor color, Component displayName) {\n        super(block, builder);\n\n        if (color != ColorMap.DEFAULT_COLOR) {\n            this.displayName = Component.translatable(\"color.minecraft.\" + color.getName())\n                .append(\" \")\n                .append(displayName);\n        } else {\n            this.displayName = displayName;\n        }\n\n    }\n\n    @Override\n    public Component getName(ItemStack stack) {\n        return displayName;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/blockitem/ControllerBlockItem.java",
    "content": "package com.refinedmods.refinedstorage.item.blockitem;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.NetworkType;\nimport com.refinedmods.refinedstorage.block.ControllerBlock;\nimport com.refinedmods.refinedstorage.util.ColorMap;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.world.item.DyeColor;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\n\npublic class ControllerBlockItem extends EnergyBlockItem {\n    private final Component displayName;\n\n    public ControllerBlockItem(ControllerBlock block, DyeColor color, Component displayName) {\n        super(block, new Item.Properties().stacksTo(1), block.getType() == NetworkType.CREATIVE, () -> RS.SERVER_CONFIG.getController().getCapacity());\n\n        if (color != ColorMap.DEFAULT_COLOR) {\n            this.displayName = Component.translatable(\"color.minecraft.\" + color.getName())\n                .append(\" \")\n                .append(displayName);\n        } else {\n            this.displayName = displayName;\n        }\n\n    }\n\n    @Override\n    public Component getName(ItemStack stack) {\n        return displayName;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/blockitem/EnergyBlockItem.java",
    "content": "package com.refinedmods.refinedstorage.item.blockitem;\n\nimport com.refinedmods.refinedstorage.block.BaseBlock;\nimport com.refinedmods.refinedstorage.energy.ItemEnergyStorage;\nimport com.refinedmods.refinedstorage.render.Styles;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.util.Mth;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.TooltipFlag;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.capabilities.Capabilities;\nimport net.neoforged.neoforge.energy.EnergyStorage;\nimport net.neoforged.neoforge.energy.IEnergyStorage;\nimport javax.annotation.Nullable;\nimport java.util.List;\nimport java.util.function.Supplier;\n\npublic abstract class EnergyBlockItem extends BaseBlockItem {\n    private final Supplier<Integer> energyCapacity;\n    private final boolean creative;\n\n    protected EnergyBlockItem(BaseBlock block, Item.Properties properties, boolean creative, Supplier<Integer> energyCapacity) {\n        super(block, properties);\n\n        this.creative = creative;\n        this.energyCapacity = energyCapacity;\n    }\n\n    public EnergyStorage createEnergyStorage(ItemStack stack) {\n        return new ItemEnergyStorage(stack, energyCapacity.get());\n    }\n\n    @Override\n    public boolean isBarVisible(ItemStack stack) {\n        return !creative;\n    }\n\n    @Override\n    public int getBarWidth(ItemStack stack) {\n        IEnergyStorage energy = stack.getCapability(Capabilities.EnergyStorage.ITEM);\n        if (energy == null) {\n            return 0;\n        }\n        float stored = (float) energy.getEnergyStored() / (float) energy.getMaxEnergyStored();\n        return Math.round(stored * 13F);\n    }\n\n    @Override\n    public int getBarColor(ItemStack stack) {\n        IEnergyStorage energy = stack.getCapability(Capabilities.EnergyStorage.ITEM);\n        if (energy == null) {\n            return super.getBarColor(stack);\n        }\n        return Mth.hsvToRgb(Math.max(0.0F, (float) energy.getEnergyStored() / (float) energy.getMaxEnergyStored()) / 3.0F, 1.0F, 1.0F);\n    }\n\n    @Override\n    public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {\n        super.appendHoverText(stack, level, tooltip, flag);\n\n        if (!creative) {\n            final IEnergyStorage energy = stack.getCapability(Capabilities.EnergyStorage.ITEM);\n            if (energy == null) {\n                return;\n            }\n            tooltip.add(Component.translatable(\"misc.refinedstorage.energy_stored\", energy.getEnergyStored(), energy.getMaxEnergyStored()).setStyle(Styles.GRAY));\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/blockitem/FluidStorageBlockItem.java",
    "content": "package com.refinedmods.refinedstorage.item.blockitem;\n\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.StorageDiskSyncData;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.storage.FluidStorageNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType;\nimport com.refinedmods.refinedstorage.block.FluidStorageBlock;\nimport com.refinedmods.refinedstorage.item.FluidStoragePartItem;\nimport com.refinedmods.refinedstorage.item.ProcessorItem;\nimport com.refinedmods.refinedstorage.render.Styles;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.Containers;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.InteractionResultHolder;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.Items;\nimport net.minecraft.world.item.TooltipFlag;\nimport net.minecraft.world.level.Level;\n\nimport javax.annotation.Nullable;\nimport java.util.List;\nimport java.util.UUID;\n\npublic class FluidStorageBlockItem extends BaseBlockItem {\n    private final FluidStorageType type;\n\n    public FluidStorageBlockItem(FluidStorageBlock block) {\n        super(block, new Item.Properties());\n\n        this.type = block.getType();\n    }\n\n    @Override\n    public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {\n        super.appendHoverText(stack, level, tooltip, flag);\n\n        if (isValid(stack)) {\n            UUID id = getId(stack);\n\n            API.instance().getStorageDiskSync().sendRequest(id);\n\n            StorageDiskSyncData data = API.instance().getStorageDiskSync().getData(id);\n            if (data != null) {\n                if (data.getCapacity() == -1) {\n                    tooltip.add(Component.translatable(\"misc.refinedstorage.storage.stored\", API.instance().getQuantityFormatter().format(data.getStored())).setStyle(Styles.GRAY));\n                } else {\n                    tooltip.add(Component.translatable(\"misc.refinedstorage.storage.stored_capacity\", API.instance().getQuantityFormatter().format(data.getStored()), API.instance().getQuantityFormatter().format(data.getCapacity())).setStyle(Styles.GRAY));\n                }\n            }\n\n            if (flag.isAdvanced()) {\n                tooltip.add(Component.literal(id.toString()).setStyle(Styles.GRAY));\n            }\n        }\n    }\n\n    @Override\n    public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {\n        ItemStack storageStack = player.getItemInHand(hand);\n\n        if (!level.isClientSide && player.isCrouching() && type != FluidStorageType.CREATIVE) {\n            UUID diskId = null;\n            IStorageDisk disk = null;\n\n            if (isValid(storageStack)) {\n                diskId = getId(storageStack);\n                disk = API.instance().getStorageDiskManager((ServerLevel) level).get(diskId);\n            }\n\n            // Newly created fluid storages won't have a tag yet, so allow invalid disks as well.\n            if (disk == null || disk.getStored() == 0) {\n                ItemStack fluidStoragePart = new ItemStack(FluidStoragePartItem.getByType(type));\n\n                if (!player.getInventory().add(fluidStoragePart.copy())) {\n                    Containers.dropItemStack(level, player.getX(), player.getY(), player.getZ(), fluidStoragePart);\n                }\n\n                ItemStack processor = new ItemStack(RSItems.PROCESSORS.get(ProcessorItem.Type.BASIC).get());\n\n                if (!player.getInventory().add(processor.copy())) {\n                    Containers.dropItemStack(level, player.getX(), player.getY(), player.getZ(), processor);\n                }\n\n                ItemStack bucket = new ItemStack(Items.BUCKET);\n\n                if (!player.getInventory().add(bucket.copy())) {\n                    Containers.dropItemStack(level, player.getX(), player.getY(), player.getZ(), bucket);\n                }\n\n                if (disk != null) {\n                    API.instance().getStorageDiskManager((ServerLevel) level).remove(diskId);\n                    API.instance().getStorageDiskManager((ServerLevel) level).markForSaving();\n                }\n\n                return new InteractionResultHolder<>(InteractionResult.SUCCESS, new ItemStack(RSBlocks.MACHINE_CASING.get()));\n            }\n        }\n\n        return new InteractionResultHolder<>(InteractionResult.PASS, storageStack);\n    }\n\n    @Override\n    public int getEntityLifespan(ItemStack stack, Level level) {\n        return Integer.MAX_VALUE;\n    }\n\n    private UUID getId(ItemStack disk) {\n        return disk.getTag().getUUID(FluidStorageNetworkNode.NBT_ID);\n    }\n\n    private boolean isValid(ItemStack disk) {\n        return disk.hasTag() && disk.getTag().hasUUID(FluidStorageNetworkNode.NBT_ID);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/blockitem/PortableGridBlockItem.java",
    "content": "package com.refinedmods.refinedstorage.item.blockitem;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.grid.factory.PortableGridGridFactory;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport com.refinedmods.refinedstorage.item.WirelessGridItem;\nimport com.refinedmods.refinedstorage.render.Styles;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.InteractionResultHolder;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.TooltipFlag;\nimport net.minecraft.world.item.context.UseOnContext;\nimport net.minecraft.world.level.Level;\n\nimport javax.annotation.Nullable;\nimport java.util.List;\n\npublic class PortableGridBlockItem extends EnergyBlockItem {\n    private final Type type;\n\n    public PortableGridBlockItem(Type type) {\n        super(\n            type == Type.CREATIVE ? RSBlocks.CREATIVE_PORTABLE_GRID.get() : RSBlocks.PORTABLE_GRID.get(),\n            new Item.Properties().stacksTo(1),\n            type == Type.CREATIVE,\n            () -> RS.SERVER_CONFIG.getPortableGrid().getCapacity()\n        );\n\n        this.type = type;\n    }\n\n    public Type getType() {\n        return type;\n    }\n\n    @Override\n    public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {\n        ItemStack stack = player.getItemInHand(hand);\n\n        if (!level.isClientSide) {\n            API.instance().getGridManager().openGrid(PortableGridGridFactory.ID, (ServerPlayer) player, stack, PlayerSlot.getSlotForHand(player, hand));\n        }\n\n        return InteractionResultHolder.success(stack);\n    }\n\n    @Override\n    public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {\n        super.appendHoverText(stack, level, tooltip, flag);\n\n        tooltip.add(Component.translatable(\"block.refinedstorage.portable_grid.tooltip\").setStyle(Styles.GRAY));\n    }\n\n    @Override\n    public InteractionResult useOn(UseOnContext context) {\n        if (context.getPlayer() == null) {\n            return InteractionResult.FAIL;\n        }\n\n        //Place\n        if (context.getPlayer().isCrouching()) {\n            return super.useOn(context);\n        }\n\n        ItemStack stack = context.getPlayer().getItemInHand(context.getHand());\n\n        if (!context.getLevel().isClientSide) {\n            API.instance().getGridManager().openGrid(PortableGridGridFactory.ID, (ServerPlayer) context.getPlayer(), stack, PlayerSlot.getSlotForHand(context.getPlayer(), context.getHand()));\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n\n    @Override\n    public int getEntityLifespan(ItemStack stack, Level level) {\n        return Integer.MAX_VALUE;\n    }\n\n    @Override\n    public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {\n        if (oldStack.getItem() == newStack.getItem() &&\n            WirelessGridItem.getSortingDirection(oldStack) == WirelessGridItem.getSortingDirection(newStack) &&\n            WirelessGridItem.getSortingType(oldStack) == WirelessGridItem.getSortingType(newStack) &&\n            WirelessGridItem.getSearchBoxMode(oldStack) == WirelessGridItem.getSearchBoxMode(newStack) &&\n            WirelessGridItem.getTabSelected(oldStack) == WirelessGridItem.getTabSelected(newStack) &&\n            WirelessGridItem.getTabPage(oldStack) == WirelessGridItem.getTabPage(newStack) &&\n            WirelessGridItem.getSize(oldStack) == WirelessGridItem.getSize(newStack)) {\n            return false;\n        }\n\n        return super.shouldCauseReequipAnimation(oldStack, newStack, slotChanged);\n    }\n\n    public enum Type {\n        NORMAL,\n        CREATIVE\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/blockitem/StorageBlockItem.java",
    "content": "package com.refinedmods.refinedstorage.item.blockitem;\n\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.StorageDiskSyncData;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.storage.StorageNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType;\nimport com.refinedmods.refinedstorage.block.StorageBlock;\nimport com.refinedmods.refinedstorage.item.StoragePartItem;\nimport com.refinedmods.refinedstorage.render.Styles;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.Containers;\nimport net.minecraft.world.InteractionHand;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.InteractionResultHolder;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.TooltipFlag;\nimport net.minecraft.world.level.Level;\n\nimport javax.annotation.Nullable;\nimport java.util.List;\nimport java.util.UUID;\n\npublic class StorageBlockItem extends BaseBlockItem {\n    private final ItemStorageType type;\n\n    public StorageBlockItem(StorageBlock block) {\n        super(block, new Item.Properties());\n\n        this.type = block.getType();\n    }\n\n    @Override\n    public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {\n        super.appendHoverText(stack, level, tooltip, flag);\n\n        if (isValid(stack)) {\n            UUID id = getId(stack);\n\n            API.instance().getStorageDiskSync().sendRequest(id);\n\n            StorageDiskSyncData data = API.instance().getStorageDiskSync().getData(id);\n            if (data != null) {\n                if (data.getCapacity() == -1) {\n                    tooltip.add(Component.translatable(\"misc.refinedstorage.storage.stored\", API.instance().getQuantityFormatter().format(data.getStored())).setStyle(Styles.GRAY));\n                } else {\n                    tooltip.add(Component.translatable(\"misc.refinedstorage.storage.stored_capacity\", API.instance().getQuantityFormatter().format(data.getStored()), API.instance().getQuantityFormatter().format(data.getCapacity())).setStyle(Styles.GRAY));\n                }\n            }\n\n            if (flag.isAdvanced()) {\n                tooltip.add(Component.literal(id.toString()).setStyle(Styles.GRAY));\n            }\n        }\n    }\n\n    @Override\n    public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {\n        ItemStack storageStack = player.getItemInHand(hand);\n        int count = storageStack.getCount();\n\n        if (!level.isClientSide && player.isCrouching() && type != ItemStorageType.CREATIVE) {\n            UUID diskId = null;\n            IStorageDisk disk = null;\n\n            if (isValid(storageStack)) {\n                diskId = getId(storageStack);\n                disk = API.instance().getStorageDiskManager((ServerLevel) level).get(diskId);\n            }\n\n            // Newly created storages won't have a tag yet, so allow invalid disks as well.\n            if (disk == null || disk.getStored() == 0) {\n                ItemStack storagePart = new ItemStack(StoragePartItem.getByType(type));\n                storagePart.setCount(count);\n\n                if (!player.getInventory().add(storagePart.copy())) {\n                    Containers.dropItemStack(level, player.getX(), player.getY(), player.getZ(), storagePart);\n                }\n\n                if (disk != null) {\n                    API.instance().getStorageDiskManager((ServerLevel) level).remove(diskId);\n                    API.instance().getStorageDiskManager((ServerLevel) level).markForSaving();\n                }\n\n                ItemStack stack = new ItemStack(RSBlocks.MACHINE_CASING.get());\n                stack.setCount(count);\n                return new InteractionResultHolder<>(InteractionResult.SUCCESS, stack);\n            }\n        }\n\n        return new InteractionResultHolder<>(InteractionResult.PASS, storageStack);\n    }\n\n    @Override\n    public int getEntityLifespan(ItemStack stack, Level level) {\n        return Integer.MAX_VALUE;\n    }\n\n    private UUID getId(ItemStack disk) {\n        return disk.getTag().getUUID(StorageNetworkNode.NBT_ID);\n    }\n\n    private boolean isValid(ItemStack disk) {\n        return disk.hasTag() && disk.getTag().hasUUID(StorageNetworkNode.NBT_ID);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/property/ControllerItemPropertyGetter.java",
    "content": "package com.refinedmods.refinedstorage.item.property;\n\nimport com.refinedmods.refinedstorage.apiimpl.network.Network;\nimport com.refinedmods.refinedstorage.block.ControllerBlock;\nimport net.minecraft.client.multiplayer.ClientLevel;\nimport net.minecraft.client.renderer.item.ClampedItemPropertyFunction;\nimport net.minecraft.client.renderer.item.ItemPropertyFunction;\nimport net.minecraft.world.entity.LivingEntity;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.capabilities.Capabilities;\nimport net.neoforged.neoforge.energy.IEnergyStorage;\nimport javax.annotation.Nullable;\n\npublic class ControllerItemPropertyGetter implements ItemPropertyFunction {\n    @Override\n    public float call(ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int p) {\n        // if that stack is still clean (like in the creative mode tab, or just crafted) maintain the on state.\n        if (stack.getTag() == null) {\n            return ControllerBlock.EnergyType.ON.ordinal();\n        }\n        IEnergyStorage storage = stack.getCapability(Capabilities.EnergyStorage.ITEM);\n        if (storage != null) {\n            return Network.getEnergyType(storage.getEnergyStored(), storage.getMaxEnergyStored()).ordinal();\n        }\n        return ControllerBlock.EnergyType.ON.ordinal();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/property/NetworkItemPropertyGetter.java",
    "content": "package com.refinedmods.refinedstorage.item.property;\n\nimport com.refinedmods.refinedstorage.item.NetworkItem;\nimport net.minecraft.client.multiplayer.ClientLevel;\nimport net.minecraft.client.renderer.item.ClampedItemPropertyFunction;\nimport net.minecraft.client.renderer.item.ItemPropertyFunction;\nimport net.minecraft.world.entity.LivingEntity;\nimport net.minecraft.world.item.ItemStack;\n\nimport javax.annotation.Nullable;\n\npublic class NetworkItemPropertyGetter implements ClampedItemPropertyFunction {\n    @Override\n    public float unclampedCall(ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int p) {\n        return entity != null && NetworkItem.isValid(stack) ? 1.0f : 0.0f;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/item/property/SecurityCardItemPropertyGetter.java",
    "content": "package com.refinedmods.refinedstorage.item.property;\n\nimport com.refinedmods.refinedstorage.item.SecurityCardItem;\nimport net.minecraft.client.multiplayer.ClientLevel;\nimport net.minecraft.client.renderer.item.ClampedItemPropertyFunction;\nimport net.minecraft.client.renderer.item.ItemPropertyFunction;\nimport net.minecraft.world.entity.LivingEntity;\nimport net.minecraft.world.item.ItemStack;\n\nimport javax.annotation.Nullable;\n\npublic class SecurityCardItemPropertyGetter implements ClampedItemPropertyFunction {\n    @Override\n    public float unclampedCall(ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int p) {\n        return entity != null && SecurityCardItem.isValid(stack) ? 1.0f : 0.0f;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/loottable/ControllerLootFunction.java",
    "content": "package com.refinedmods.refinedstorage.loottable;\n\nimport com.refinedmods.refinedstorage.RSLootFunctions;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.blockentity.ControllerBlockEntity;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.storage.loot.LootContext;\nimport net.minecraft.world.level.storage.loot.functions.LootItemFunction;\nimport net.minecraft.world.level.storage.loot.functions.LootItemFunctionType;\nimport net.minecraft.world.level.storage.loot.parameters.LootContextParams;\nimport net.neoforged.neoforge.capabilities.Capabilities;\nimport net.neoforged.neoforge.energy.IEnergyStorage;\n\npublic class ControllerLootFunction implements LootItemFunction {\n    @Override\n    public LootItemFunctionType getType() {\n        return RSLootFunctions.CONTROLLER;\n    }\n\n    @Override\n    public ItemStack apply(ItemStack stack, LootContext lootContext) {\n        BlockEntity blockEntity = lootContext.getParamOrNull(LootContextParams.BLOCK_ENTITY);\n\n        if (blockEntity instanceof ControllerBlockEntity) {\n            INetwork network = ((ControllerBlockEntity) blockEntity).getRemovedNetwork() == null ? ((ControllerBlockEntity) blockEntity).getNetwork() : ((ControllerBlockEntity) blockEntity).getRemovedNetwork();\n\n            IEnergyStorage energyStorage = stack.getCapability(Capabilities.EnergyStorage.ITEM);\n            if (energyStorage != null) {\n                energyStorage.receiveEnergy(network.getEnergyStorage().getEnergyStored(), false);\n            }\n        }\n\n        return stack;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/loottable/CrafterLootFunction.java",
    "content": "package com.refinedmods.refinedstorage.loottable;\n\nimport com.refinedmods.refinedstorage.RSLootFunctions;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.CrafterNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.CrafterBlockEntity;\n\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.storage.loot.LootContext;\nimport net.minecraft.world.level.storage.loot.functions.LootItemFunction;\nimport net.minecraft.world.level.storage.loot.functions.LootItemFunctionType;\nimport net.minecraft.world.level.storage.loot.parameters.LootContextParams;\n\npublic class CrafterLootFunction implements LootItemFunction {\n    @Override\n    public LootItemFunctionType getType() {\n        return RSLootFunctions.CRAFTER;\n    }\n\n    @Override\n    public ItemStack apply(ItemStack stack, LootContext lootContext) {\n        BlockEntity blockEntity = lootContext.getParamOrNull(LootContextParams.BLOCK_ENTITY);\n\n        CrafterNetworkNode removedNode = ((CrafterBlockEntity) blockEntity).getRemovedNode();\n        if (removedNode == null) {\n            removedNode = ((CrafterBlockEntity) blockEntity).getNode();\n        }\n\n        if (removedNode.getDisplayName() != null) {\n            stack.setHoverName(removedNode.getDisplayName());\n        }\n\n        return stack;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/loottable/PortableGridBlockLootFunction.java",
    "content": "package com.refinedmods.refinedstorage.loottable;\n\nimport com.refinedmods.refinedstorage.RSLootFunctions;\nimport com.refinedmods.refinedstorage.blockentity.grid.portable.PortableGridBlockEntity;\n\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.storage.loot.LootContext;\nimport net.minecraft.world.level.storage.loot.functions.LootItemFunction;\nimport net.minecraft.world.level.storage.loot.functions.LootItemFunctionType;\nimport net.minecraft.world.level.storage.loot.parameters.LootContextParams;\n\npublic class PortableGridBlockLootFunction implements LootItemFunction {\n    @Override\n    public LootItemFunctionType getType() {\n        return RSLootFunctions.PORTABLE_GRID;\n    }\n\n    @Override\n    public ItemStack apply(ItemStack stack, LootContext lootContext) {\n        BlockEntity blockEntity = lootContext.getParamOrNull(LootContextParams.BLOCK_ENTITY);\n\n        if (blockEntity instanceof PortableGridBlockEntity) {\n            ((PortableGridBlockEntity) blockEntity).applyDataFromBlockEntityToItem(stack);\n        }\n\n        return stack;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/loottable/StorageBlockLootFunction.java",
    "content": "package com.refinedmods.refinedstorage.loottable;\n\nimport com.google.gson.JsonDeserializationContext;\nimport com.google.gson.JsonObject;\nimport com.refinedmods.refinedstorage.RSLootFunctions;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.storage.FluidStorageNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.storage.StorageNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.FluidStorageBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.StorageBlockEntity;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.level.storage.loot.LootContext;\nimport net.minecraft.world.level.storage.loot.functions.LootItemConditionalFunction;\nimport net.minecraft.world.level.storage.loot.functions.LootItemFunction;\nimport net.minecraft.world.level.storage.loot.functions.LootItemFunctionType;\nimport net.minecraft.world.level.storage.loot.parameters.LootContextParams;\nimport net.minecraft.world.level.storage.loot.predicates.LootItemCondition;\n\npublic class StorageBlockLootFunction implements LootItemFunction {\n    @Override\n    public LootItemFunctionType getType() {\n        return RSLootFunctions.STORAGE_BLOCK;\n    }\n\n    @Override\n    public ItemStack apply(ItemStack stack, LootContext lootContext) {\n        BlockEntity blockEntity = lootContext.getParamOrNull(LootContextParams.BLOCK_ENTITY);\n\n        // This code needs to work without the node being removed as well.\n        // For example: the Destructor calls getDrops before the node has been removed.\n\n        if (blockEntity instanceof StorageBlockEntity) {\n            StorageNetworkNode removedNode = ((StorageBlockEntity) blockEntity).getRemovedNode();\n            if (removedNode == null) {\n                removedNode = ((StorageBlockEntity) blockEntity).getNode();\n            }\n\n            stack.setTag(new CompoundTag());\n            stack.getTag().putUUID(StorageNetworkNode.NBT_ID, removedNode.getStorageId());\n        } else if (blockEntity instanceof FluidStorageBlockEntity) {\n            FluidStorageNetworkNode removedNode = ((FluidStorageBlockEntity) blockEntity).getRemovedNode();\n            if (removedNode == null) {\n                removedNode = ((FluidStorageBlockEntity) blockEntity).getNode();\n            }\n\n            stack.setTag(new CompoundTag());\n            stack.getTag().putUUID(FluidStorageNetworkNode.NBT_ID, removedNode.getStorageId());\n        }\n\n        return stack;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/ClientProxy.java",
    "content": "package com.refinedmods.refinedstorage.network;\n\nimport com.refinedmods.refinedstorage.network.craftingmonitor.CraftingMonitorUpdateMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridCraftingPreviewResponseMessage;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.screen.CraftingMonitorScreen;\nimport com.refinedmods.refinedstorage.screen.grid.CraftingPreviewScreen;\nimport com.refinedmods.refinedstorage.screen.grid.CraftingSettingsScreen;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.screens.Screen;\nimport net.minecraft.network.chat.Component;\n\n\npublic class ClientProxy {\n    private ClientProxy() {\n    }\n\n    public static void onReceivedCraftingPreviewResponseMessage(GridCraftingPreviewResponseMessage message) {\n        Screen parent = Minecraft.getInstance().screen;\n\n        if (parent instanceof CraftingSettingsScreen) {\n            parent = ((CraftingSettingsScreen) parent).getParent();\n        }\n\n        Minecraft.getInstance().setScreen(new CraftingPreviewScreen(\n            parent,\n            message.getElements(),\n            message.getId(),\n            message.getQuantity(),\n            message.isFluids(),\n            Component.translatable(\"gui.refinedstorage.crafting_preview\"),\n            Minecraft.getInstance().player.getInventory()\n        ));\n    }\n\n    public static void onReceivedCraftingStartResponseMessage() {\n        Screen screen = Minecraft.getInstance().screen;\n\n        if (screen instanceof CraftingSettingsScreen) {\n            ((CraftingSettingsScreen) screen).close();\n        }\n    }\n\n    public static void onReceivedCraftingMonitorUpdateMessage(CraftingMonitorUpdateMessage message) {\n        BaseScreen.executeLater(CraftingMonitorScreen.class, craftingMonitor -> craftingMonitor.setTasks(message.getTasks()));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/FilterUpdateMessage.java",
    "content": "package com.refinedmods.refinedstorage.network;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.container.FilterContainerMenu;\nimport com.refinedmods.refinedstorage.item.FilterItem;\nimport com.refinedmods.refinedstorage.util.PacketBufferUtils;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class FilterUpdateMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"filter_update\");\n\n    private final int compare;\n    private final int mode;\n    private final boolean modFilter;\n    private final String name;\n    private final int type;\n\n    public FilterUpdateMessage(int compare, int mode, boolean modFilter, String name, int type) {\n        this.compare = compare;\n        this.mode = mode;\n        this.modFilter = modFilter;\n        this.name = name;\n        this.type = type;\n    }\n\n    public static FilterUpdateMessage decode(FriendlyByteBuf buf) {\n        return new FilterUpdateMessage(\n            buf.readInt(),\n            buf.readInt(),\n            buf.readBoolean(),\n            PacketBufferUtils.readString(buf),\n            buf.readInt()\n        );\n    }\n\n    public static void handle(FilterUpdateMessage message, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            FilterItem.setCompare(((FilterContainerMenu) player.containerMenu).getFilterItem(), message.compare);\n            FilterItem.setMode(((FilterContainerMenu) player.containerMenu).getFilterItem(), message.mode);\n            FilterItem.setModFilter(((FilterContainerMenu) player.containerMenu).getFilterItem(), message.modFilter);\n            FilterItem.setName(((FilterContainerMenu) player.containerMenu).getFilterItem(), message.name);\n            FilterItem.setType(((FilterContainerMenu) player.containerMenu).getFilterItem(), message.type);\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeInt(compare);\n        buf.writeInt(mode);\n        buf.writeBoolean(modFilter);\n        buf.writeUtf(name);\n        buf.writeInt(type);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/FluidFilterSlotUpdateMessage.java",
    "content": "package com.refinedmods.refinedstorage.network;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.inventory.Slot;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class FluidFilterSlotUpdateMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"fluid_filter_update\");\n\n    private final int containerSlot;\n    private final FluidStack stack;\n\n    public FluidFilterSlotUpdateMessage(int containerSlot, FluidStack stack) {\n        this.containerSlot = containerSlot;\n        this.stack = stack;\n    }\n\n    public static FluidFilterSlotUpdateMessage decode(FriendlyByteBuf buf) {\n        return new FluidFilterSlotUpdateMessage(buf.readInt(), FluidStack.readFromPacket(buf));\n    }\n\n    public static void handle(FluidFilterSlotUpdateMessage message, PlayPayloadContext ctx) {\n        BaseScreen.executeLater(gui -> {\n            if (message.containerSlot >= 0 && message.containerSlot < gui.getMenu().slots.size()) {\n                Slot slot = gui.getMenu().getSlot(message.containerSlot);\n\n                if (slot instanceof FluidFilterSlot) {\n                    ((FluidFilterSlot) slot).getFluidInventory().setFluid(slot.getSlotIndex(), message.stack);\n                }\n            }\n        });\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeInt(containerSlot);\n        stack.writeToPacket(buf);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/NetworkHandler.java",
    "content": "package com.refinedmods.refinedstorage.network;\n\nimport com.refinedmods.refinedstorage.network.craftingmonitor.CraftingMonitorCancelMessage;\nimport com.refinedmods.refinedstorage.network.craftingmonitor.CraftingMonitorUpdateMessage;\nimport com.refinedmods.refinedstorage.network.craftingmonitor.WirelessCraftingMonitorSettingsUpdateMessage;\nimport com.refinedmods.refinedstorage.network.disk.StorageDiskSizeRequestMessage;\nimport com.refinedmods.refinedstorage.network.disk.StorageDiskSizeResponseMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridClearMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridCraftingPreviewRequestMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridCraftingPreviewResponseMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridCraftingStartRequestMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridCraftingStartResponseMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridFluidDeltaMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridFluidInsertHeldMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridFluidPullMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridFluidUpdateMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridItemDeltaMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridItemGridScrollMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridItemInsertHeldMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridItemInventoryScrollMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridItemPullMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridItemUpdateMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridPatternCreateMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridProcessingTransferMessage;\nimport com.refinedmods.refinedstorage.network.grid.GridTransferMessage;\nimport com.refinedmods.refinedstorage.network.grid.PortableGridSettingsUpdateMessage;\nimport com.refinedmods.refinedstorage.network.grid.WirelessFluidGridSettingsUpdateMessage;\nimport com.refinedmods.refinedstorage.network.grid.WirelessGridSettingsUpdateMessage;\nimport com.refinedmods.refinedstorage.network.sync.BlockEntitySynchronizationParameterMessage;\nimport com.refinedmods.refinedstorage.network.sync.BlockEntitySynchronizationParameterUpdateMessage;\n\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.neoforged.neoforge.common.util.FakePlayer;\nimport net.neoforged.neoforge.network.PacketDistributor;\nimport net.neoforged.neoforge.network.registration.IPayloadRegistrar;\n\npublic class NetworkHandler {\n    public void register(IPayloadRegistrar registrar) {\n        registrar.play(\n            StorageDiskSizeRequestMessage.ID,\n            StorageDiskSizeRequestMessage::decode,\n            handler -> handler.server(StorageDiskSizeRequestMessage::handle)\n        );\n        registrar.play(\n            StorageDiskSizeResponseMessage.ID,\n            StorageDiskSizeResponseMessage::decode,\n            handler -> handler.client(StorageDiskSizeResponseMessage::handle)\n        );\n        registrar.play(\n            FilterUpdateMessage.ID,\n            FilterUpdateMessage::decode,\n            handler -> handler.server(FilterUpdateMessage::handle)\n        );\n        registrar.play(\n            FluidFilterSlotUpdateMessage.ID,\n            FluidFilterSlotUpdateMessage::decode,\n            handler -> handler.client(FluidFilterSlotUpdateMessage::handle)\n        );\n        registrar.play(\n            BlockEntitySynchronizationParameterMessage.ID,\n            BlockEntitySynchronizationParameterMessage::decode,\n            handler -> handler.client(BlockEntitySynchronizationParameterMessage::handle)\n        );\n        registrar.play(\n            BlockEntitySynchronizationParameterUpdateMessage.ID,\n            BlockEntitySynchronizationParameterUpdateMessage::decode,\n            handler -> handler.server(BlockEntitySynchronizationParameterUpdateMessage::handle)\n        );\n        registrar.play(\n            GridItemUpdateMessage.ID,\n            GridItemUpdateMessage::decode,\n            handler -> handler.client(GridItemUpdateMessage::handle)\n        );\n        registrar.play(\n            GridItemDeltaMessage.ID,\n            GridItemDeltaMessage::decode,\n            handler -> handler.client(GridItemDeltaMessage::handle)\n        );\n        registrar.play(\n            GridItemPullMessage.ID,\n            GridItemPullMessage::decode,\n            handler -> handler.server(GridItemPullMessage::handle)\n        );\n        registrar.play(\n            GridItemGridScrollMessage.ID,\n            GridItemGridScrollMessage::decode,\n            handler -> handler.server(GridItemGridScrollMessage::handle)\n        );\n        registrar.play(\n            GridItemInventoryScrollMessage.ID,\n            GridItemInventoryScrollMessage::decode,\n            handler -> handler.server(GridItemInventoryScrollMessage::handle)\n        );\n        registrar.play(\n            GridItemInsertHeldMessage.ID,\n            GridItemInsertHeldMessage::decode,\n            handler -> handler.server(GridItemInsertHeldMessage::handle)\n        );\n        registrar.play(\n            GridClearMessage.ID,\n            ctx -> new GridClearMessage(),\n            handler -> handler.server(GridClearMessage::handle)\n        );\n        registrar.play(\n            GridPatternCreateMessage.ID,\n            GridPatternCreateMessage::decode,\n            handler -> handler.server(GridPatternCreateMessage::handle)\n        );\n        registrar.play(\n            SetFilterSlotMessage.ID,\n            SetFilterSlotMessage::decode,\n            handler -> handler.server(SetFilterSlotMessage::handle)\n        );\n        registrar.play(\n            SetFluidFilterSlotMessage.ID,\n            SetFluidFilterSlotMessage::decode,\n            handler -> handler.server(SetFluidFilterSlotMessage::handle)\n        );\n        registrar.play(\n            GridFluidUpdateMessage.ID,\n            GridFluidUpdateMessage::decode,\n            handler -> handler.client(GridFluidUpdateMessage::handle)\n        );\n        registrar.play(\n            GridFluidDeltaMessage.ID,\n            GridFluidDeltaMessage::decode,\n            handler -> handler.client(GridFluidDeltaMessage::handle)\n        );\n        registrar.play(\n            GridFluidInsertHeldMessage.ID,\n            ctx -> new GridFluidInsertHeldMessage(),\n            handler -> handler.server(GridFluidInsertHeldMessage::handle)\n        );\n        registrar.play(\n            GridFluidPullMessage.ID,\n            GridFluidPullMessage::decode,\n            handler -> handler.server(GridFluidPullMessage::handle)\n        );\n        registrar.play(\n            GridTransferMessage.ID,\n            GridTransferMessage::decode,\n            handler -> handler.server(GridTransferMessage::handle)\n        );\n        registrar.play(\n            GridProcessingTransferMessage.ID,\n            GridProcessingTransferMessage::decode,\n            handler -> handler.server(GridProcessingTransferMessage::handle)\n        );\n        registrar.play(\n            SecurityManagerUpdateMessage.ID,\n            SecurityManagerUpdateMessage::decode,\n            handler -> handler.server(SecurityManagerUpdateMessage::handle)\n        );\n        registrar.play(\n            WirelessGridSettingsUpdateMessage.ID,\n            WirelessGridSettingsUpdateMessage::decode,\n            handler -> handler.server(WirelessGridSettingsUpdateMessage::handle)\n        );\n        registrar.play(\n            OpenNetworkItemMessage.ID,\n            OpenNetworkItemMessage::decode,\n            handler -> handler.server(OpenNetworkItemMessage::handle)\n        );\n        registrar.play(\n            WirelessFluidGridSettingsUpdateMessage.ID,\n            WirelessFluidGridSettingsUpdateMessage::decode,\n            handler -> handler.server(WirelessFluidGridSettingsUpdateMessage::handle)\n        );\n        registrar.play(\n            PortableGridSettingsUpdateMessage.ID,\n            PortableGridSettingsUpdateMessage::decode,\n            handler -> handler.server(PortableGridSettingsUpdateMessage::handle)\n        );\n        registrar.play(\n            GridCraftingPreviewRequestMessage.ID,\n            GridCraftingPreviewRequestMessage::decode,\n            handler -> handler.server(GridCraftingPreviewRequestMessage::handle)\n        );\n        registrar.play(\n            GridCraftingPreviewResponseMessage.ID,\n            GridCraftingPreviewResponseMessage::decode,\n            handler -> handler.client(GridCraftingPreviewResponseMessage::handle)\n        );\n        registrar.play(\n            GridCraftingStartRequestMessage.ID,\n            GridCraftingStartRequestMessage::decode,\n            handler -> handler.server(GridCraftingStartRequestMessage::handle)\n        );\n        registrar.play(\n            GridCraftingStartResponseMessage.ID,\n            buf -> new GridCraftingStartResponseMessage(),\n            handler -> handler.client(GridCraftingStartResponseMessage::handle)\n        );\n        registrar.play(\n            CraftingMonitorUpdateMessage.ID,\n            CraftingMonitorUpdateMessage::decode,\n            handler -> handler.client(CraftingMonitorUpdateMessage::handle)\n        );\n        registrar.play(\n            CraftingMonitorCancelMessage.ID,\n            CraftingMonitorCancelMessage::decode,\n            handler -> handler.server(CraftingMonitorCancelMessage::handle)\n        );\n        registrar.play(\n            WirelessCraftingMonitorSettingsUpdateMessage.ID,\n            WirelessCraftingMonitorSettingsUpdateMessage::decode,\n            handler -> handler.server(WirelessCraftingMonitorSettingsUpdateMessage::handle)\n        );\n    }\n\n    public void sendTo(ServerPlayer player, CustomPacketPayload message) {\n        if (!(player instanceof FakePlayer)) {\n            PacketDistributor.PLAYER.with(player).send(message);\n        }\n    }\n\n    public void sendToServer(CustomPacketPayload message) {\n        PacketDistributor.SERVER.noArg().send(message);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/OpenNetworkItemMessage.java",
    "content": "package com.refinedmods.refinedstorage.network;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.grid.factory.PortableGridGridFactory;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport com.refinedmods.refinedstorage.item.NetworkItem;\nimport com.refinedmods.refinedstorage.item.blockitem.PortableGridBlockItem;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class OpenNetworkItemMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"open_network_item\");\n\n    private final PlayerSlot slot;\n\n    public OpenNetworkItemMessage(PlayerSlot slot) {\n        this.slot = slot;\n    }\n\n    public static OpenNetworkItemMessage decode(FriendlyByteBuf buf) {\n        return new OpenNetworkItemMessage(new PlayerSlot(buf));\n    }\n\n    public static void handle(OpenNetworkItemMessage message, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            ItemStack stack = message.slot.getStackFromSlot(player);\n\n            if (stack == null) {\n                return;\n            }\n\n            if (stack.getItem() instanceof NetworkItem) {\n                ((NetworkItem) stack.getItem()).applyNetwork(player.getServer(), stack,\n                    n -> n.getNetworkItemManager().open(player, stack, message.slot), player::sendSystemMessage);\n            } else if (stack.getItem() instanceof PortableGridBlockItem) {\n                API.instance().getGridManager()\n                    .openGrid(PortableGridGridFactory.ID, (ServerPlayer) player, stack, message.slot);\n            }\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        slot.writePlayerSlot(buf);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/SecurityManagerUpdateMessage.java",
    "content": "package com.refinedmods.refinedstorage.network;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.blockentity.SecurityManagerBlockEntity;\nimport com.refinedmods.refinedstorage.container.SecurityManagerContainerMenu;\n\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class SecurityManagerUpdateMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"security_manager_update\");\n\n    private final Permission permission;\n    private final boolean state;\n\n    public SecurityManagerUpdateMessage(Permission permission, boolean state) {\n        this.permission = permission;\n        this.state = state;\n    }\n\n    public static SecurityManagerUpdateMessage decode(FriendlyByteBuf buf) {\n        int id = buf.readInt();\n        Permission permission = Permission.INSERT;\n\n        for (Permission otherPermission : Permission.values()) {\n            if (otherPermission.getId() == id) {\n                permission = otherPermission;\n                break;\n            }\n        }\n\n        boolean state = buf.readBoolean();\n\n        return new SecurityManagerUpdateMessage(permission, state);\n    }\n\n    public static void handle(SecurityManagerUpdateMessage message, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            if (player.containerMenu instanceof SecurityManagerContainerMenu securityManagerContainerMenu) {\n                securityManagerContainerMenu.updatePermission(message.permission, message.state);\n            }\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeInt(permission.getId());\n        buf.writeBoolean(state);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/SetFilterSlotMessage.java",
    "content": "package com.refinedmods.refinedstorage.network;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport com.refinedmods.refinedstorage.container.slot.filter.FilterSlot;\nimport com.refinedmods.refinedstorage.container.slot.legacy.LegacyFilterSlot;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.minecraft.world.inventory.Slot;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class SetFilterSlotMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"set_filter_slot\");\n\n    private final int containerSlot;\n    private final ItemStack stack;\n\n    public SetFilterSlotMessage(int containerSlot, ItemStack stack) {\n        this.containerSlot = containerSlot;\n        this.stack = stack;\n    }\n\n    public static SetFilterSlotMessage decode(FriendlyByteBuf buf) {\n        return new SetFilterSlotMessage(buf.readInt(), buf.readItem());\n    }\n\n    public static void handle(SetFilterSlotMessage message, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            if (!message.stack.isEmpty() && message.stack.getCount() <= message.stack.getMaxStackSize()) {\n                AbstractContainerMenu container = player.containerMenu;\n\n                if (container != null && message.containerSlot >= 0 && message.containerSlot < container.slots.size()) {\n                    handle(message, container);\n                }\n            }\n        }));\n    }\n\n    private static void handle(SetFilterSlotMessage message, AbstractContainerMenu container) {\n        Slot slot = container.getSlot(message.containerSlot);\n\n        if (slot instanceof FilterSlot || slot instanceof LegacyFilterSlot) {\n            Runnable postAction = () -> {\n            };\n\n            // Prevent the grid crafting matrix inventory listener from resetting the list.\n            if (container instanceof GridContainerMenu) {\n                IGrid grid = ((GridContainerMenu) container).getGrid();\n                //exclude output slots\n                if (grid instanceof GridNetworkNode &&\n                    slot.getSlotIndex() < ((GridNetworkNode) grid).getAllowedTagList().getAllowedItemTags().size()) {\n                    Set<ResourceLocation> list = new HashSet<>(\n                        ((GridNetworkNode) grid).getAllowedTagList().getAllowedItemTags().get(slot.getSlotIndex()));\n\n                    postAction = () -> {\n                        ((GridNetworkNode) grid).getAllowedTagList().setAllowedItemTags(slot.getSlotIndex(), list);\n                        ((GridNetworkNode) grid).markDirty();\n                    };\n                }\n            }\n\n            slot.set(message.stack);\n            postAction.run();\n        }\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeInt(containerSlot);\n        buf.writeItem(stack);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/SetFluidFilterSlotMessage.java",
    "content": "package com.refinedmods.refinedstorage.network;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.minecraft.world.inventory.Slot;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class SetFluidFilterSlotMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"set_fluid_filter_slot\");\n\n    private final int containerSlot;\n    private final FluidStack stack;\n\n    public SetFluidFilterSlotMessage(int containerSlot, FluidStack stack) {\n        this.containerSlot = containerSlot;\n        this.stack = stack;\n    }\n\n    public static SetFluidFilterSlotMessage decode(FriendlyByteBuf buf) {\n        return new SetFluidFilterSlotMessage(buf.readInt(), FluidStack.readFromPacket(buf));\n    }\n\n    public static void handle(SetFluidFilterSlotMessage message, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            AbstractContainerMenu container = player.containerMenu;\n\n            if (!message.stack.isEmpty() && container != null && message.containerSlot >= 0 &&\n                message.containerSlot < container.slots.size()) {\n                handle(message, container);\n            }\n        }));\n    }\n\n    private static void handle(SetFluidFilterSlotMessage message, AbstractContainerMenu container) {\n        Slot slot = container.getSlot(message.containerSlot);\n\n        if (slot instanceof FluidFilterSlot) {\n            Runnable postAction = () -> {\n            };\n\n            // Prevent the grid crafting matrix inventory listener from resetting the list.\n            if (container instanceof GridContainerMenu) {\n                IGrid grid = ((GridContainerMenu) container).getGrid();\n                if (grid instanceof GridNetworkNode &&\n                    slot.getSlotIndex() < ((GridNetworkNode) grid).getAllowedTagList().getAllowedFluidTags().size()) {\n                    Set<ResourceLocation> list = new HashSet<>(\n                        ((GridNetworkNode) grid).getAllowedTagList().getAllowedFluidTags().get(slot.getSlotIndex()));\n\n                    postAction = () -> {\n                        ((GridNetworkNode) grid).getAllowedTagList().setAllowedFluidTags(slot.getSlotIndex(), list);\n                        ((GridNetworkNode) grid).markDirty();\n                    };\n                }\n            }\n\n            FluidFilterSlot fluidSlot = (FluidFilterSlot) slot;\n\n            fluidSlot.getFluidInventory().setFluid(slot.getSlotIndex(), message.stack);\n            postAction.run();\n        }\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeInt(containerSlot);\n        stack.writeToPacket(buf);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/craftingmonitor/CraftingMonitorCancelMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.craftingmonitor;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.container.CraftingMonitorContainerMenu;\n\nimport java.util.UUID;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class CraftingMonitorCancelMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"crafting_monitor_cancel\");\n\n    @Nullable\n    private final UUID taskId;\n\n    public CraftingMonitorCancelMessage(@Nullable UUID taskId) {\n        this.taskId = taskId;\n    }\n\n    public static CraftingMonitorCancelMessage decode(FriendlyByteBuf buf) {\n        return new CraftingMonitorCancelMessage(buf.readBoolean() ? buf.readUUID() : null);\n    }\n\n    public static void handle(CraftingMonitorCancelMessage message, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            if (player.containerMenu instanceof CraftingMonitorContainerMenu) {\n                ((CraftingMonitorContainerMenu) player.containerMenu).getCraftingMonitor().onCancelled(\n                    (ServerPlayer) player,\n                    message.taskId\n                );\n            }\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeBoolean(taskId != null);\n\n        if (taskId != null) {\n            buf.writeUUID(taskId);\n        }\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/craftingmonitor/CraftingMonitorSyncTask.java",
    "content": "package com.refinedmods.refinedstorage.network.craftingmonitor;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingRequestInfo;\n\nimport java.util.List;\nimport java.util.UUID;\n\npublic record CraftingMonitorSyncTask(UUID id,\n                                      ICraftingRequestInfo requestInfo,\n                                      int quantity,\n                                      long startTime,\n                                      int completionPercentage,\n                                      List<ICraftingMonitorElement> elements) {\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/craftingmonitor/CraftingMonitorUpdateMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.craftingmonitor;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingRequestInfo;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask;\nimport com.refinedmods.refinedstorage.api.network.grid.IGridTab;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.blockentity.craftingmonitor.ICraftingMonitor;\nimport com.refinedmods.refinedstorage.network.ClientProxy;\nimport com.refinedmods.refinedstorage.screen.CraftingMonitorScreen;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.UUID;\nimport java.util.function.Function;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\n\npublic class CraftingMonitorUpdateMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"crafting_monitor_update\");\n\n    private static final Logger LOGGER = LogManager.getLogger(CraftingMonitorUpdateMessage.class);\n\n    private final List<CraftingMonitorSyncTask> tasks;\n\n    public CraftingMonitorUpdateMessage(List<CraftingMonitorSyncTask> tasks) {\n        this.tasks = tasks;\n    }\n\n    public static CraftingMonitorUpdateMessage decode(FriendlyByteBuf buf) {\n        int size = buf.readInt();\n\n        List<CraftingMonitorSyncTask> tasks = new ArrayList<>();\n\n        for (int i = 0; i < size; ++i) {\n            UUID id = buf.readUUID();\n\n            ICraftingRequestInfo requested = null;\n            try {\n                requested = API.instance().createCraftingRequestInfo(buf.readNbt());\n            } catch (CraftingTaskReadException e) {\n                LOGGER.error(\"Could not create crafting request info\", e);\n            }\n\n            int qty = buf.readInt();\n            long executionStarted = buf.readLong();\n            int percentage = buf.readInt();\n\n            List<ICraftingMonitorElement> elements = new ArrayList<>();\n\n            int elementCount = buf.readInt();\n\n            for (int j = 0; j < elementCount; ++j) {\n                Function<FriendlyByteBuf, ICraftingMonitorElement> factory =\n                    API.instance().getCraftingMonitorElementRegistry().get(buf.readResourceLocation());\n\n                if (factory != null) {\n                    elements.add(factory.apply(buf));\n                }\n            }\n\n            tasks.add(new CraftingMonitorSyncTask(id, requested, qty, executionStarted, percentage, elements));\n        }\n\n        return new CraftingMonitorUpdateMessage(tasks);\n    }\n\n    public static void handle(CraftingMonitorUpdateMessage message, PlayPayloadContext ctx) {\n        ctx.workHandler().submitAsync(() -> ClientProxy.onReceivedCraftingMonitorUpdateMessage(message));\n    }\n\n    public List<CraftingMonitorSyncTask> getTasks() {\n        return tasks;\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeInt(tasks.size());\n\n        for (CraftingMonitorSyncTask task : tasks) {\n            buf.writeUUID(task.id());\n            buf.writeNbt(task.requestInfo().writeToNbt());\n            buf.writeInt(task.quantity());\n            buf.writeLong(task.startTime());\n            buf.writeInt(task.completionPercentage());\n\n            List<ICraftingMonitorElement> elements = task.elements();\n\n            buf.writeInt(elements.size());\n\n            for (ICraftingMonitorElement element : elements) {\n                buf.writeResourceLocation(element.getId());\n\n                element.write(buf);\n            }\n        }\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/craftingmonitor/WirelessCraftingMonitorSettingsUpdateMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.craftingmonitor;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.blockentity.craftingmonitor.WirelessCraftingMonitor;\nimport com.refinedmods.refinedstorage.container.CraftingMonitorContainerMenu;\n\nimport java.util.Optional;\nimport java.util.UUID;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class WirelessCraftingMonitorSettingsUpdateMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"wireless_crafting_monitor_settings_update\");\n\n    private final Optional<UUID> tabSelected;\n    private final int tabPage;\n\n    public WirelessCraftingMonitorSettingsUpdateMessage(Optional<UUID> tabSelected, int tabPage) {\n        this.tabSelected = tabSelected;\n        this.tabPage = tabPage;\n    }\n\n    public static WirelessCraftingMonitorSettingsUpdateMessage decode(FriendlyByteBuf buf) {\n        Optional<UUID> tabSelected = Optional.empty();\n\n        if (buf.readBoolean()) {\n            tabSelected = Optional.of(buf.readUUID());\n        }\n\n        int tabPage = buf.readInt();\n\n        return new WirelessCraftingMonitorSettingsUpdateMessage(tabSelected, tabPage);\n    }\n\n    public static void handle(WirelessCraftingMonitorSettingsUpdateMessage message, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            if (player.containerMenu instanceof CraftingMonitorContainerMenu) {\n                ((WirelessCraftingMonitor) ((CraftingMonitorContainerMenu) player.containerMenu).getCraftingMonitor()).setSettings(\n                    message.tabSelected, message.tabPage);\n            }\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeBoolean(tabSelected.isPresent());\n\n        tabSelected.ifPresent(buf::writeUUID);\n\n        buf.writeInt(tabPage);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/disk/StorageDiskSizeRequestMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.disk;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\nimport java.util.UUID;\n\npublic class StorageDiskSizeRequestMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"storage_disk_size_request\");\n\n    private final UUID id;\n\n    public StorageDiskSizeRequestMessage(UUID id) {\n        this.id = id;\n    }\n\n    public static StorageDiskSizeRequestMessage decode(FriendlyByteBuf buf) {\n        return new StorageDiskSizeRequestMessage(buf.readUUID());\n    }\n\n    public static void handle(StorageDiskSizeRequestMessage message, PlayPayloadContext context) {\n        context.player().ifPresent(player -> context.workHandler().submitAsync(() -> {\n            IStorageDisk disk = API.instance().getStorageDiskManager(((ServerPlayer) player).serverLevel()).get(message.id);\n\n            if (disk != null) {\n                RS.NETWORK_HANDLER.sendTo((ServerPlayer) player, new StorageDiskSizeResponseMessage(message.id, disk.getStored(), disk.getCapacity()));\n            }\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeUUID(id);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/disk/StorageDiskSizeResponseMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.disk;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.storage.disk.StorageDiskSyncData;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.storage.disk.StorageDiskSync;\n\nimport java.util.UUID;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class StorageDiskSizeResponseMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"storage_disk_size_response\");\n\n    private final UUID id;\n    private final int stored;\n    private final int capacity;\n\n    public StorageDiskSizeResponseMessage(UUID id, int stored, int capacity) {\n        this.id = id;\n        this.stored = stored;\n        this.capacity = capacity;\n    }\n\n    public static StorageDiskSizeResponseMessage decode(FriendlyByteBuf buf) {\n        return new StorageDiskSizeResponseMessage(buf.readUUID(), buf.readInt(), buf.readInt());\n    }\n\n    public static void handle(StorageDiskSizeResponseMessage message, PlayPayloadContext context) {\n        context.workHandler().submitAsync(() -> ((StorageDiskSync) API.instance().getStorageDiskSync()).setData(\n            message.id,\n            new StorageDiskSyncData(message.stored, message.capacity)\n        ));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeUUID(id);\n        buf.writeInt(stored);\n        buf.writeInt(capacity);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/GridClearMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class GridClearMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"grid_clear\");\n\n    public static void handle(GridClearMessage msg, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            AbstractContainerMenu container = player.containerMenu;\n\n            if (container instanceof GridContainerMenu) {\n                ((GridContainerMenu) container).getGrid().onClear(player);\n            }\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        // no op\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/GridCraftingPreviewRequestMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\n\nimport java.util.UUID;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class GridCraftingPreviewRequestMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"grid_crafting_preview_request\");\n\n    private final UUID id;\n    private final int quantity;\n    private final boolean noPreview;\n    private final boolean fluids;\n\n    public GridCraftingPreviewRequestMessage(UUID id, int quantity, boolean noPreview, boolean fluids) {\n        this.id = id;\n        this.quantity = quantity;\n        this.noPreview = noPreview;\n        this.fluids = fluids;\n    }\n\n    public static GridCraftingPreviewRequestMessage decode(FriendlyByteBuf buf) {\n        return new GridCraftingPreviewRequestMessage(\n            buf.readUUID(),\n            buf.readInt(),\n            buf.readBoolean(),\n            buf.readBoolean()\n        );\n    }\n\n    public static void handle(GridCraftingPreviewRequestMessage message, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            AbstractContainerMenu container = player.containerMenu;\n\n            if (container instanceof GridContainerMenu) {\n                IGrid grid = ((GridContainerMenu) container).getGrid();\n\n                if (message.fluids) {\n                    if (grid.getFluidHandler() != null) {\n                        grid.getFluidHandler()\n                            .onCraftingPreviewRequested((ServerPlayer) player, message.id, message.quantity,\n                                message.noPreview);\n                    }\n                } else {\n                    if (grid.getItemHandler() != null) {\n                        grid.getItemHandler()\n                            .onCraftingPreviewRequested((ServerPlayer) player, message.id, message.quantity,\n                                message.noPreview);\n                    }\n                }\n            }\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeUUID(id);\n        buf.writeInt(quantity);\n        buf.writeBoolean(noPreview);\n        buf.writeBoolean(fluids);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/GridCraftingPreviewResponseMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.network.ClientProxy;\n\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.UUID;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class GridCraftingPreviewResponseMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"grid_crafting_preview_response\");\n\n    private final List<ICraftingPreviewElement> elements;\n    private final UUID id;\n    private final int quantity;\n    private final boolean fluids;\n\n    public GridCraftingPreviewResponseMessage(List<ICraftingPreviewElement> elements, UUID id, int quantity,\n                                              boolean fluids) {\n        this.elements = elements;\n        this.id = id;\n        this.quantity = quantity;\n        this.fluids = fluids;\n    }\n\n    public static GridCraftingPreviewResponseMessage decode(FriendlyByteBuf buf) {\n        UUID id = buf.readUUID();\n        int quantity = buf.readInt();\n        boolean fluids = buf.readBoolean();\n\n        List<ICraftingPreviewElement> elements = new LinkedList<>();\n\n        int size = buf.readInt();\n\n        for (int i = 0; i < size; i++) {\n            ResourceLocation type = buf.readResourceLocation();\n            elements.add(API.instance().getCraftingPreviewElementRegistry().get(type).apply(buf));\n        }\n\n        return new GridCraftingPreviewResponseMessage(elements, id, quantity, fluids);\n    }\n\n    public static void handle(GridCraftingPreviewResponseMessage message, PlayPayloadContext ctx) {\n        ctx.workHandler().submitAsync(() -> ClientProxy.onReceivedCraftingPreviewResponseMessage(message));\n    }\n\n    public List<ICraftingPreviewElement> getElements() {\n        return elements;\n    }\n\n    public UUID getId() {\n        return id;\n    }\n\n    public int getQuantity() {\n        return quantity;\n    }\n\n    public boolean isFluids() {\n        return fluids;\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeUUID(id);\n        buf.writeInt(quantity);\n        buf.writeBoolean(fluids);\n        buf.writeInt(elements.size());\n\n        for (ICraftingPreviewElement element : elements) {\n            buf.writeResourceLocation(element.getId());\n            element.write(buf);\n        }\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/GridCraftingStartRequestMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\n\nimport java.util.UUID;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class GridCraftingStartRequestMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"grid_crafting_start_request\");\n\n    private final UUID id;\n    private final int quantity;\n    private final boolean fluids;\n\n    public GridCraftingStartRequestMessage(UUID id, int quantity, boolean fluids) {\n        this.id = id;\n        this.quantity = quantity;\n        this.fluids = fluids;\n    }\n\n    public static GridCraftingStartRequestMessage decode(FriendlyByteBuf buf) {\n        return new GridCraftingStartRequestMessage(\n            buf.readUUID(),\n            buf.readInt(),\n            buf.readBoolean()\n        );\n    }\n\n    public static void handle(GridCraftingStartRequestMessage message, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            AbstractContainerMenu container = player.containerMenu;\n\n            if (container instanceof GridContainerMenu) {\n                IGrid grid = ((GridContainerMenu) container).getGrid();\n\n                if (message.fluids) {\n                    if (grid.getFluidHandler() != null) {\n                        grid.getFluidHandler().onCraftingRequested((ServerPlayer) player, message.id, message.quantity);\n                    }\n                } else {\n                    if (grid.getItemHandler() != null) {\n                        grid.getItemHandler().onCraftingRequested((ServerPlayer) player, message.id, message.quantity);\n                    }\n                }\n            }\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeUUID(id);\n        buf.writeInt(quantity);\n        buf.writeBoolean(fluids);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/GridCraftingStartResponseMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.network.ClientProxy;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class GridCraftingStartResponseMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"grid_crafting_start_response\");\n\n    public static void handle(GridCraftingStartResponseMessage msg, PlayPayloadContext ctx) {\n        ctx.workHandler().submitAsync(ClientProxy::onReceivedCraftingStartResponseMessage);\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        // no op\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/GridFluidDeltaMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.screen.grid.GridScreen;\nimport com.refinedmods.refinedstorage.screen.grid.stack.FluidGridStack;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\nimport java.util.LinkedList;\nimport java.util.List;\n\npublic class GridFluidDeltaMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"grid_fluid_delta\");\n\n    private final List<GridStackDelta<FluidGridStack>> deltas;\n\n    public GridFluidDeltaMessage(List<GridStackDelta<FluidGridStack>> deltas) {\n        this.deltas = deltas;\n    }\n\n    public static GridFluidDeltaMessage decode(FriendlyByteBuf buf) {\n        final int size = buf.readInt();\n        final List<GridStackDelta<FluidGridStack>> deltas = new LinkedList<>();\n        for (int i = 0; i < size; ++i) {\n            deltas.add(StackUtils.readFluidGridStackDelta(buf));\n        }\n        return new GridFluidDeltaMessage(deltas);\n    }\n\n    public static void handle(GridFluidDeltaMessage message, PlayPayloadContext ctx) {\n        BaseScreen.executeLater(GridScreen.class, grid -> {\n            message.deltas.forEach(p -> grid.getView().postChange(p.stack(), p.change()));\n        });\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeInt(deltas.size());\n        deltas.forEach(delta -> StackUtils.writeFluidGridStackDelta(buf, delta));\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/GridFluidInsertHeldMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class GridFluidInsertHeldMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"grid_fluid_insert_held\");\n\n    public static void handle(GridFluidInsertHeldMessage msg, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            AbstractContainerMenu container = player.containerMenu;\n\n            if (container instanceof GridContainerMenu) {\n                IGrid grid = ((GridContainerMenu) container).getGrid();\n\n                if (grid.getFluidHandler() != null) {\n                    grid.getFluidHandler().onInsertHeldContainer((ServerPlayer) player);\n                }\n            }\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        // no op\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/GridFluidPullMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\n\nimport java.util.UUID;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class GridFluidPullMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"grid_fluid_pull\");\n\n    private final UUID id;\n    private final boolean shift;\n\n    public GridFluidPullMessage(UUID id, boolean shift) {\n        this.id = id;\n        this.shift = shift;\n    }\n\n    public static GridFluidPullMessage decode(FriendlyByteBuf buf) {\n        return new GridFluidPullMessage(buf.readUUID(), buf.readBoolean());\n    }\n\n    public static void handle(GridFluidPullMessage message, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            AbstractContainerMenu container = player.containerMenu;\n\n            if (container instanceof GridContainerMenu) {\n                IGrid grid = ((GridContainerMenu) container).getGrid();\n\n                if (grid.getFluidHandler() != null) {\n                    grid.getFluidHandler().onExtract((ServerPlayer) player, message.id, message.shift);\n                }\n            }\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeUUID(id);\n        buf.writeBoolean(shift);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/GridFluidUpdateMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.api.util.StackListEntry;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.screen.grid.GridScreen;\nimport com.refinedmods.refinedstorage.screen.grid.stack.FluidGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.view.GridViewImpl;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class GridFluidUpdateMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"grid_fluid_update\");\n\n    private final boolean canCraft;\n    private final List<FluidGridStack> stacks;\n\n    public GridFluidUpdateMessage(final boolean canCraft, final List<FluidGridStack> stacks) {\n        this.canCraft = canCraft;\n        this.stacks = stacks;\n    }\n\n    public static GridFluidUpdateMessage decode(FriendlyByteBuf buf) {\n        final boolean canCraft = buf.readBoolean();\n        final int size = buf.readInt();\n        final List<FluidGridStack> stacks = new ArrayList<>();\n        for (int i = 0; i < size; ++i) {\n            stacks.add(StackUtils.readFluidGridStack(buf));\n        }\n        return new GridFluidUpdateMessage(canCraft, stacks);\n    }\n\n    public static void handle(GridFluidUpdateMessage message, PlayPayloadContext ctx) {\n        BaseScreen.executeLater(GridScreen.class, grid -> {\n            grid.setView(new GridViewImpl(grid, GridScreen.getDefaultSorter(), GridScreen.getSorters()));\n            grid.getView().setCanCraft(message.canCraft);\n            grid.getView().setStacks(message.stacks);\n            grid.getView().forceSort();\n        });\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeBoolean(canCraft);\n        buf.writeInt(stacks.size());\n        stacks.forEach(stack -> StackUtils.writeFluidGridStack(buf, stack));\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/GridItemDeltaMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.screen.grid.GridScreen;\nimport com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack;\nimport com.refinedmods.refinedstorage.util.StackUtils;\n\nimport java.util.LinkedList;\nimport java.util.List;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class GridItemDeltaMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"grid_item_delta\");\n\n    private final List<GridStackDelta<ItemGridStack>> deltas;\n\n    public GridItemDeltaMessage(List<GridStackDelta<ItemGridStack>> deltas) {\n        this.deltas = deltas;\n    }\n\n    public static GridItemDeltaMessage decode(FriendlyByteBuf buf) {\n        final int size = buf.readInt();\n        final List<GridStackDelta<ItemGridStack>> deltas = new LinkedList<>();\n        for (int i = 0; i < size; ++i) {\n            deltas.add(StackUtils.readItemGridStackDelta(buf));\n        }\n        return new GridItemDeltaMessage(deltas);\n    }\n\n    public static void handle(GridItemDeltaMessage message, PlayPayloadContext ctx) {\n        BaseScreen.executeLater(GridScreen.class, grid -> {\n            message.deltas.forEach(p -> grid.getView().postChange(p.stack(), p.change()));\n        });\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeInt(deltas.size());\n        deltas.forEach(delta -> StackUtils.writeItemGridStackDelta(buf, delta));\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/GridItemGridScrollMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\nimport javax.annotation.Nullable;\nimport java.util.UUID;\n\npublic class GridItemGridScrollMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"grid_item_grid_scroll\");\n\n    private final UUID id;\n    private final boolean shift;\n    private final boolean up;\n\n    public GridItemGridScrollMessage(@Nullable UUID id, boolean shift, boolean up) {\n        this.id = id;\n        this.shift = shift;\n        this.up = up;\n    }\n\n    public static GridItemGridScrollMessage decode(FriendlyByteBuf buf) {\n        return new GridItemGridScrollMessage(buf.readBoolean() ? buf.readUUID() : null, buf.readBoolean(), buf.readBoolean());\n    }\n\n    public static void handle(GridItemGridScrollMessage message, PlayPayloadContext ctx) {\n       ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            if (player.containerMenu instanceof GridContainerMenu && ((GridContainerMenu) player.containerMenu).getGrid().getItemHandler() != null) {\n                ((GridContainerMenu) player.containerMenu).getGrid().getItemHandler().onGridScroll((ServerPlayer) player, message.id, message.shift, message.up);\n            }\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        boolean hasId = id != null;\n        buf.writeBoolean(hasId);\n        if (hasId) {\n            buf.writeUUID(id);\n        }\n\n        buf.writeBoolean(shift);\n        buf.writeBoolean(up);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/GridItemInsertHeldMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class GridItemInsertHeldMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"grid_item_insert_held\");\n\n    private final boolean single;\n\n    public GridItemInsertHeldMessage(boolean single) {\n        this.single = single;\n    }\n\n    public static GridItemInsertHeldMessage decode(FriendlyByteBuf buf) {\n        return new GridItemInsertHeldMessage(buf.readBoolean());\n    }\n\n    public static void handle(GridItemInsertHeldMessage message, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            AbstractContainerMenu container = player.containerMenu;\n\n            if (container instanceof GridContainerMenu) {\n                IGrid grid = ((GridContainerMenu) container).getGrid();\n\n                if (grid.getItemHandler() != null) {\n                    grid.getItemHandler().onInsertHeldItem((ServerPlayer) player, message.single);\n                }\n            }\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeBoolean(single);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/GridItemInventoryScrollMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class GridItemInventoryScrollMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"grid_item_inventory_scroll\");\n\n    private final int slot;\n    private final boolean shift;\n    private final boolean up;\n\n    public GridItemInventoryScrollMessage(int slot, boolean shift, boolean up) {\n        this.slot = slot;\n        this.shift = shift;\n        this.up = up;\n    }\n\n    public static GridItemInventoryScrollMessage decode(FriendlyByteBuf buf) {\n        return new GridItemInventoryScrollMessage(buf.readInt(), buf.readBoolean(), buf.readBoolean());\n    }\n\n    public static void handle(GridItemInventoryScrollMessage message, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            if (player.containerMenu instanceof GridContainerMenu && ((GridContainerMenu) player.containerMenu).getGrid().getItemHandler() != null) {\n                ((GridContainerMenu) player.containerMenu).getGrid().getItemHandler().onInventoryScroll((ServerPlayer) player, message.slot, message.shift, message.up);\n            }\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeInt(slot);\n        buf.writeBoolean(shift);\n        buf.writeBoolean(up);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/GridItemPullMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\nimport java.util.UUID;\n\npublic class GridItemPullMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"grid_item_pull\");\n\n    private final UUID id;\n    private final int flags;\n\n    public GridItemPullMessage(UUID id, int flags) {\n        this.id = id;\n        this.flags = flags;\n    }\n\n    public static GridItemPullMessage decode(FriendlyByteBuf buf) {\n        return new GridItemPullMessage(buf.readUUID(), buf.readInt());\n    }\n\n    public static void handle(GridItemPullMessage message, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            AbstractContainerMenu container = player.containerMenu;\n\n            if (container instanceof GridContainerMenu) {\n                IGrid grid = ((GridContainerMenu) container).getGrid();\n\n                if (grid.getItemHandler() != null) {\n                    grid.getItemHandler().onExtract((ServerPlayer) player, message.id, -1, message.flags);\n                }\n            }\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeUUID(id);\n        buf.writeInt(flags);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/GridItemUpdateMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.api.util.StackListEntry;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.screen.grid.GridScreen;\nimport com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.view.GridViewImpl;\nimport com.refinedmods.refinedstorage.util.StackUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class GridItemUpdateMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"grid_item_update\");\n\n    private final boolean canCraft;\n    private final List<ItemGridStack> stacks;\n\n    public GridItemUpdateMessage(boolean canCraft, List<ItemGridStack> stacks) {\n        this.canCraft = canCraft;\n        this.stacks = stacks;\n    }\n\n    public static GridItemUpdateMessage decode(FriendlyByteBuf buf) {\n        final boolean canCraft = buf.readBoolean();\n        final int size = buf.readInt();\n        final List<ItemGridStack> stacks = new ArrayList<>();\n        for (int i = 0; i < size; ++i) {\n            stacks.add(StackUtils.readItemGridStack(buf));\n        }\n        return new GridItemUpdateMessage(canCraft, stacks);\n    }\n\n    public static void handle(GridItemUpdateMessage message, PlayPayloadContext ctx) {\n        BaseScreen.executeLater(GridScreen.class, grid -> {\n            grid.setView(new GridViewImpl(grid, GridScreen.getDefaultSorter(), GridScreen.getSorters()));\n            grid.getView().setCanCraft(message.canCraft);\n            grid.getView().setStacks(message.stacks);\n            grid.getView().forceSort();\n        });\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeBoolean(canCraft);\n        buf.writeInt(stacks.size());\n        stacks.forEach(stack -> StackUtils.writeItemGridStack(buf, stack));\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/GridPatternCreateMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.GridType;\nimport com.refinedmods.refinedstorage.blockentity.grid.GridBlockEntity;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class GridPatternCreateMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"grid_pattern_create\");\n\n    private final BlockPos pos;\n\n    public GridPatternCreateMessage(BlockPos pos) {\n        this.pos = pos;\n    }\n\n    public static GridPatternCreateMessage decode(FriendlyByteBuf buf) {\n        return new GridPatternCreateMessage(buf.readBlockPos());\n    }\n\n    public static void handle(GridPatternCreateMessage message, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            BlockEntity blockEntity = player.getCommandSenderWorld().getBlockEntity(message.pos);\n\n            if (blockEntity instanceof GridBlockEntity &&\n                ((GridBlockEntity) blockEntity).getNode().getGridType() == GridType.PATTERN) {\n                ((GridBlockEntity) blockEntity).getNode().onCreatePattern();\n            }\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeBlockPos(pos);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/GridProcessingTransferMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.GridType;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport com.refinedmods.refinedstorage.inventory.fluid.FluidInventory;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.List;\n\npublic class GridProcessingTransferMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"grid_processing_transfer\");\n\n    private final Collection<ItemStack> inputs;\n    private final Collection<ItemStack> outputs;\n    private final Collection<FluidStack> fluidInputs;\n    private final Collection<FluidStack> fluidOutputs;\n\n    public GridProcessingTransferMessage(Collection<ItemStack> inputs, Collection<ItemStack> outputs, Collection<FluidStack> fluidInputs, Collection<FluidStack> fluidOutputs) {\n        this.inputs = inputs;\n        this.outputs = outputs;\n        this.fluidInputs = fluidInputs;\n        this.fluidOutputs = fluidOutputs;\n    }\n\n    public static GridProcessingTransferMessage decode(FriendlyByteBuf buf) {\n        int size = buf.readInt();\n\n        List<ItemStack> inputs = new ArrayList<>(size);\n\n        for (int i = 0; i < size; i++) {\n            inputs.add(StackUtils.readItemStack(buf));\n        }\n\n        size = buf.readInt();\n\n        List<ItemStack> outputs = new ArrayList<>(size);\n\n        for (int i = 0; i < size; i++) {\n            outputs.add(StackUtils.readItemStack(buf));\n        }\n\n        size = buf.readInt();\n\n        List<FluidStack> fluidInputs = new ArrayList<>(size);\n\n        for (int i = 0; i < size; i++) {\n            fluidInputs.add(FluidStack.readFromPacket(buf));\n        }\n\n        size = buf.readInt();\n\n        List<FluidStack> fluidOutputs = new ArrayList<>(size);\n\n        for (int i = 0; i < size; i++) {\n            fluidOutputs.add(FluidStack.readFromPacket(buf));\n        }\n\n        return new GridProcessingTransferMessage(inputs, outputs, fluidInputs, fluidOutputs);\n    }\n\n    public static void handle(GridProcessingTransferMessage message, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            if (player.containerMenu instanceof GridContainerMenu) {\n                IGrid grid = ((GridContainerMenu) player.containerMenu).getGrid();\n\n                if (grid.getGridType() == GridType.PATTERN) {\n                    BaseItemHandler handler = ((GridNetworkNode) grid).getProcessingMatrix();\n                    FluidInventory handlerFluid = ((GridNetworkNode) grid).getProcessingMatrixFluids();\n\n                    clearInputsAndOutputs(handler);\n                    clearInputsAndOutputs(handlerFluid);\n\n                    setInputs(handler, message.inputs, handlerFluid, message.fluidInputs);\n                    setOutputs(handler, message.outputs, handlerFluid, message.fluidOutputs);\n\n\n                    ((GridNetworkNode) grid).setProcessingPattern(true);\n                    ((GridNetworkNode) grid).markDirty();\n                }\n            }\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeInt(inputs.size());\n\n        for (ItemStack stack : inputs) {\n            StackUtils.writeItemStack(buf, stack);\n        }\n\n        buf.writeInt(outputs.size());\n\n        for (ItemStack stack : outputs) {\n            StackUtils.writeItemStack(buf, stack);\n        }\n\n        buf.writeInt(fluidInputs.size());\n\n        for (FluidStack stack : fluidInputs) {\n            stack.writeToPacket(buf);\n        }\n\n        buf.writeInt(fluidOutputs.size());\n\n        for (FluidStack stack : fluidOutputs) {\n            stack.writeToPacket(buf);\n        }\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n\n    private static void clearInputsAndOutputs(BaseItemHandler handler) {\n        for (int i = 0; i < handler.getSlots(); ++i) {\n            handler.setStackInSlot(i, ItemStack.EMPTY);\n        }\n    }\n\n    private static void clearInputsAndOutputs(FluidInventory handler) {\n        for (int i = 0; i < handler.getSlots(); ++i) {\n            handler.setFluid(i, FluidStack.EMPTY);\n        }\n    }\n\n    private static void setInputs(BaseItemHandler handler, Collection<ItemStack> stacks, FluidInventory fluidHandler, Collection<FluidStack> fluidStacks) {\n        setSlots(handler, stacks, fluidHandler, fluidStacks, 0, handler.getSlots() / 2);\n    }\n\n    private static void setOutputs(BaseItemHandler handler, Collection<ItemStack> stacks, FluidInventory fluidHandler, Collection<FluidStack> fluidStacks) {\n        setSlots(handler, stacks, fluidHandler, fluidStacks, handler.getSlots() / 2, handler.getSlots());\n    }\n\n    private static void setSlots(BaseItemHandler handler, Collection<ItemStack> stacks, FluidInventory fluidHandler, Collection<FluidStack> fluidStacks, int begin, int end) {\n        for (ItemStack stack : stacks) {\n            handler.setStackInSlot(begin, stack);\n\n            begin++;\n\n            if (begin >= end) {\n                break;\n            }\n        }\n        for (FluidStack stack : fluidStacks) {\n\n            fluidHandler.setFluid(begin, stack.copy());\n\n            begin++;\n\n            if (begin >= end) {\n                break;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/GridStackDelta.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\n\npublic record GridStackDelta<T extends IGridStack>(int change, T stack) {\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/GridTransferMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.GridType;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\nimport java.util.List;\n\npublic class GridTransferMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"grid_transfer\");\n\n    private final ItemStack[][] recipe;\n\n    public GridTransferMessage(final ItemStack[][] recipe) {\n        this.recipe = recipe;\n    }\n\n    public static GridTransferMessage decode(FriendlyByteBuf buf) {\n        int slots = buf.readInt();\n        final ItemStack[][] recipe = new ItemStack[slots][];\n        for (int i = 0; i < slots; i++) {\n            int numberOfIngredients = buf.readInt();\n            recipe[i] = new ItemStack[numberOfIngredients];\n            for (int j = 0; j < numberOfIngredients; j++) {\n                recipe[i][j] = StackUtils.readItemStack(buf);\n            }\n        }\n        return new GridTransferMessage(recipe);\n    }\n\n    public static void handle(GridTransferMessage message, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            if (player.containerMenu instanceof GridContainerMenu) {\n                IGrid grid = ((GridContainerMenu) player.containerMenu).getGrid();\n\n                if (grid.getGridType() == GridType.CRAFTING || grid.getGridType() == GridType.PATTERN) {\n                    grid.onRecipeTransfer(player, message.recipe);\n                }\n            }\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeInt(recipe.length);\n        for (ItemStack[] stacks : recipe) {\n            buf.writeInt(stacks.length);\n            for (ItemStack possibleStack : stacks) {\n                StackUtils.writeItemStack(buf, possibleStack);\n            }\n        }\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/PortableGridSettingsUpdateMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport com.refinedmods.refinedstorage.blockentity.grid.portable.PortableGrid;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class PortableGridSettingsUpdateMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"portable_grid_settings_update\");\n\n    private final int viewType;\n    private final int sortingDirection;\n    private final int sortingType;\n    private final int searchBoxMode;\n    private final int size;\n    private final int tabSelected;\n    private final int tabPage;\n\n    public PortableGridSettingsUpdateMessage(int viewType, int sortingDirection, int sortingType, int searchBoxMode, int size, int tabSelected, int tabPage) {\n        this.viewType = viewType;\n        this.sortingDirection = sortingDirection;\n        this.sortingType = sortingType;\n        this.searchBoxMode = searchBoxMode;\n        this.size = size;\n        this.tabSelected = tabSelected;\n        this.tabPage = tabPage;\n    }\n\n    public static PortableGridSettingsUpdateMessage decode(FriendlyByteBuf buf) {\n        return new PortableGridSettingsUpdateMessage(\n            buf.readInt(),\n            buf.readInt(),\n            buf.readInt(),\n            buf.readInt(),\n            buf.readInt(),\n            buf.readInt(),\n            buf.readInt()\n        );\n    }\n\n    public static void handle(PortableGridSettingsUpdateMessage message, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            if (player.containerMenu instanceof GridContainerMenu) {\n                IGrid grid = ((GridContainerMenu) player.containerMenu).getGrid();\n\n                if (grid instanceof PortableGrid) {\n                    ItemStack stack = ((PortableGrid) grid).getStack();\n\n                    if (!stack.hasTag()) {\n                        stack.setTag(new CompoundTag());\n                    }\n\n                    if (IGrid.isValidViewType(message.viewType)) {\n                        stack.getTag().putInt(GridNetworkNode.NBT_VIEW_TYPE, message.viewType);\n                    }\n\n                    if (IGrid.isValidSortingDirection(message.sortingDirection)) {\n                        stack.getTag().putInt(GridNetworkNode.NBT_SORTING_DIRECTION, message.sortingDirection);\n                    }\n\n                    if (IGrid.isValidSortingType(message.sortingType)) {\n                        stack.getTag().putInt(GridNetworkNode.NBT_SORTING_TYPE, message.sortingType);\n                    }\n\n                    if (IGrid.isValidSearchBoxMode(message.searchBoxMode)) {\n                        stack.getTag().putInt(GridNetworkNode.NBT_SEARCH_BOX_MODE, message.searchBoxMode);\n                    }\n\n                    if (IGrid.isValidSize(message.size)) {\n                        stack.getTag().putInt(GridNetworkNode.NBT_SIZE, message.size);\n                    }\n\n                    stack.getTag().putInt(GridNetworkNode.NBT_TAB_SELECTED, message.tabSelected);\n                    stack.getTag().putInt(GridNetworkNode.NBT_TAB_PAGE, message.tabPage);\n                }\n            }\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeInt(viewType);\n        buf.writeInt(sortingDirection);\n        buf.writeInt(sortingType);\n        buf.writeInt(searchBoxMode);\n        buf.writeInt(size);\n        buf.writeInt(tabSelected);\n        buf.writeInt(tabPage);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/WirelessFluidGridSettingsUpdateMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport com.refinedmods.refinedstorage.blockentity.grid.WirelessFluidGrid;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class WirelessFluidGridSettingsUpdateMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"wireless_fluid_grid_settings_update\");\n\n    private final int sortingDirection;\n    private final int sortingType;\n    private final int searchBoxMode;\n    private final int size;\n    private final int tabSelected;\n    private final int tabPage;\n\n    public WirelessFluidGridSettingsUpdateMessage(int sortingDirection, int sortingType, int searchBoxMode, int size, int tabSelected, int tabPage) {\n        this.sortingDirection = sortingDirection;\n        this.sortingType = sortingType;\n        this.searchBoxMode = searchBoxMode;\n        this.size = size;\n        this.tabSelected = tabSelected;\n        this.tabPage = tabPage;\n    }\n\n    public static WirelessFluidGridSettingsUpdateMessage decode(FriendlyByteBuf buf) {\n        return new WirelessFluidGridSettingsUpdateMessage(\n            buf.readInt(),\n            buf.readInt(),\n            buf.readInt(),\n            buf.readInt(),\n            buf.readInt(),\n            buf.readInt()\n        );\n    }\n\n    public static void handle(WirelessFluidGridSettingsUpdateMessage message, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            if (player.containerMenu instanceof GridContainerMenu) {\n                IGrid grid = ((GridContainerMenu) player.containerMenu).getGrid();\n\n                if (grid instanceof WirelessFluidGrid) {\n                    ItemStack stack = ((WirelessFluidGrid) grid).getStack();\n\n                    if (IGrid.isValidSortingDirection(message.sortingDirection)) {\n                        stack.getTag().putInt(GridNetworkNode.NBT_SORTING_DIRECTION, message.sortingDirection);\n                    }\n\n                    if (IGrid.isValidSortingType(message.sortingType)) {\n                        stack.getTag().putInt(GridNetworkNode.NBT_SORTING_TYPE, message.sortingType);\n                    }\n\n                    if (IGrid.isValidSearchBoxMode(message.searchBoxMode)) {\n                        stack.getTag().putInt(GridNetworkNode.NBT_SEARCH_BOX_MODE, message.searchBoxMode);\n                    }\n\n                    if (IGrid.isValidSize(message.size)) {\n                        stack.getTag().putInt(GridNetworkNode.NBT_SIZE, message.size);\n                    }\n\n                    stack.getTag().putInt(GridNetworkNode.NBT_TAB_SELECTED, message.tabSelected);\n                    stack.getTag().putInt(GridNetworkNode.NBT_TAB_PAGE, message.tabPage);\n                }\n            }\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeInt(sortingDirection);\n        buf.writeInt(sortingType);\n        buf.writeInt(searchBoxMode);\n        buf.writeInt(size);\n        buf.writeInt(tabSelected);\n        buf.writeInt(tabPage);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/grid/WirelessGridSettingsUpdateMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport com.refinedmods.refinedstorage.blockentity.grid.WirelessGrid;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class WirelessGridSettingsUpdateMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"wireless_grid_settings_update\");\n\n    private final int viewType;\n    private final int sortingDirection;\n    private final int sortingType;\n    private final int searchBoxMode;\n    private final int size;\n    private final int tabSelected;\n    private final int tabPage;\n\n    public WirelessGridSettingsUpdateMessage(int viewType, int sortingDirection, int sortingType, int searchBoxMode, int size, int tabSelected, int tabPage) {\n        this.viewType = viewType;\n        this.sortingDirection = sortingDirection;\n        this.sortingType = sortingType;\n        this.searchBoxMode = searchBoxMode;\n        this.size = size;\n        this.tabSelected = tabSelected;\n        this.tabPage = tabPage;\n    }\n\n    public static WirelessGridSettingsUpdateMessage decode(FriendlyByteBuf buf) {\n        return new WirelessGridSettingsUpdateMessage(\n            buf.readInt(),\n            buf.readInt(),\n            buf.readInt(),\n            buf.readInt(),\n            buf.readInt(),\n            buf.readInt(),\n            buf.readInt()\n        );\n    }\n\n    public static void handle(WirelessGridSettingsUpdateMessage message, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            if (player.containerMenu instanceof GridContainerMenu) {\n                IGrid grid = ((GridContainerMenu) player.containerMenu).getGrid();\n\n                if (grid instanceof WirelessGrid) {\n                    ItemStack stack = ((WirelessGrid) grid).getStack();\n\n                    if (!stack.hasTag()) {\n                        stack.setTag(new CompoundTag());\n                    }\n\n                    if (IGrid.isValidViewType(message.viewType)) {\n                        stack.getTag().putInt(GridNetworkNode.NBT_VIEW_TYPE, message.viewType);\n                    }\n\n                    if (IGrid.isValidSortingDirection(message.sortingDirection)) {\n                        stack.getTag().putInt(GridNetworkNode.NBT_SORTING_DIRECTION, message.sortingDirection);\n                    }\n\n                    if (IGrid.isValidSortingType(message.sortingType)) {\n                        stack.getTag().putInt(GridNetworkNode.NBT_SORTING_TYPE, message.sortingType);\n                    }\n\n                    if (IGrid.isValidSearchBoxMode(message.searchBoxMode)) {\n                        stack.getTag().putInt(GridNetworkNode.NBT_SEARCH_BOX_MODE, message.searchBoxMode);\n                    }\n\n                    if (IGrid.isValidSize(message.size)) {\n                        stack.getTag().putInt(GridNetworkNode.NBT_SIZE, message.size);\n                    }\n\n                    stack.getTag().putInt(GridNetworkNode.NBT_TAB_SELECTED, message.tabSelected);\n                    stack.getTag().putInt(GridNetworkNode.NBT_TAB_PAGE, message.tabPage);\n                }\n            }\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeInt(viewType);\n        buf.writeInt(sortingDirection);\n        buf.writeInt(sortingType);\n        buf.writeInt(searchBoxMode);\n        buf.writeInt(size);\n        buf.writeInt(tabSelected);\n        buf.writeInt(tabPage);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/sync/BlockEntitySynchronizationParameterMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.sync;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class BlockEntitySynchronizationParameterMessage<T> implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"sync_param\");\n\n    private final BlockEntitySynchronizationParameter<T, ?> parameter;\n    private final T value;\n    private final boolean initial;\n\n    public BlockEntitySynchronizationParameterMessage(BlockEntitySynchronizationParameter parameter,\n                                                      T value,\n                                                      boolean initial) {\n        this.parameter = parameter;\n        this.value = value;\n        this.initial = initial;\n    }\n\n    public static BlockEntitySynchronizationParameterMessage decode(FriendlyByteBuf buf) {\n        ResourceLocation id = buf.readResourceLocation();\n        boolean initial = buf.readBoolean();\n        BlockEntitySynchronizationParameter parameter = BlockEntitySynchronizationManager.getParameter(id);\n        return new BlockEntitySynchronizationParameterMessage(parameter, parameter.getSerializer().read(buf), initial);\n    }\n\n    public static <T> void handle(BlockEntitySynchronizationParameterMessage<T> msg, PlayPayloadContext ctx) {\n        msg.parameter.setValue(msg.initial, msg.value);\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeResourceLocation(parameter.getId());\n        buf.writeBoolean(initial);\n        parameter.getSerializer().write(buf, value);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/network/sync/BlockEntitySynchronizationParameterUpdateMessage.java",
    "content": "package com.refinedmods.refinedstorage.network.sync;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.container.BaseContainerMenu;\n\nimport java.util.function.BiConsumer;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.network.protocol.common.custom.CustomPacketPayload;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.neoforge.network.handling.PlayPayloadContext;\n\npublic class BlockEntitySynchronizationParameterUpdateMessage implements CustomPacketPayload {\n    public static final ResourceLocation ID = new ResourceLocation(RS.ID, \"sync_param_update\");\n\n    private final BlockEntitySynchronizationParameter parameter;\n    private final Object value;\n\n    public BlockEntitySynchronizationParameterUpdateMessage(BlockEntitySynchronizationParameter parameter, Object value) {\n        this.parameter = parameter;\n        this.value = value;\n    }\n\n    public static BlockEntitySynchronizationParameterUpdateMessage decode(FriendlyByteBuf buf) {\n        ResourceLocation id = buf.readResourceLocation();\n\n        BlockEntitySynchronizationParameter parameter = BlockEntitySynchronizationManager.getParameter(id);\n        Object value = null;\n\n        if (parameter != null) {\n            try {\n                value = parameter.getSerializer().read(buf);\n            } catch (Exception e) {\n                // NO OP\n            }\n        }\n\n        return new BlockEntitySynchronizationParameterUpdateMessage(parameter, value);\n    }\n\n    public static void handle(BlockEntitySynchronizationParameterUpdateMessage message, PlayPayloadContext ctx) {\n        ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> {\n            if (player.containerMenu instanceof BaseContainerMenu baseContainerMenu) {\n                BiConsumer consumer = message.parameter.getValueConsumer();\n\n                if (consumer != null) {\n                    consumer.accept(baseContainerMenu.getBlockEntity(), message.value);\n                }\n            }\n        }));\n    }\n\n    @Override\n    public void write(FriendlyByteBuf buf) {\n        buf.writeResourceLocation(parameter.getId());\n\n        parameter.getSerializer().write(buf, value);\n    }\n\n    @Override\n    public ResourceLocation id() {\n        return ID;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/recipe/CoverRecipe.java",
    "content": "package com.refinedmods.refinedstorage.recipe;\n\n\nimport com.google.common.collect.Lists;\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;\nimport com.refinedmods.refinedstorage.item.CoverItem;\nimport net.minecraft.core.RegistryAccess;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.inventory.CraftingContainer;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.crafting.CraftingBookCategory;\nimport net.minecraft.world.item.crafting.CustomRecipe;\nimport net.minecraft.world.item.crafting.RecipeSerializer;\nimport net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer;\nimport net.minecraft.world.level.Level;\nimport net.neoforged.neoforge.common.Tags;\nimport java.util.List;\n\npublic class CoverRecipe extends CustomRecipe {\n    public static RecipeSerializer<CoverRecipe> SERIALIZER = new SimpleCraftingRecipeSerializer<>(CoverRecipe::new);\n\n    public CoverRecipe(CraftingBookCategory category) {\n        super(category);\n    }\n\n    public static boolean stackMatches(ItemStack first) {\n        return CoverManager.isValidCover(first);\n    }\n\n    public static boolean matches(List<ItemStack> list) {\n        return list.size() == 2;\n    }\n\n    public static ItemStack getResult(List<ItemStack> list) {\n        if (list.size() == 2) {\n            ItemStack first = list.get(0);\n            ItemStack second = list.get(1);\n            return getResult(first, second);\n        }\n        return ItemStack.EMPTY;\n    }\n\n    public static ItemStack getResult(ItemStack first, ItemStack second) {\n        if (first.is(Tags.Items.NUGGETS_IRON)) {\n            ItemStack stack = new ItemStack(RSItems.COVER.get());\n            CoverItem.setItem(stack, second);\n            stack.setCount(6);\n            return stack;\n        }\n        if (second.is(Tags.Items.NUGGETS_IRON)) {\n            ItemStack stack = new ItemStack(RSItems.COVER.get());\n            CoverItem.setItem(stack, first);\n            stack.setCount(6);\n            return stack;\n        }\n        return ItemStack.EMPTY;\n    }\n\n    @Override\n    public boolean matches(CraftingContainer craftingContainer, Level level) {\n        List<ItemStack> list = Lists.newArrayList();\n        int ingots = 0;\n        for (int i = 0; i < craftingContainer.getContainerSize(); ++i) {\n            ItemStack itemstack = craftingContainer.getItem(i);\n            if (!itemstack.isEmpty()) {\n                list.add(itemstack);\n                if (itemstack.is(Tags.Items.NUGGETS_IRON)) {\n                    ++ingots;\n                } else if (!stackMatches(itemstack)) {\n                    return false;\n                }\n            }\n        }\n        return matches(list) && ingots == 1;\n    }\n\n    @Override\n    public ItemStack assemble(CraftingContainer inv, RegistryAccess registryAccess) {\n        List<ItemStack> list = Lists.newArrayList();\n        int ingots = 0;\n        for (int i = 0; i < inv.getContainerSize(); ++i) {\n            ItemStack itemstack = inv.getItem(i);\n            if (!itemstack.isEmpty()) {\n                list.add(itemstack);\n                if (itemstack.is(Tags.Items.NUGGETS_IRON)) {\n                    ++ingots;\n                } else if (!stackMatches(itemstack)) {\n                    return ItemStack.EMPTY;\n                }\n            }\n        }\n        if (ingots > 1) {\n            return ItemStack.EMPTY;\n        }\n        return getResult(list);\n    }\n\n    @Override\n    public boolean canCraftInDimensions(int width, int height) {\n        return width * height >= 2;\n    }\n\n    @Override\n    public RecipeSerializer<?> getSerializer() {\n        return SERIALIZER;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/recipe/HollowCoverRecipe.java",
    "content": "package com.refinedmods.refinedstorage.recipe;\n\n\nimport com.google.common.collect.Lists;\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.item.CoverItem;\nimport net.minecraft.core.RegistryAccess;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.inventory.CraftingContainer;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.crafting.CraftingBookCategory;\nimport net.minecraft.world.item.crafting.CustomRecipe;\nimport net.minecraft.world.item.crafting.RecipeSerializer;\nimport net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer;\nimport net.minecraft.world.level.Level;\n\nimport java.util.List;\n\npublic class HollowCoverRecipe extends CustomRecipe {\n    public static RecipeSerializer<HollowCoverRecipe> SERIALIZER = new SimpleCraftingRecipeSerializer<>(HollowCoverRecipe::new);\n\n    public HollowCoverRecipe(CraftingBookCategory category) {\n        super(category);\n    }\n\n    public static boolean stackMatches(ItemStack first) {\n        return first.getItem() == RSItems.COVER.get();\n    }\n\n    public static boolean matches(List<ItemStack> list) {\n        return list.size() == 1;\n    }\n\n    public static ItemStack getResult(List<ItemStack> list) {\n        if (list.size() == 1) {\n            ItemStack first = list.get(0);\n            return getResult(first);\n        }\n        return ItemStack.EMPTY;\n    }\n\n    public static ItemStack getResult(ItemStack first) {\n        ItemStack stack = CoverItem.getItem(first);\n        ItemStack result = new ItemStack(RSItems.HOLLOW_COVER.get());\n        CoverItem.setItem(result, stack);\n        return result;\n    }\n\n    @Override\n    public boolean matches(CraftingContainer craftingContainer, Level level) {\n        List<ItemStack> list = Lists.newArrayList();\n        for (int i = 0; i < craftingContainer.getContainerSize(); ++i) {\n            ItemStack itemstack = craftingContainer.getItem(i);\n            if (!itemstack.isEmpty()) {\n                list.add(itemstack);\n                if (!stackMatches(itemstack)) {\n                    return false;\n                }\n            }\n        }\n        return matches(list);\n    }\n\n    @Override\n    public ItemStack assemble(CraftingContainer inv, RegistryAccess registryAccess) {\n        List<ItemStack> list = Lists.newArrayList();\n        for (int i = 0; i < inv.getContainerSize(); ++i) {\n            ItemStack itemstack = inv.getItem(i);\n            if (!itemstack.isEmpty()) {\n                list.add(itemstack);\n                if (!stackMatches(itemstack)) {\n                    return ItemStack.EMPTY;\n                }\n            }\n        }\n        return getResult(list);\n    }\n\n    @Override\n    public boolean canCraftInDimensions(int width, int height) {\n        return width * height >= 2;\n    }\n\n    @Override\n    public RecipeSerializer<?> getSerializer() {\n        return SERIALIZER;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/recipe/UpgradeWithEnchantedBookRecipe.java",
    "content": "package com.refinedmods.refinedstorage.recipe;\n\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.item.UpgradeItem;\n\nimport java.util.Objects;\nimport java.util.Optional;\nimport javax.annotation.Nullable;\n\nimport com.mojang.serialization.Codec;\nimport com.mojang.serialization.codecs.RecordCodecBuilder;\nimport net.minecraft.core.Holder;\nimport net.minecraft.core.NonNullList;\nimport net.minecraft.core.registries.Registries;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.resources.RegistryFixedCodec;\nimport net.minecraft.resources.ResourceKey;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.inventory.CraftingContainer;\nimport net.minecraft.world.item.EnchantedBookItem;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.crafting.CraftingBookCategory;\nimport net.minecraft.world.item.crafting.Ingredient;\nimport net.minecraft.world.item.crafting.ShapedRecipe;\nimport net.minecraft.world.item.crafting.ShapedRecipePattern;\nimport net.minecraft.world.item.enchantment.Enchantment;\nimport net.minecraft.world.item.enchantment.EnchantmentHelper;\nimport net.minecraft.world.item.enchantment.EnchantmentInstance;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.Blocks;\n\npublic class UpgradeWithEnchantedBookRecipe extends ShapedRecipe {\n    public static final Codec<UpgradeWithEnchantedBookRecipe> CODEC = RecordCodecBuilder.create(\n        instance -> instance.group(\n            RegistryFixedCodec.create(Registries.ENCHANTMENT).fieldOf(\"enchantment\")\n                .forGetter(UpgradeWithEnchantedBookRecipe::getEnchantment),\n            Codec.INT.fieldOf(\"level\").orElse(1)\n                .forGetter(UpgradeWithEnchantedBookRecipe::getEnchantmentLevel),\n            RegistryFixedCodec.create(Registries.ITEM).fieldOf(\"result\")\n                .forGetter(UpgradeWithEnchantedBookRecipe::getResultItem)\n        ).apply(instance, UpgradeWithEnchantedBookRecipe::new)\n    );\n\n    private final Holder<Enchantment> enchantment;\n    private final int level;\n    private final Holder<Item> resultItem;\n\n    UpgradeWithEnchantedBookRecipe(final Holder<Enchantment> enchantment,\n                                   final int level,\n                                   final Holder<Item> resultItem) {\n        super(\"\", CraftingBookCategory.MISC, new ShapedRecipePattern(3, 3, NonNullList.of(\n            Ingredient.EMPTY,\n            Ingredient.of(new ItemStack(RSItems.QUARTZ_ENRICHED_IRON.get())),\n            Ingredient.of(EnchantedBookItem.createForEnchantment(new EnchantmentInstance(enchantment.value(), level))),\n            Ingredient.of(new ItemStack(RSItems.QUARTZ_ENRICHED_IRON.get())),\n            Ingredient.of(new ItemStack(Blocks.BOOKSHELF)),\n            Ingredient.of(new ItemStack(RSItems.UPGRADE_ITEMS.get(UpgradeItem.Type.NORMAL).get())),\n            Ingredient.of(new ItemStack(Blocks.BOOKSHELF)),\n            Ingredient.of(new ItemStack(RSItems.QUARTZ_ENRICHED_IRON.get())),\n            Ingredient.of(new ItemStack(RSItems.QUARTZ_ENRICHED_IRON.get())),\n            Ingredient.of(new ItemStack(RSItems.QUARTZ_ENRICHED_IRON.get()))\n        ), Optional.empty()), new ItemStack(resultItem.value()));\n        this.enchantment = enchantment;\n        this.level = level;\n        this.resultItem = resultItem;\n    }\n\n    public Holder<Item> getResultItem() {\n        return resultItem;\n    }\n\n    public Holder<Enchantment> getEnchantment() {\n        return enchantment;\n    }\n\n    @Nullable\n    public ResourceLocation getEnchantmentId() {\n        return enchantment.unwrapKey().map(ResourceKey::location).orElse(null);\n    }\n\n    public int getEnchantmentLevel() {\n        return level;\n    }\n\n    @Override\n    public boolean matches(final CraftingContainer craftingContainer, final Level theLevel) {\n        if (!super.matches(craftingContainer, theLevel)) {\n            return false;\n        }\n        final ListTag enchantments = EnchantedBookItem.getEnchantments(craftingContainer.getItem(1));\n        for (int i = 0; i < enchantments.size(); ++i) {\n            final CompoundTag tag = enchantments.getCompound(i);\n            final int containerLevel = EnchantmentHelper.getEnchantmentLevel(tag);\n            final ResourceLocation containerEnchantment = EnchantmentHelper.getEnchantmentId(tag);\n            if (Objects.equals(containerEnchantment, getEnchantmentId()) && containerLevel == level) {\n                return true;\n            }\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/recipe/UpgradeWithEnchantedBookRecipeSerializer.java",
    "content": "package com.refinedmods.refinedstorage.recipe;\n\nimport java.util.Objects;\n\nimport com.mojang.serialization.Codec;\nimport net.minecraft.core.Holder;\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.core.registries.Registries;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.resources.ResourceKey;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.crafting.RecipeSerializer;\nimport net.minecraft.world.item.enchantment.Enchantment;\n\npublic class UpgradeWithEnchantedBookRecipeSerializer implements RecipeSerializer<UpgradeWithEnchantedBookRecipe> {\n    @Override\n    public Codec<UpgradeWithEnchantedBookRecipe> codec() {\n        return UpgradeWithEnchantedBookRecipe.CODEC;\n    }\n\n    @Override\n    public UpgradeWithEnchantedBookRecipe fromNetwork(final FriendlyByteBuf buf) {\n        final Holder<Item> result = BuiltInRegistries.ITEM.getHolder(ResourceKey.create(\n            Registries.ITEM,\n            buf.readResourceLocation()\n        )).orElseThrow();\n        final Holder<Enchantment> enchantment = BuiltInRegistries.ENCHANTMENT.getHolder(ResourceKey.create(\n            Registries.ENCHANTMENT,\n            buf.readResourceLocation()\n        )).orElseThrow();\n        final int level = buf.readInt();\n        return new UpgradeWithEnchantedBookRecipe(enchantment, level, result);\n    }\n\n    @Override\n    public void toNetwork(final FriendlyByteBuf buf, final UpgradeWithEnchantedBookRecipe recipe) {\n        buf.writeResourceLocation(recipe.getResultItem().unwrapKey().orElseThrow().location());\n        buf.writeResourceLocation(Objects.requireNonNull(recipe.getEnchantmentId()));\n        buf.writeInt(recipe.getEnchantmentLevel());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/BakedModelOverrideRegistry.java",
    "content": "package com.refinedmods.refinedstorage.render;\n\nimport net.minecraft.client.resources.model.BakedModel;\nimport net.minecraft.resources.ResourceLocation;\n\nimport javax.annotation.Nullable;\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class BakedModelOverrideRegistry {\n    private final Map<ResourceLocation, BakedModelOverrideFactory> registry = new HashMap<>();\n\n    public void add(ResourceLocation id, BakedModelOverrideFactory factory) {\n        registry.put(id, factory);\n    }\n\n    @Nullable\n    public BakedModelOverrideFactory get(ResourceLocation id) {\n        return registry.get(id);\n    }\n\n    public interface BakedModelOverrideFactory {\n        BakedModel create(BakedModel base, Map<ResourceLocation, BakedModel> registry);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/ConstantsCable.java",
    "content": "package com.refinedmods.refinedstorage.render;\n\nimport com.refinedmods.refinedstorage.api.network.node.ICoverable;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.Cover;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverType;\nimport com.refinedmods.refinedstorage.render.collision.CollisionGroup;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.util.CollisionUtils;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.world.level.BlockGetter;\nimport net.minecraft.world.level.block.entity.BlockEntity;\nimport net.minecraft.world.phys.AABB;\nimport net.minecraft.world.phys.shapes.Shapes;\nimport net.minecraft.world.phys.shapes.VoxelShape;\n\nimport javax.annotation.Nonnull;\n\npublic class ConstantsCable {\n\n    public static final CollisionGroup CORE = new CollisionGroup().addItem(CollisionUtils.getBounds(6, 6, 6, 10, 10, 10));\n    public static final CollisionGroup NORTH = new CollisionGroup().addItem(CollisionUtils.getBounds(6, 6, 0, 10, 10, 6));\n    public static final CollisionGroup EAST = new CollisionGroup().addItem(CollisionUtils.getBounds(10, 6, 6, 16, 10, 10));\n    public static final CollisionGroup SOUTH = new CollisionGroup().addItem(CollisionUtils.getBounds(6, 6, 10, 10, 10, 16));\n    public static final CollisionGroup WEST = new CollisionGroup().addItem(CollisionUtils.getBounds(0, 6, 6, 6, 10, 10));\n    public static final CollisionGroup UP = new CollisionGroup().addItem(CollisionUtils.getBounds(6, 10, 6, 10, 16, 10));\n    public static final CollisionGroup DOWN = new CollisionGroup().addItem(CollisionUtils.getBounds(6, 0, 6, 10, 6, 10));\n\n    public static final CollisionGroup HOLDER_NORTH = new CollisionGroup().addItem(getHolderBounds(Direction.NORTH));\n    public static final CollisionGroup HOLDER_EAST = new CollisionGroup().addItem(getHolderBounds(Direction.EAST));\n    public static final CollisionGroup HOLDER_SOUTH = new CollisionGroup().addItem(getHolderBounds(Direction.SOUTH));\n    public static final CollisionGroup HOLDER_WEST = new CollisionGroup().addItem(getHolderBounds(Direction.WEST));\n    public static final CollisionGroup HOLDER_UP = new CollisionGroup().addItem(getHolderBounds(Direction.UP));\n    public static final CollisionGroup HOLDER_DOWN = new CollisionGroup().addItem(getHolderBounds(Direction.DOWN));\n\n    @Nonnull\n    public static AABB getCoverBounds(Direction side) {\n        switch (side) {\n            case DOWN:\n                return CollisionUtils.getBounds(0, 0, 0, 16, 2, 16);\n            case UP:\n                return CollisionUtils.getBounds(0, 14, 0, 16, 16, 16);\n            case NORTH:\n                return CollisionUtils.getBounds(0, 0, 0, 16, 16, 2);\n            case SOUTH:\n                return CollisionUtils.getBounds(0, 0, 14, 16, 16, 16);\n            case WEST:\n                return CollisionUtils.getBounds(0, 0, 0, 2, 16, 16);\n            case EAST:\n                return CollisionUtils.getBounds(14, 0, 0, 16, 16, 16);\n            default:\n                return null;\n        }\n    }\n\n    @Nonnull\n    public static AABB getHolderBounds(Direction side) {\n        switch (side) {\n            case DOWN:\n                return CollisionUtils.getBounds(7, 2, 7, 9, 6, 9);\n            case UP:\n                return CollisionUtils.getBounds(7, 10, 7, 9, 14, 9);\n            case NORTH:\n                return CollisionUtils.getBounds(7, 7, 2, 9, 9, 6);\n            case SOUTH:\n                return CollisionUtils.getBounds(7, 7, 10, 9, 9, 14);\n            case WEST:\n                return CollisionUtils.getBounds(2, 7, 7, 6, 9, 9);\n            case EAST:\n                return CollisionUtils.getBounds(10, 7, 7, 14, 9, 9);\n            default:\n                return null;\n        }\n    }\n\n    public static VoxelShape addCoverVoxelShapes(VoxelShape shape, BlockGetter world, BlockPos pos) {\n        if (world != null) {\n            BlockEntity entity = world.getBlockEntity(pos);\n            if (entity instanceof NetworkNodeBlockEntity && ((NetworkNodeBlockEntity<?>) entity).getNode() instanceof ICoverable) {\n                CoverManager coverManager = ((ICoverable) ((NetworkNodeBlockEntity<?>) entity).getNode()).getCoverManager();\n                for (Direction value : Direction.values()) {\n                    Cover cover = coverManager.getCover(value);\n                    if (cover != null) {\n                        shape = Shapes.or(shape, Shapes.create(ConstantsCable.getCoverBounds(value)));\n                        if (cover.getType() == CoverType.NORMAL) {\n                            shape = Shapes.or(shape, Shapes.create(ConstantsCable.getHolderBounds(value)));\n                        }\n                    }\n                }\n            }\n        }\n        return shape;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/FluidRenderer.java",
    "content": "package com.refinedmods.refinedstorage.render;\n\nimport com.mojang.blaze3d.systems.RenderSystem;\nimport com.mojang.blaze3d.vertex.*;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.renderer.GameRenderer;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.inventory.InventoryMenu;\nimport net.minecraft.world.level.material.Fluid;\nimport net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.fluids.FluidType;\nimport org.joml.Matrix4f;\n\nimport javax.annotation.Nullable;\n\n/**\n * @see <a href=\"https://github.com/mezz/JustEnoughItems/blob/1.15/src/main/java/mezz/jei/plugins/vanilla/ingredients/fluid/FluidStackRenderer.java\">JEI implementation</a>\n */\npublic class FluidRenderer {\n    public static final FluidRenderer INSTANCE = new FluidRenderer(FluidType.BUCKET_VOLUME, 16, 16, 16);\n\n    private static final int TEX_WIDTH = 16;\n    private static final int TEX_HEIGHT = 16;\n\n    private final int capacityMb;\n    private final int width;\n    private final int height;\n    private final int minHeight;\n\n    public FluidRenderer(int capacityMb, int width, int height, int minHeight) {\n        this.capacityMb = capacityMb;\n        this.width = width;\n        this.height = height;\n        this.minHeight = minHeight;\n    }\n\n    private static TextureAtlasSprite getStillFluidSprite(FluidStack fluidStack) {\n        Minecraft minecraft = Minecraft.getInstance();\n        Fluid fluid = fluidStack.getFluid();\n        IClientFluidTypeExtensions attributes = IClientFluidTypeExtensions.of(fluid);\n        ResourceLocation fluidStill = attributes.getStillTexture(fluidStack);\n        return minecraft.getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(fluidStill);\n    }\n\n    private static void setGLColorFromInt(int color) {\n        float red = (color >> 16 & 0xFF) / 255.0F;\n        float green = (color >> 8 & 0xFF) / 255.0F;\n        float blue = (color & 0xFF) / 255.0F;\n        float alpha = ((color >> 24) & 0xFF) / 255F;\n\n        RenderSystem.setShaderColor(red, green, blue, alpha);\n    }\n\n    private static void drawTextureWithMasking(Matrix4f matrix, float xCoord, float yCoord, TextureAtlasSprite textureSprite, int maskTop, int maskRight, float zLevel) {\n        float uMin = textureSprite.getU0();\n        float uMax = textureSprite.getU1();\n        float vMin = textureSprite.getV0();\n        float vMax = textureSprite.getV1();\n        uMax = uMax - (maskRight / 16F * (uMax - uMin));\n        vMax = vMax - (maskTop / 16F * (vMax - vMin));\n\n        RenderSystem.setShader(GameRenderer::getPositionTexShader);\n\n        Tesselator tessellator = Tesselator.getInstance();\n        BufferBuilder bufferBuilder = tessellator.getBuilder();\n        bufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX);\n        bufferBuilder.vertex(matrix, xCoord, yCoord + 16, zLevel).uv(uMin, vMax).endVertex();\n        bufferBuilder.vertex(matrix, xCoord + 16 - maskRight, yCoord + 16, zLevel).uv(uMax, vMax).endVertex();\n        bufferBuilder.vertex(matrix, xCoord + 16 - maskRight, yCoord + maskTop, zLevel).uv(uMax, vMin).endVertex();\n        bufferBuilder.vertex(matrix, xCoord, yCoord + maskTop, zLevel).uv(uMin, vMin).endVertex();\n        tessellator.end();\n    }\n\n    public void render(GuiGraphics graphics, final int xPosition, final int yPosition, @Nullable FluidStack fluidStack) {\n        RenderSystem.enableBlend();\n        drawFluid(graphics.pose(), xPosition, yPosition, fluidStack);\n        RenderSystem.setShaderColor(1, 1, 1, 1);\n        RenderSystem.disableBlend();\n    }\n\n    private void drawFluid(PoseStack poseStack, final int xPosition, final int yPosition, @Nullable FluidStack fluidStack) {\n        if (fluidStack == null) {\n            return;\n        }\n        Fluid fluid = fluidStack.getFluid();\n        if (fluid == null) {\n            return;\n        }\n\n        TextureAtlasSprite fluidStillSprite = getStillFluidSprite(fluidStack);\n\n        IClientFluidTypeExtensions attributes = IClientFluidTypeExtensions.of(fluid);\n        int fluidColor = attributes.getTintColor(fluidStack);\n\n        int amount = fluidStack.getAmount();\n        int scaledAmount = (amount * height) / capacityMb;\n        if (amount > 0 && scaledAmount < minHeight) {\n            scaledAmount = minHeight;\n        }\n        if (scaledAmount > height) {\n            scaledAmount = height;\n        }\n\n        drawTiledSprite(poseStack, xPosition, yPosition, width, height, fluidColor, scaledAmount, fluidStillSprite);\n    }\n\n    private void drawTiledSprite(PoseStack poseStack, final int xPosition, final int yPosition, final int tiledWidth, final int tiledHeight, int color, int scaledAmount, TextureAtlasSprite sprite) {\n        RenderSystem.setShaderTexture(0, InventoryMenu.BLOCK_ATLAS);\n        Matrix4f matrix = poseStack.last().pose();\n        setGLColorFromInt(color);\n\n        final int xTileCount = tiledWidth / TEX_WIDTH;\n        final int xRemainder = tiledWidth - (xTileCount * TEX_WIDTH);\n        final int yTileCount = scaledAmount / TEX_HEIGHT;\n        final int yRemainder = scaledAmount - (yTileCount * TEX_HEIGHT);\n\n        final int yStart = yPosition + tiledHeight;\n\n        for (int xTile = 0; xTile <= xTileCount; xTile++) {\n            for (int yTile = 0; yTile <= yTileCount; yTile++) {\n                int width = (xTile == xTileCount) ? xRemainder : TEX_WIDTH;\n                int height = (yTile == yTileCount) ? yRemainder : TEX_HEIGHT;\n                int x = xPosition + (xTile * TEX_WIDTH);\n                int y = yStart - ((yTile + 1) * TEX_HEIGHT);\n                if (width > 0 && height > 0) {\n                    int maskTop = TEX_HEIGHT - height;\n                    int maskRight = TEX_WIDTH - width;\n\n                    drawTextureWithMasking(matrix, x, y, sprite, maskTop, maskRight, 100);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/RenderSettings.java",
    "content": "package com.refinedmods.refinedstorage.render;\n\nimport net.minecraft.ChatFormatting;\n\npublic class RenderSettings {\n    public static final RenderSettings INSTANCE = new RenderSettings();\n\n    private int primaryColor;\n    private int secondaryColor;\n\n    public RenderSettings() {\n        setColors(-1, -1);\n    }\n\n    public void setColors(int primaryColor, int secondaryColor) {\n        if (primaryColor == -1) {\n            this.primaryColor = 4210752;\n        } else {\n            this.primaryColor = primaryColor;\n        }\n\n        if (secondaryColor == -1) {\n            this.secondaryColor = ChatFormatting.WHITE.getColor();\n        } else {\n            this.secondaryColor = secondaryColor;\n        }\n    }\n\n    public int getPrimaryColor() {\n        return primaryColor;\n    }\n\n    public int getSecondaryColor() {\n        return secondaryColor;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/Styles.java",
    "content": "package com.refinedmods.refinedstorage.render;\n\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.network.chat.Style;\nimport net.minecraft.network.chat.TextColor;\n\npublic final class Styles {\n    public static final Style WHITE = Style.EMPTY.withColor(TextColor.fromLegacyFormat(ChatFormatting.WHITE));\n    public static final Style GRAY = Style.EMPTY.withColor(TextColor.fromLegacyFormat(ChatFormatting.GRAY));\n    public static final Style YELLOW = Style.EMPTY.withColor(TextColor.fromLegacyFormat(ChatFormatting.YELLOW));\n    public static final Style RED = Style.EMPTY.withColor(TextColor.fromLegacyFormat(ChatFormatting.RED));\n    public static final Style BLUE = Style.EMPTY.withColor(TextColor.fromLegacyFormat(ChatFormatting.BLUE));\n    public static final Style AQUA = Style.EMPTY.withColor(TextColor.fromLegacyFormat(ChatFormatting.AQUA));\n\n    private Styles() {\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/blockentity/PatternItemBlockEntityRenderer.java",
    "content": "package com.refinedmods.refinedstorage.render.blockentity;\n\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.item.PatternItem;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.model.geom.EntityModelSet;\nimport net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer;\nimport net.minecraft.client.renderer.MultiBufferSource;\nimport net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher;\nimport net.minecraft.world.item.ItemDisplayContext;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.client.extensions.common.IClientItemExtensions;\n\npublic class PatternItemBlockEntityRenderer extends BlockEntityWithoutLevelRenderer {\n    private static PatternItemBlockEntityRenderer instance;\n\n    public PatternItemBlockEntityRenderer(BlockEntityRenderDispatcher dispatcher, EntityModelSet entityModelSet) {\n        super(dispatcher, entityModelSet);\n    }\n\n    @Override\n    public void renderByItem(ItemStack stack, ItemDisplayContext context, PoseStack poseStack, MultiBufferSource renderTypeBuffer, int combinedLight, int combinedOverlay) {\n        ICraftingPattern pattern = PatternItem.fromCache(Minecraft.getInstance().level, stack);\n\n        ItemStack outputStack = pattern.getOutputs().get(0);\n\n        IClientItemExtensions.of(outputStack.getItem()).getCustomRenderer()\n            .renderByItem(outputStack, context, poseStack, renderTypeBuffer, combinedLight, combinedOverlay);\n    }\n\n    public static PatternItemBlockEntityRenderer getInstance() {\n        if (instance == null) {\n            instance = new PatternItemBlockEntityRenderer(\n                Minecraft.getInstance().getBlockEntityRenderDispatcher(),\n                Minecraft.getInstance().getEntityModels()\n            );\n        }\n        return instance;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/blockentity/StorageMonitorBlockEntityRenderer.java",
    "content": "package com.refinedmods.refinedstorage.render.blockentity;\n\nimport com.mojang.blaze3d.platform.Lighting;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.mojang.blaze3d.vertex.VertexConsumer;\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.block.StorageMonitorBlock;\nimport com.refinedmods.refinedstorage.blockentity.StorageMonitorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.Font;\nimport net.minecraft.client.renderer.LevelRenderer;\nimport net.minecraft.client.renderer.MultiBufferSource;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.client.renderer.blockentity.BlockEntityRenderer;\nimport net.minecraft.client.renderer.texture.OverlayTexture;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.client.resources.model.BakedModel;\nimport net.minecraft.core.Direction;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.inventory.InventoryMenu;\nimport net.minecraft.world.item.ItemDisplayContext;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.level.material.Fluid;\nimport net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions;\nimport net.neoforged.neoforge.common.util.TransformationHelper;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport org.joml.Vector3f;\n\npublic class StorageMonitorBlockEntityRenderer implements BlockEntityRenderer<StorageMonitorBlockEntity> {\n    @Override\n    public void render(StorageMonitorBlockEntity blockEntity, float partialTicks, PoseStack poseStack, MultiBufferSource renderTypeBuffer, int i, int i1) {\n        Direction direction = Direction.NORTH;\n\n        BlockState state = blockEntity.getLevel().getBlockState(blockEntity.getBlockPos());\n        if (state.getBlock() instanceof StorageMonitorBlock) {\n            direction = state.getValue(RSBlocks.STORAGE_MONITOR.get().getDirection().getProperty());\n        }\n\n        final int light = LevelRenderer.getLightColor(blockEntity.getLevel(), blockEntity.getBlockPos().offset(direction.getNormal()));\n        final float rotation = (float) (Math.PI * (360 - direction.getOpposite().get2DDataValue() * 90) / 180d);\n\n        final int type = blockEntity.getStackType();\n\n        final ItemStack itemStack = blockEntity.getItemStack();\n        final FluidStack fluidStack = blockEntity.getFluidStack();\n\n        if (type == IType.ITEMS && itemStack != null && !itemStack.isEmpty()) {\n            renderItem(poseStack, renderTypeBuffer, direction, rotation, light, itemStack);\n\n            String amount = API.instance().getQuantityFormatter().formatWithUnits(blockEntity.getAmount());\n\n            renderText(poseStack, renderTypeBuffer, direction, rotation, light, amount);\n        } else if (type == IType.FLUIDS && fluidStack != null && !fluidStack.isEmpty()) {\n            renderFluid(poseStack, renderTypeBuffer, direction, rotation, light, fluidStack);\n\n            String amount = API.instance().getQuantityFormatter().formatInBucketFormWithOnlyTrailingDigitsIfZero(blockEntity.getAmount());\n\n            renderText(poseStack, renderTypeBuffer, direction, rotation, light, amount);\n        }\n    }\n\n    private void renderText(PoseStack poseStack, MultiBufferSource renderTypeBuffer, Direction direction, float rotation, int light, String amount) {\n        poseStack.pushPose();\n\n        float stringOffset = -(Minecraft.getInstance().font.width(amount) * 0.01F) / 2F;\n\n        poseStack.translate(0.5D, 0.5D, 0.5D);\n        poseStack.translate(\n            ((float) direction.getStepX() * 0.501F) + (direction.getStepZ() * stringOffset),\n            -0.275,\n            ((float) direction.getStepZ() * 0.501F) - (direction.getStepX() * stringOffset)\n        );\n\n        poseStack.mulPose(TransformationHelper.quatFromXYZ(new Vector3f(direction.getStepX() * 180, 0, direction.getStepZ() * 180), true));\n        poseStack.mulPose(TransformationHelper.quatFromXYZ(new Vector3f(0, rotation, 0), false));\n\n        poseStack.scale(0.01F, 0.01F, 0.01F);\n\n        Minecraft.getInstance().font.drawInBatch(\n            amount,\n            0,\n            0,\n            -1,\n            false,\n            poseStack.last().pose(),\n            renderTypeBuffer,\n            Font.DisplayMode.NORMAL,\n            0,\n            light\n        );\n\n        poseStack.popPose();\n    }\n\n    private void renderItem(PoseStack poseStack, MultiBufferSource renderTypeBuffer, Direction direction, float rotation, int light, ItemStack itemStack) {\n        poseStack.pushPose();\n\n        // Put it in the middle, outwards, and facing the correct direction\n        poseStack.translate(0.5D, 0.5D, 0.5D);\n        poseStack.translate((float) direction.getStepX() * 0.501F, 0, (float) direction.getStepZ() * 0.501F);\n        poseStack.mulPose(TransformationHelper.quatFromXYZ(new Vector3f(0, rotation, 0), false));\n\n        // Make it look \"flat\"\n        poseStack.scale(0.5F, -0.5F, -0.00005f);\n\n        // Fix rotation after making it look flat\n        poseStack.mulPose(TransformationHelper.quatFromXYZ(new Vector3f(0, 0, 180), true));\n\n        BakedModel itemModel = Minecraft.getInstance().getItemRenderer().getModel(itemStack, null, null, 0);\n        boolean render3D = itemModel.isGui3d();\n\n        if (render3D) {\n            Lighting.setupFor3DItems();\n        } else {\n            Lighting.setupForFlatItems();\n        }\n\n        Minecraft.getInstance().getItemRenderer().render(\n            itemStack,\n            ItemDisplayContext.GUI,\n            false,\n            poseStack,\n            renderTypeBuffer,\n            light,\n            OverlayTexture.NO_OVERLAY,\n            itemModel\n        );\n\n        poseStack.popPose();\n    }\n\n    private void renderFluid(PoseStack poseStack, MultiBufferSource renderTypeBuffer, Direction direction, float rotation, int light, FluidStack fluidStack) {\n        poseStack.pushPose();\n\n        poseStack.translate(0.5D, 0.5D, 0.5D);\n        poseStack.translate((float) direction.getStepX() * 0.51F, 0.5F, (float) direction.getStepZ() * 0.51F);\n        poseStack.mulPose(TransformationHelper.quatFromXYZ(new Vector3f(0, rotation, 0), false));\n\n        poseStack.scale(0.5F, 0.5F, 0.5F);\n\n        final Fluid fluid = fluidStack.getFluid();\n        final IClientFluidTypeExtensions attributes = IClientFluidTypeExtensions.of(fluid);\n        final ResourceLocation fluidStill = attributes.getStillTexture(fluidStack);\n        final TextureAtlasSprite sprite = Minecraft.getInstance().getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(fluidStill);\n        final int fluidColor = attributes.getTintColor(fluidStack);\n\n        final VertexConsumer buffer = renderTypeBuffer.getBuffer(RenderType.text(sprite.atlasLocation()));\n\n        final int colorRed = fluidColor >> 16 & 0xFF;\n        final int colorGreen = fluidColor >> 8 & 0xFF;\n        final int colorBlue = fluidColor & 0xFF;\n        final int colorAlpha = fluidColor >> 24 & 0xFF;\n\n        buffer.vertex(poseStack.last().pose(), -0.5F, -0.5F, 0F)\n            .color(colorRed, colorGreen, colorBlue, colorAlpha)\n            .uv(sprite.getU0(), sprite.getV0())\n            .uv2(light)\n            .endVertex();\n        buffer.vertex(poseStack.last().pose(), 0.5F, -0.5F, 0F)\n            .color(colorRed, colorGreen, colorBlue, colorAlpha)\n            .uv(sprite.getU1(), sprite.getV0())\n            .uv2(light)\n            .endVertex();\n        buffer.vertex(poseStack.last().pose(), 0.5F, -1.5F, 0F)\n            .color(colorRed, colorGreen, colorBlue, colorAlpha)\n            .uv(sprite.getU1(), sprite.getV1())\n            .uv2(light)\n            .endVertex();\n        buffer.vertex(poseStack.last().pose(), -0.5F, -1.5F, 0F)\n            .color(colorRed, colorGreen, colorBlue, colorAlpha)\n            .uv(sprite.getU0(), sprite.getV1())\n            .uv2(light)\n            .endVertex();\n\n        poseStack.popPose();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/collision/CollisionGroup.java",
    "content": "package com.refinedmods.refinedstorage.render.collision;\n\nimport net.minecraft.core.Direction;\nimport net.minecraft.world.phys.AABB;\n\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class CollisionGroup {\n\n    private List<AABB> items = new ArrayList<>();\n    private boolean canAccessGui;\n    @Nullable\n    private Direction direction;\n\n    public CollisionGroup addItem(AABB item) {\n        items.add(item);\n\n        return this;\n    }\n\n    public List<AABB> getItems() {\n        return items;\n    }\n\n    public boolean canAccessGui() {\n        return canAccessGui;\n    }\n\n    public CollisionGroup setCanAccessGui(boolean canAccessGui) {\n        this.canAccessGui = canAccessGui;\n\n        return this;\n    }\n\n    @Nullable\n    public Direction getDirection() {\n        return direction;\n    }\n\n    public CollisionGroup setDirection(Direction direction) {\n        this.direction = direction;\n\n        return this;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/color/PatternItemColor.java",
    "content": "package com.refinedmods.refinedstorage.render.color;\n\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.item.PatternItem;\nimport com.refinedmods.refinedstorage.render.model.baked.PatternBakedModel;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.color.item.ItemColor;\nimport net.minecraft.world.item.ItemStack;\n\npublic class PatternItemColor implements ItemColor {\n    @Override\n    public int getColor(ItemStack stack, int tintIndex) {\n        ICraftingPattern pattern = PatternItem.fromCache(Minecraft.getInstance().level, stack);\n\n        if (PatternBakedModel.canDisplayOutput(stack, pattern)) {\n            int color = Minecraft.getInstance().getItemColors().getColor(pattern.getOutputs().get(0), tintIndex);\n\n            if (color != -1) {\n                return color;\n            }\n        }\n\n        return 0xFFFFFF;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/model/CubeBuilder.java",
    "content": "package com.refinedmods.refinedstorage.render.model;\n\nimport net.minecraft.client.renderer.block.model.BakedQuad;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.core.Direction;\nimport net.neoforged.neoforge.client.model.pipeline.QuadBakingVertexConsumer;\nimport org.joml.Vector3f;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.function.Function;\n\npublic class CubeBuilder {\n    private Vector3f from;\n    private Vector3f to;\n    private final Map<Direction, Face> faces = new HashMap<>();\n    private int color = 0xFFFFFFFF;\n\n    public CubeBuilder from(float x, float y, float z) {\n        this.from = new Vector3f(x / 16, y / 16, z / 16);\n\n        return this;\n    }\n\n    public CubeBuilder to(float x, float y, float z) {\n        this.to = new Vector3f(x / 16, y / 16, z / 16);\n\n        return this;\n    }\n\n    public CubeBuilder color(int color) {\n        this.color = color;\n\n        return this;\n    }\n\n    public CubeBuilder addFaces(Function<Direction, Face> faceSupplier) {\n        for (Direction facing : Direction.values()) {\n            addFace(faceSupplier.apply(facing));\n        }\n\n        return this;\n    }\n\n    public CubeBuilder addFace(Face face) {\n        faces.put(face.face, face);\n\n        return this;\n    }\n\n    public List<BakedQuad> bake() {\n        List<BakedQuad> quads = new ArrayList<>();\n\n        for (Map.Entry<Direction, Face> entry : faces.entrySet()) {\n            quads.add(bakeFace(entry.getKey(), entry.getValue()));\n        }\n\n        return quads;\n    }\n\n    private BakedQuad bakeFace(Direction facing, Face cubeFace) {\n        List<BakedQuad> quad = new ArrayList<>();\n        QuadBakingVertexConsumer builder = new QuadBakingVertexConsumer(quad::add);\n\n        builder.setSprite(cubeFace.sprite);\n        builder.setDirection(facing);\n        builder.setTintIndex(-1);\n        builder.setShade(true);\n\n        Uv uv = getDefaultUv(facing, cubeFace.sprite, from.x(), from.y(), from.z(), to.x(), to.y(), to.z());\n\n        switch (facing) {\n            case DOWN:\n                addVertexTopRight(builder, cubeFace, to.x(), from.y(), from.z(), uv);\n                addVertexBottomRight(builder, cubeFace, to.x(), from.y(), to.z(), uv);\n                addVertexBottomLeft(builder, cubeFace, from.x(), from.y(), to.z(), uv);\n                addVertexTopLeft(builder, cubeFace, from.x(), from.y(), from.z(), uv);\n                break;\n            case UP:\n                addVertexTopLeft(builder, cubeFace, from.x(), to.y(), from.z(), uv);\n                addVertexBottomLeft(builder, cubeFace, from.x(), to.y(), to.z(), uv);\n                addVertexBottomRight(builder, cubeFace, to.x(), to.y(), to.z(), uv);\n                addVertexTopRight(builder, cubeFace, to.x(), to.y(), from.z(), uv);\n                break;\n            case NORTH:\n                addVertexBottomRight(builder, cubeFace, to.x(), to.y(), from.z(), uv);\n                addVertexTopRight(builder, cubeFace, to.x(), from.y(), from.z(), uv);\n                addVertexTopLeft(builder, cubeFace, from.x(), from.y(), from.z(), uv);\n                addVertexBottomLeft(builder, cubeFace, from.x(), to.y(), from.z(), uv);\n                break;\n            case SOUTH:\n                addVertexBottomLeft(builder, cubeFace, from.x(), to.y(), to.z(), uv);\n                addVertexTopLeft(builder, cubeFace, from.x(), from.y(), to.z(), uv);\n                addVertexTopRight(builder, cubeFace, to.x(), from.y(), to.z(), uv);\n                addVertexBottomRight(builder, cubeFace, to.x(), to.y(), to.z(), uv);\n                break;\n            case WEST:\n                addVertexTopLeft(builder, cubeFace, from.x(), from.y(), from.z(), uv);\n                addVertexTopRight(builder, cubeFace, from.x(), from.y(), to.z(), uv);\n                addVertexBottomRight(builder, cubeFace, from.x(), to.y(), to.z(), uv);\n                addVertexBottomLeft(builder, cubeFace, from.x(), to.y(), from.z(), uv);\n                break;\n            case EAST:\n                addVertexBottomRight(builder, cubeFace, to.x(), to.y(), from.z(), uv);\n                addVertexBottomLeft(builder, cubeFace, to.x(), to.y(), to.z(), uv);\n                addVertexTopLeft(builder, cubeFace, to.x(), from.y(), to.z(), uv);\n                addVertexTopRight(builder, cubeFace, to.x(), from.y(), from.z(), uv);\n                break;\n        }\n\n        return quad.get(0);\n    }\n\n    private Uv getDefaultUv(Direction face, TextureAtlasSprite texture, float x1, float y1, float z1, float x2, float y2, float z2) {\n        Uv uv = new Uv();\n\n        if (face.getAxis() != Direction.Axis.Y) {\n            uv.v1 = texture.getV(1 - y1);\n            uv.v2 = texture.getV(1 - y2);\n        } else {\n            uv.v1 = texture.getV(z1);\n            uv.v2 = texture.getV(z2);\n        }\n\n        switch (face) {\n            case DOWN, UP, SOUTH -> {\n                uv.u1 = texture.getU(x1);\n                uv.u2 = texture.getU(x2);\n            }\n            case NORTH -> {\n                uv.u1 = texture.getU(1 - x2);\n                uv.u2 = texture.getU(1 - x1);\n            }\n            case WEST -> {\n                uv.u1 = texture.getU(z1);\n                uv.u2 = texture.getU(z2);\n            }\n            case EAST -> {\n                uv.u1 = texture.getU(1 - z2);\n                uv.u2 = texture.getU(1 - z1);\n            }\n        }\n\n        return uv;\n    }\n\n    private void addVertexTopLeft(QuadBakingVertexConsumer builder, Face face, float x, float y, float z, Uv uv) {\n        float u;\n        float v;\n\n        switch (face.uvRotation) {\n            default:\n            case CLOCKWISE_0:\n                u = uv.u1;\n                v = uv.v1;\n                break;\n            case CLOCKWISE_90:\n                u = uv.u1;\n                v = uv.v2;\n                break;\n            case CLOCKWISE_180:\n                u = uv.u2;\n                v = uv.v2;\n                break;\n            case CLOCKWISE_270:\n                u = uv.u2;\n                v = uv.v1;\n                break;\n        }\n\n        addVertex(builder, face, x, y, z, u, v);\n    }\n\n    private void addVertexTopRight(QuadBakingVertexConsumer builder, Face face, float x, float y, float z, Uv uv) {\n        float u;\n        float v;\n\n        switch (face.uvRotation) {\n            default:\n            case CLOCKWISE_0:\n                u = uv.u2;\n                v = uv.v1;\n                break;\n            case CLOCKWISE_90:\n                u = uv.u1;\n                v = uv.v1;\n                break;\n            case CLOCKWISE_180:\n                u = uv.u1;\n                v = uv.v2;\n                break;\n            case CLOCKWISE_270:\n                u = uv.u2;\n                v = uv.v2;\n                break;\n        }\n\n        addVertex(builder, face, x, y, z, u, v);\n    }\n\n    private void addVertexBottomRight(QuadBakingVertexConsumer builder, Face face, float x, float y, float z, Uv uv) {\n        float u;\n        float v;\n\n        switch (face.uvRotation) {\n            default:\n            case CLOCKWISE_0:\n                u = uv.u2;\n                v = uv.v2;\n                break;\n            case CLOCKWISE_90:\n                u = uv.u2;\n                v = uv.v1;\n                break;\n            case CLOCKWISE_180:\n                u = uv.u1;\n                v = uv.v1;\n                break;\n            case CLOCKWISE_270:\n                u = uv.u1;\n                v = uv.v2;\n                break;\n        }\n\n        addVertex(builder, face, x, y, z, u, v);\n    }\n\n    private void addVertexBottomLeft(QuadBakingVertexConsumer builder, Face face, float x, float y, float z, Uv uv) {\n        float u;\n        float v;\n\n        switch (face.uvRotation) {\n            default:\n            case CLOCKWISE_0:\n                u = uv.u1;\n                v = uv.v2;\n                break;\n            case CLOCKWISE_90:\n                u = uv.u2;\n                v = uv.v2;\n                break;\n            case CLOCKWISE_180:\n                u = uv.u2;\n                v = uv.v1;\n                break;\n            case CLOCKWISE_270:\n                u = uv.u1;\n                v = uv.v1;\n                break;\n        }\n\n        addVertex(builder, face, x, y, z, u, v);\n    }\n\n    private void addVertex(QuadBakingVertexConsumer builder, Face face, float x, float y, float z, float u, float v) {\n        builder.vertex(x, y, z);\n        builder.normal(face.face.getStepX(), face.face.getStepY(), face.face.getStepZ());\n        float r = (color >> 16 & 0xFF) / 255F;\n        float g = (color >> 8 & 0xFF) / 255F;\n        float b = (color & 0xFF) / 255F;\n        float a = (color >> 24 & 0xFF) / 255F;\n        builder.uv(u, v);\n        builder.color(r, g, b, a);\n        builder.endVertex();\n    }\n\n    public enum UvRotation {\n        CLOCKWISE_0,\n        CLOCKWISE_90,\n        CLOCKWISE_180,\n        CLOCKWISE_270\n    }\n\n    private static class Uv {\n        private float u1;\n        private float u2;\n        private float v1;\n        private float v2;\n    }\n\n    public static class Face {\n        private final Direction face;\n        private final TextureAtlasSprite sprite;\n        private final UvRotation uvRotation = UvRotation.CLOCKWISE_0;\n\n        public Face(Direction face, TextureAtlasSprite sprite) {\n            this.face = face;\n            this.sprite = sprite;\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/model/DiskDriveGeometryLoader.java",
    "content": "package com.refinedmods.refinedstorage.render.model;\n\nimport com.google.gson.JsonDeserializationContext;\nimport com.google.gson.JsonObject;\nimport net.neoforged.neoforge.client.model.geometry.IGeometryLoader;\n\npublic class DiskDriveGeometryLoader implements IGeometryLoader<DiskDriveUnbakedGeometry> {\n    @Override\n    public DiskDriveUnbakedGeometry read(final JsonObject jsonObject,\n                                         final JsonDeserializationContext deserializationContext) {\n        return new DiskDriveUnbakedGeometry();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/model/DiskDriveUnbakedGeometry.java",
    "content": "package com.refinedmods.refinedstorage.render.model;\n\nimport com.mojang.math.Transformation;\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.render.model.baked.DiskDriveBakedModel;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.client.renderer.block.model.ItemOverrides;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.client.resources.model.*;\nimport net.minecraft.core.Direction;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.neoforge.client.model.SimpleModelState;\nimport net.neoforged.neoforge.client.model.geometry.IGeometryBakingContext;\nimport net.neoforged.neoforge.client.model.geometry.IUnbakedGeometry;\nimport org.joml.Vector3f;\n\nimport java.util.Objects;\nimport java.util.function.BiFunction;\nimport java.util.function.Function;\n\npublic class DiskDriveUnbakedGeometry implements IUnbakedGeometry<DiskDriveUnbakedGeometry> {\n    private static final ResourceLocation BASE_MODEL = new ResourceLocation(RS.ID, \"block/disk_drive_base\");\n    private static final ResourceLocation DISK_MODEL = new ResourceLocation(RS.ID, \"block/disks/disk\");\n    private static final ResourceLocation DISK_DISCONNECTED_MODEL = new ResourceLocation(RS.ID, \"block/disks/disk_disconnected\");\n    private static final ResourceLocation DISK_FULL_MODEL = new ResourceLocation(RS.ID, \"block/disks/disk_full\");\n    private static final ResourceLocation DISK_NEAR_CAPACITY_MODEL = new ResourceLocation(RS.ID, \"block/disks/disk_near_capacity\");\n\n    @Override\n    public void resolveParents(final Function<ResourceLocation, UnbakedModel> modelGetter,\n                               final IGeometryBakingContext context) {\n        modelGetter.apply(BASE_MODEL).resolveParents(modelGetter);\n        modelGetter.apply(DISK_MODEL).resolveParents(modelGetter);\n        modelGetter.apply(DISK_DISCONNECTED_MODEL).resolveParents(modelGetter);\n        modelGetter.apply(DISK_FULL_MODEL).resolveParents(modelGetter);\n        modelGetter.apply(DISK_NEAR_CAPACITY_MODEL).resolveParents(modelGetter);\n    }\n\n    @Override\n    public BakedModel bake(final IGeometryBakingContext context,\n                           final ModelBaker baker,\n                           final Function<Material, TextureAtlasSprite> spriteGetter,\n                           final ModelState modelState,\n                           final ItemOverrides overrides,\n                           final ResourceLocation modelLocation) {\n        return new DiskDriveBakedModel(\n            Objects.requireNonNull(baker.bake(BASE_MODEL, modelState, spriteGetter)),\n            getBaseModelBaker(modelState, baker, spriteGetter),\n            getDiskModelBaker(DISK_MODEL, modelState, baker, spriteGetter),\n            getDiskModelBaker(DISK_NEAR_CAPACITY_MODEL, modelState, baker, spriteGetter),\n            getDiskModelBaker(DISK_FULL_MODEL, modelState, baker, spriteGetter),\n            getDiskModelBaker(DISK_DISCONNECTED_MODEL, modelState, baker, spriteGetter)\n        );\n    }\n\n    private Function<Direction, BakedModel> getBaseModelBaker(final ModelState state,\n                                                              final ModelBaker baker,\n                                                              final Function<Material, TextureAtlasSprite> sg) {\n        return direction -> {\n            final Transformation rotation = new Transformation(null, RenderUtils.getQuaternion(direction), null, null);\n            final ModelState wrappedState = new SimpleModelState(rotation, state.isUvLocked());\n            return baker.bake(BASE_MODEL, wrappedState, sg);\n        };\n    }\n\n    private BiFunction<Direction, Vector3f, BakedModel> getDiskModelBaker(final ResourceLocation id,\n                                                                          final ModelState state,\n                                                                          final ModelBaker baker,\n                                                                          final Function\n                                                                              <Material, TextureAtlasSprite> sg) {\n        return (direction, trans) -> {\n            final Transformation translation = new Transformation(trans, null, null, null);\n            final Transformation rotation = new Transformation(null, RenderUtils.getQuaternion(direction), null, null);\n            final ModelState wrappedState = new SimpleModelState(rotation.compose(translation), state.isUvLocked());\n            return baker.bake(id, wrappedState, sg);\n        };\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/model/DiskManipulatorGeometryLoader.java",
    "content": "package com.refinedmods.refinedstorage.render.model;\n\nimport com.google.gson.JsonDeserializationContext;\nimport com.google.gson.JsonObject;\nimport net.neoforged.neoforge.client.model.geometry.IGeometryLoader;\n\npublic class DiskManipulatorGeometryLoader implements IGeometryLoader<DiskManipulatorUnbakedGeometry> {\n    @Override\n    public DiskManipulatorUnbakedGeometry read(final JsonObject jsonObject,\n                                               final JsonDeserializationContext deserializationContext) {\n        return new DiskManipulatorUnbakedGeometry();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/model/DiskManipulatorUnbakedGeometry.java",
    "content": "package com.refinedmods.refinedstorage.render.model;\n\nimport com.mojang.math.Transformation;\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.render.model.baked.DiskManipulatorBakedModel;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.client.renderer.block.model.ItemOverrides;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.client.resources.model.*;\nimport net.minecraft.core.Direction;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.DyeColor;\nimport net.neoforged.neoforge.client.RenderTypeGroup;\nimport net.neoforged.neoforge.client.model.SimpleModelState;\nimport net.neoforged.neoforge.client.model.geometry.IGeometryBakingContext;\nimport net.neoforged.neoforge.client.model.geometry.IUnbakedGeometry;\nimport org.joml.Vector3f;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.function.BiFunction;\nimport java.util.function.Function;\n\npublic class DiskManipulatorUnbakedGeometry implements IUnbakedGeometry<DiskManipulatorUnbakedGeometry> {\n    private static final ResourceLocation BASE_MODEL_DISCONNECTED = new ResourceLocation(RS.ID, \"block/disk_manipulator/disconnected\");\n\n    private final Map<DyeColor, ResourceLocation> BASE_MODEL_CONNECTED = new HashMap<>();\n    private static final ResourceLocation DISK_MODEL = new ResourceLocation(RS.ID, \"block/disks/disk\");\n    private static final ResourceLocation DISK_DISCONNECTED_MODEL = new ResourceLocation(RS.ID, \"block/disks/disk_disconnected\");\n    private static final ResourceLocation DISK_FULL_MODEL = new ResourceLocation(RS.ID, \"block/disks/disk_full\");\n    private static final ResourceLocation DISK_NEAR_CAPACITY_MODEL = new ResourceLocation(RS.ID, \"block/disks/disk_near_capacity\");\n\n    public DiskManipulatorUnbakedGeometry() {\n        for (DyeColor value : DyeColor.values()) {\n            BASE_MODEL_CONNECTED.put(value, new ResourceLocation(RS.ID, \"block/disk_manipulator/\" + value.getName()));\n        }\n    }\n\n    @Override\n    public void resolveParents(final Function<ResourceLocation, UnbakedModel> modelGetter,\n                               final IGeometryBakingContext context) {\n        modelGetter.apply(BASE_MODEL_DISCONNECTED).resolveParents(modelGetter);\n        modelGetter.apply(DISK_MODEL).resolveParents(modelGetter);\n        modelGetter.apply(DISK_DISCONNECTED_MODEL).resolveParents(modelGetter);\n        modelGetter.apply(DISK_FULL_MODEL).resolveParents(modelGetter);\n        modelGetter.apply(DISK_NEAR_CAPACITY_MODEL).resolveParents(modelGetter);\n        BASE_MODEL_CONNECTED.values().forEach(m -> modelGetter.apply(m).resolveParents(modelGetter));\n    }\n\n    @Override\n    public BakedModel bake(final IGeometryBakingContext context,\n                           final ModelBaker baker,\n                           final Function<Material, TextureAtlasSprite> spriteGetter,\n                           final ModelState modelState,\n                           final ItemOverrides overrides,\n                           final ResourceLocation modelLocation) {\n        var renderTypeHint = context.getRenderTypeHint();\n        var renderTypes = renderTypeHint != null ? context.getRenderType(renderTypeHint) : RenderTypeGroup.EMPTY;\n\n        return new DiskManipulatorBakedModel(\n            Objects.requireNonNull(baker.bake(BASE_MODEL_DISCONNECTED, modelState, spriteGetter)),\n            getBaseModelBakerConnected(modelState, baker, spriteGetter),\n            getBaseModelBaker(modelState, baker, spriteGetter),\n            getDiskModelBaker(DISK_MODEL, modelState, baker, spriteGetter),\n            getDiskModelBaker(DISK_NEAR_CAPACITY_MODEL, modelState, baker, spriteGetter),\n            getDiskModelBaker(DISK_FULL_MODEL, modelState, baker, spriteGetter),\n            getDiskModelBaker(DISK_DISCONNECTED_MODEL, modelState, baker, spriteGetter),\n            renderTypes\n        );\n    }\n\n    private Function<Direction, BakedModel> getBaseModelBaker(final ModelState state,\n                                                              final ModelBaker baker,\n                                                              final Function<Material, TextureAtlasSprite> sg) {\n        return direction -> {\n            final Transformation rotation = new Transformation(null, RenderUtils.getQuaternion(direction), null, null);\n            final ModelState wrappedState = new SimpleModelState(rotation, state.isUvLocked());\n            return baker.bake(BASE_MODEL_DISCONNECTED, wrappedState, sg);\n        };\n    }\n\n    private BiFunction<Direction, DyeColor, BakedModel> getBaseModelBakerConnected(final ModelState state,\n                                                                                   final ModelBaker baker,\n                                                                                   final Function<Material, TextureAtlasSprite> sg) {\n        return (direction, color) -> {\n            final Transformation rotation = new Transformation(null, RenderUtils.getQuaternion(direction), null, null);\n            final ModelState wrappedState = new SimpleModelState(rotation, state.isUvLocked());\n            return baker.bake(BASE_MODEL_CONNECTED.get(color), wrappedState, sg);\n        };\n    }\n\n    private BiFunction<Direction, Vector3f, BakedModel> getDiskModelBaker(final ResourceLocation id,\n                                                                          final ModelState state,\n                                                                          final ModelBaker baker,\n                                                                          final Function\n                                                                              <Material, TextureAtlasSprite> sg) {\n        return (direction, trans) -> {\n            final Transformation translation = new Transformation(trans, null, null, null);\n            final Transformation rotation = new Transformation(null, RenderUtils.getQuaternion(direction), null, null);\n            final ModelState wrappedState = new SimpleModelState(rotation.compose(translation), state.isUvLocked());\n            return baker.bake(id, wrappedState, sg);\n        };\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/model/PortableGridGeometryLoader.java",
    "content": "package com.refinedmods.refinedstorage.render.model;\n\nimport com.google.gson.JsonDeserializationContext;\nimport com.google.gson.JsonObject;\nimport net.neoforged.neoforge.client.model.geometry.IGeometryLoader;\n\npublic class PortableGridGeometryLoader implements IGeometryLoader<PortableGridUnbakedGeometry> {\n    @Override\n    public PortableGridUnbakedGeometry read(final JsonObject jsonObject,\n                                            final JsonDeserializationContext deserializationContext) {\n        return new PortableGridUnbakedGeometry();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/model/PortableGridUnbakedGeometry.java",
    "content": "package com.refinedmods.refinedstorage.render.model;\n\nimport com.mojang.math.Transformation;\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.render.model.baked.PortableGridBakedModel;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.client.renderer.block.model.ItemOverrides;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.client.resources.model.*;\nimport net.minecraft.core.Direction;\nimport net.minecraft.resources.ResourceLocation;\nimport net.neoforged.neoforge.client.RenderTypeGroup;\nimport net.neoforged.neoforge.client.model.SimpleModelState;\nimport net.neoforged.neoforge.client.model.geometry.IGeometryBakingContext;\nimport net.neoforged.neoforge.client.model.geometry.IUnbakedGeometry;\nimport java.util.Objects;\nimport java.util.function.Function;\n\npublic class PortableGridUnbakedGeometry implements IUnbakedGeometry<PortableGridUnbakedGeometry> {\n    private static final ResourceLocation BASE_CONNECTED_MODEL = new ResourceLocation(RS.ID, \"block/portable_grid_connected\");\n    private static final ResourceLocation BASE_DISCONNECTED_MODEL = new ResourceLocation(RS.ID, \"block/portable_grid_disconnected\");\n    private static final ResourceLocation DISK_MODEL = new ResourceLocation(RS.ID, \"block/disks/portable_grid_disk\");\n    private static final ResourceLocation DISK_DISCONNECTED_MODEL = new ResourceLocation(RS.ID, \"block/disks/portable_grid_disk_disconnected\");\n    private static final ResourceLocation DISK_FULL_MODEL = new ResourceLocation(RS.ID, \"block/disks/portable_grid_disk_full\");\n    private static final ResourceLocation DISK_NEAR_CAPACITY_MODEL = new ResourceLocation(RS.ID, \"block/disks/portable_grid_disk_near_capacity\");\n\n    @Override\n    public void resolveParents(final Function<ResourceLocation, UnbakedModel> modelGetter,\n                               final IGeometryBakingContext context) {\n        modelGetter.apply(BASE_CONNECTED_MODEL).resolveParents(modelGetter);\n        modelGetter.apply(BASE_DISCONNECTED_MODEL).resolveParents(modelGetter);\n        modelGetter.apply(DISK_MODEL).resolveParents(modelGetter);\n        modelGetter.apply(DISK_DISCONNECTED_MODEL).resolveParents(modelGetter);\n        modelGetter.apply(DISK_FULL_MODEL).resolveParents(modelGetter);\n        modelGetter.apply(DISK_NEAR_CAPACITY_MODEL).resolveParents(modelGetter);\n    }\n\n    @Override\n    public BakedModel bake(final IGeometryBakingContext context,\n                           final ModelBaker baker,\n                           final Function<Material, TextureAtlasSprite> spriteGetter,\n                           final ModelState modelState,\n                           final ItemOverrides overrides,\n                           final ResourceLocation modelLocation) {\n\n        var renderTypeHint = context.getRenderTypeHint();\n        var renderTypes = renderTypeHint != null ? context.getRenderType(renderTypeHint) : RenderTypeGroup.EMPTY;\n\n        return new PortableGridBakedModel(\n            Objects.requireNonNull(baker.bake(BASE_CONNECTED_MODEL, modelState, spriteGetter)),\n            getModelBaker(BASE_CONNECTED_MODEL, modelState, baker, spriteGetter),\n            getModelBaker(BASE_DISCONNECTED_MODEL, modelState, baker, spriteGetter),\n            getModelBaker(DISK_MODEL, modelState, baker, spriteGetter),\n            getModelBaker(DISK_NEAR_CAPACITY_MODEL, modelState, baker, spriteGetter),\n            getModelBaker(DISK_FULL_MODEL, modelState, baker, spriteGetter),\n            getModelBaker(DISK_DISCONNECTED_MODEL, modelState, baker, spriteGetter),\n            renderTypes\n        );\n    }\n\n    private Function<Direction, BakedModel> getModelBaker(final ResourceLocation id,\n                                                          final ModelState state,\n                                                          final ModelBaker baker,\n                                                          final Function<Material, TextureAtlasSprite> sg) {\n        return direction -> {\n            final Transformation rotation = new Transformation(null, RenderUtils.getQuaternion(direction), null, null);\n            final ModelState wrappedState = new SimpleModelState(rotation, state.isUvLocked());\n            return baker.bake(id, wrappedState, sg);\n        };\n    }\n}"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/model/baked/CableCoverBakedModel.java",
    "content": "package com.refinedmods.refinedstorage.render.model.baked;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.Cover;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;\nimport com.refinedmods.refinedstorage.block.BaseBlock;\nimport com.refinedmods.refinedstorage.render.ConstantsCable;\nimport com.refinedmods.refinedstorage.render.model.CubeBuilder;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.client.renderer.block.model.BakedQuad;\nimport net.minecraft.client.renderer.texture.TextureAtlas;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.client.resources.model.BakedModel;\nimport net.minecraft.core.Direction;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.util.RandomSource;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.AABB;\nimport net.neoforged.neoforge.client.model.BakedModelWrapper;\nimport net.neoforged.neoforge.client.model.data.ModelData;\nimport org.joml.Vector3f;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\n\npublic class CableCoverBakedModel extends BakedModelWrapper<BakedModel> {\n\n    private static TextureAtlasSprite BORDER_SPRITE;\n\n    public CableCoverBakedModel(BakedModel base) {\n        super(base);\n    }\n\n    private static int getHollowCoverSize(@Nullable BlockState state, Direction coverSide) {\n        if (state == null) {\n            return 6;\n        }\n\n        BaseBlock block = (BaseBlock) state.getBlock();\n        if (block == RSBlocks.CABLE.get()) {\n            return 6;\n        }\n\n        if (block.getDirection() != null && state.getValue(block.getDirection().getProperty()) == coverSide) {\n            if (block == RSBlocks.EXPORTER.get()) {\n                return 6;\n            } else if (block == RSBlocks.EXTERNAL_STORAGE.get() || block == RSBlocks.IMPORTER.get()) {\n                return 3;\n            } else if (block == RSBlocks.CONSTRUCTOR.get() || block == RSBlocks.DESTRUCTOR.get()) { //Removed reader and writer\n                return 2;\n            }\n        }\n\n        return 6;\n    }\n\n    protected static void addCover(List<BakedQuad> quads, @Nullable Cover cover, Direction coverSide, Direction side, RandomSource rand, @Nullable CoverManager manager, BlockState state, boolean handle) {\n        if (cover == null) {\n            return;\n        }\n\n        BlockState coverState = CoverManager.getBlockState(cover.getStack());\n\n        if (coverState == null) {\n            return;\n        }\n\n        boolean hasUp = false, hasDown = false, hasEast = false, hasWest = false;\n\n        if (manager != null) {\n            hasUp = manager.hasCover(Direction.UP);\n            hasDown = manager.hasCover(Direction.DOWN);\n            hasEast = manager.hasCover(Direction.EAST);\n            hasWest = manager.hasCover(Direction.WEST);\n        }\n\n        switch (cover.getType()) {\n            case NORMAL -> addNormalCover(quads, coverState, coverSide, hasUp, hasDown, hasEast, hasWest, handle, rand);\n            case HOLLOW ->\n                addHollowCover(quads, coverState, coverSide, hasUp, hasDown, hasEast, hasWest, getHollowCoverSize(state, coverSide), rand);\n        }\n    }\n\n    private static void addNormalCover(List<BakedQuad> quads, BlockState state, Direction coverSide, boolean hasUp, boolean hasDown, boolean hasEast, boolean hasWest, boolean handle, RandomSource random) {\n        AABB bounds = ConstantsCable.getCoverBounds(coverSide);\n\n        float fromX = (float) bounds.minX * 16;\n        float fromY = (float) bounds.minY * 16;\n        float fromZ = (float) bounds.minZ * 16;\n\n        float toX = (float) bounds.maxX * 16;\n        float toY = (float) bounds.maxY * 16;\n        float toZ = (float) bounds.maxZ * 16;\n\n        if (coverSide == Direction.NORTH) {\n            if (hasWest) {\n                fromX = 2;\n            }\n\n            if (hasEast) {\n                toX = 14;\n            }\n        } else if (coverSide == Direction.SOUTH) {\n            if (hasWest) {\n                fromX = 2;\n            }\n\n            if (hasEast) {\n                toX = 14;\n            }\n        }\n\n        if (coverSide.getAxis() != Direction.Axis.Y) {\n            if (hasDown) {\n                fromY = 2;\n            }\n\n            if (hasUp) {\n                toY = 14;\n            }\n        }\n\n        Vector3f from = new Vector3f(fromX, fromY, fromZ);\n        Vector3f to = new Vector3f(toX, toY, toZ);\n\n        HashMap<Direction, TextureAtlasSprite> spriteCache = new HashMap<>();  //Changed from 1.12: to improve sprite getting for each side\n        quads.addAll(new CubeBuilder().from(from.x(), from.y(), from.z()).to(to.x(), to.y(), to.z()).addFaces(face -> new CubeBuilder.Face(face, spriteCache.computeIfAbsent(face, direction -> RenderUtils.getSprite(Minecraft.getInstance().getBlockRenderer().getBlockModel(state), state, direction, random)))).bake());\n\n        if (handle) {\n            if (BORDER_SPRITE == null) {\n                BORDER_SPRITE = Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(new ResourceLocation(RS.ID, \"block/cable_part_border\"));\n            }\n\n            bounds = ConstantsCable.getHolderBounds(coverSide);\n\n            from = new Vector3f((float) bounds.minX * 16, (float) bounds.minY * 16, (float) bounds.minZ * 16);\n            to = new Vector3f((float) bounds.maxX * 16, (float) bounds.maxY * 16, (float) bounds.maxZ * 16);\n\n            quads.addAll(new CubeBuilder().from(from.x(), from.y(), from.z()).to(to.x(), to.y(), to.z()).addFaces(face -> new CubeBuilder.Face(face, BORDER_SPRITE)).bake());\n        }\n    }\n\n    private static void addHollowCover(List<BakedQuad> quads, BlockState state, Direction coverSide, boolean hasUp, boolean hasDown, boolean hasEast, boolean hasWest, int size, RandomSource random) {\n        AABB bounds = ConstantsCable.getCoverBounds(coverSide);\n\n        float fromX = (float) bounds.minX * 16;\n        float fromY = (float) bounds.minY * 16;\n        float fromZ = (float) bounds.minZ * 16;\n\n        float toX = (float) bounds.maxX * 16;\n        float toY = (float) bounds.maxY * 16;\n        float toZ = (float) bounds.maxZ * 16;\n\n        if (coverSide.getAxis() != Direction.Axis.Y) {\n            if (hasDown) {\n                fromY = 2;\n            }\n\n            if (hasUp) {\n                toY = 14;\n            }\n        }\n\n        // Right\n        if (coverSide == Direction.NORTH) {\n            if (hasWest) {\n                fromX = 2;\n            } else {\n                fromX = 0;\n            }\n\n            toX = size;\n        } else if (coverSide == Direction.SOUTH) {\n            if (hasEast) {\n                toX = 14;\n            } else {\n                toX = 16;\n            }\n\n            fromX = 16F - size;\n        } else if (coverSide == Direction.EAST) {\n            fromZ = 0;\n            toZ = size;\n        } else if (coverSide == Direction.WEST) {\n            fromZ = 16F - size;\n            toZ = 16;\n        } else if (coverSide == Direction.DOWN || coverSide == Direction.UP) {\n            fromZ = 16F - size;\n            toZ = 16;\n        }\n        HashMap<Direction, TextureAtlasSprite> spriteCache = new HashMap<>(); //Changed from 1.12: to improve sprite getting for each side\n        quads.addAll(new CubeBuilder()\n            .from(fromX, fromY, fromZ)\n            .to(toX, toY, toZ)\n            .addFaces(face -> new CubeBuilder.Face(face, spriteCache.computeIfAbsent(face, direction -> RenderUtils.getSprite(Minecraft.getInstance().getBlockRenderer().getBlockModel(state), state, direction, random))))\n            .bake()\n        );\n\n        // Left\n        if (coverSide == Direction.NORTH) {\n            if (hasEast) {\n                toX = 14;\n            } else {\n                toX = 16;\n            }\n\n            fromX = 16F - size;\n        } else if (coverSide == Direction.SOUTH) {\n            if (hasWest) {\n                fromX = 2;\n            } else {\n                fromX = 0;\n            }\n\n            toX = size;\n        } else if (coverSide == Direction.EAST) {\n            fromZ = 16F - size;\n            toZ = 16;\n        } else if (coverSide == Direction.WEST) {\n            fromZ = 0;\n            toZ = size;\n        } else if (coverSide == Direction.DOWN || coverSide == Direction.UP) {\n            fromZ = 0;\n            toZ = size;\n        }\n\n        quads.addAll(new CubeBuilder()\n            .from(fromX, fromY, fromZ)\n            .to(toX, toY, toZ)\n            .addFaces(face -> new CubeBuilder.Face(face, spriteCache.computeIfAbsent(face, direction -> RenderUtils.getSprite(Minecraft.getInstance().getBlockRenderer().getBlockModel(state), state, direction, random))))\n            .bake()\n        );\n\n        // Bottom\n        if (coverSide == Direction.NORTH) {\n            fromX = size;\n            toX = 16F - size;\n\n            if (hasDown) {\n                fromY = 2;\n            } else {\n                fromY = 0;\n            }\n\n            toY = size;\n        } else if (coverSide == Direction.SOUTH) {\n            fromX = size;\n            toX = 16F - size;\n\n            if (hasDown) {\n                fromY = 2;\n            } else {\n                fromY = 0;\n            }\n\n            toY = size;\n        } else if (coverSide == Direction.EAST) {\n            fromZ = size;\n            toZ = 16F - size;\n\n            if (hasDown) {\n                fromY = 2;\n            } else {\n                fromY = 0;\n            }\n\n            toY = size;\n        } else if (coverSide == Direction.WEST) {\n            fromZ = size;\n            toZ = 16F - size;\n\n            if (hasDown) {\n                fromY = 2;\n            } else {\n                fromY = 0;\n            }\n\n            toY = size;\n        } else if (coverSide == Direction.DOWN || coverSide == Direction.UP) {\n            fromZ = size;\n            toZ = 16F - size;\n\n            fromX = 0;\n            toX = size;\n        }\n\n        quads.addAll(new CubeBuilder()\n            .from(fromX, fromY, fromZ)\n            .to(toX, toY, toZ)\n            .addFaces(face -> new CubeBuilder.Face(face, spriteCache.computeIfAbsent(face, direction -> RenderUtils.getSprite(Minecraft.getInstance().getBlockRenderer().getBlockModel(state), state, direction, random))))\n            .bake()\n        );\n\n        // Up\n        if (coverSide == Direction.NORTH) {\n            fromX = size;\n            toX = 16F - size;\n\n            if (hasUp) {\n                toY = 14;\n            } else {\n                toY = 16;\n            }\n\n            fromY = 16F - size;\n        } else if (coverSide == Direction.SOUTH) {\n            fromX = size;\n            toX = 16F - size;\n\n            if (hasUp) {\n                toY = 14;\n            } else {\n                toY = 16;\n            }\n\n            fromY = 16F - size;\n        } else if (coverSide == Direction.EAST) {\n            fromZ = size;\n            toZ = 16F - size;\n\n            if (hasUp) {\n                toY = 14;\n            } else {\n                toY = 16;\n            }\n\n            fromY = 16F - size;\n        } else if (coverSide == Direction.WEST) {\n            fromZ = size;\n            toZ = 16F - size;\n\n            if (hasUp) {\n                toY = 14;\n            } else {\n                toY = 16;\n            }\n\n            fromY = 16F - size;\n        } else if (coverSide == Direction.DOWN || coverSide == Direction.UP) {\n            fromZ = size;\n            toZ = 16F - size;\n\n            fromX = 16F - size;\n            toX = 16;\n        }\n\n        quads.addAll(new CubeBuilder()\n            .from(fromX, fromY, fromZ)\n            .to(toX, toY, toZ)\n            .addFaces(face -> new CubeBuilder.Face(face, spriteCache.computeIfAbsent(face, direction -> RenderUtils.getSprite(Minecraft.getInstance().getBlockRenderer().getBlockModel(state), state, direction, random))))\n            .bake()\n        );\n    }\n\n    @Override\n    public List<BakedQuad> getQuads(@Nullable final BlockState state,\n                                    @Nullable final Direction side,\n                                    @Nonnull final RandomSource rand,\n                                    @Nonnull final ModelData extraData,\n                                    @Nullable final RenderType renderType) {\n        List<BakedQuad> quads = new ArrayList<>(super.getQuads(state, side, rand, extraData, renderType));\n        if (extraData.has(CoverManager.PROPERTY)) {\n            CoverManager manager = extraData.get(CoverManager.PROPERTY);\n            addCover(quads, manager.getCover(Direction.NORTH), Direction.NORTH, side, rand, manager, state, true);\n            addCover(quads, manager.getCover(Direction.SOUTH), Direction.SOUTH, side, rand, manager, state, true);\n            addCover(quads, manager.getCover(Direction.EAST), Direction.EAST, side, rand, manager, state, true);\n            addCover(quads, manager.getCover(Direction.WEST), Direction.WEST, side, rand, manager, state, true);\n            addCover(quads, manager.getCover(Direction.DOWN), Direction.DOWN, side, rand, manager, state, true);\n            addCover(quads, manager.getCover(Direction.UP), Direction.UP, side, rand, manager, state, true);\n        }\n        return quads;\n    }\n}\n\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/model/baked/CableCoverItemBakedModel.java",
    "content": "package com.refinedmods.refinedstorage.render.model.baked;\n\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.cache.CacheLoader;\nimport com.google.common.cache.LoadingCache;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.Cover;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverType;\nimport com.refinedmods.refinedstorage.item.CoverItem;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.client.multiplayer.ClientLevel;\nimport net.minecraft.client.renderer.block.model.BakedQuad;\nimport net.minecraft.client.renderer.block.model.ItemOverrides;\nimport net.minecraft.client.renderer.block.model.ItemTransforms;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.client.resources.model.BakedModel;\nimport net.minecraft.core.Direction;\nimport net.minecraft.util.RandomSource;\nimport net.minecraft.world.entity.LivingEntity;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.state.BlockState;\n\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\n\nimport static com.refinedmods.refinedstorage.render.model.baked.CableCoverBakedModel.addCover;\n\npublic class CableCoverItemBakedModel implements BakedModel {\n    private static final LoadingCache<CacheKey, List<BakedQuad>> CACHE = CacheBuilder.newBuilder().build(new CacheLoader<CacheKey, List<BakedQuad>>() {\n        @Override\n        public List<BakedQuad> load(CacheKey key) {\n            List<BakedQuad> quads = new ArrayList<>();\n            addCover(quads, new Cover(key.stack, key.type), Direction.NORTH, key.side, key.random, null, null, true);\n            return quads;\n        }\n    });\n    private final ItemStack stack;\n    private final CoverType type;\n\n    public CableCoverItemBakedModel(ItemStack stack, CoverType type) {\n        this.stack = stack;\n        this.type = type;\n    }\n\n    @Override\n    public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, RandomSource rand) {\n        if (stack.isEmpty()) {\n            return Collections.emptyList();\n        }\n        CacheKey key = new CacheKey(state, CoverItem.getItem(stack), side, type, rand);\n        return CACHE.getUnchecked(key);\n    }\n\n    @Override\n    public ItemOverrides getOverrides() {\n        return new ItemOverrides() {\n            @Override\n            public BakedModel resolve(BakedModel originalModel, ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int p) {\n                return new CableCoverItemBakedModel(stack, type);\n            }\n        };\n    }\n\n    @Override\n    public List<BakedModel> getRenderPasses(final ItemStack itemStack, final boolean fabulous) {\n        return List.of(this);\n    }\n\n    @Override\n    public boolean useAmbientOcclusion() {\n        return true;\n    }\n\n    @Override\n    public boolean isGui3d() {\n        return true;\n    }\n\n    @Override\n    public boolean isCustomRenderer() {\n        return false;\n    }\n\n    @Override\n    public TextureAtlasSprite getParticleIcon() {\n        return null;\n    }\n\n    @Override\n    public boolean useAmbientOcclusion(BlockState state) {\n        return true;\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public ItemTransforms getTransforms() {\n        return RenderUtils.getDefaultBlockTransforms();\n    }\n\n    @Override\n    public boolean usesBlockLight() {\n        return true;\n    }\n\n    private static class CacheKey {\n        private final BlockState state;\n        private final ItemStack stack;\n        private final Direction side;\n        private final CoverType type;\n        private final RandomSource random;\n\n        CacheKey(BlockState state, ItemStack stack, Direction side, CoverType type, RandomSource rand) {\n            this.state = state;\n            this.stack = stack;\n            this.side = side;\n            this.type = type;\n            this.random = rand;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) {\n                return true;\n            }\n\n            if (o == null || getClass() != o.getClass()) {\n                return false;\n            }\n\n            CableCoverItemBakedModel.CacheKey cacheKey = (CableCoverItemBakedModel.CacheKey) o;\n\n            return cacheKey.type == type && cacheKey.stack.getItem() == stack.getItem() && cacheKey.side == side && Objects.equals(cacheKey.state, state);\n        }\n\n        @Override\n        public int hashCode() {\n            int result = stack.getItem().hashCode();\n            result = 31 * result + (side != null ? side.hashCode() : 0);\n            result = 31 * result + (state != null ? state.hashCode() : 0);\n            result = 31 * result + type.hashCode();\n            return result;\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/model/baked/DiskDriveBakedModel.java",
    "content": "package com.refinedmods.refinedstorage.render.model.baked;\n\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.cache.CacheLoader;\nimport com.google.common.cache.LoadingCache;\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.DiskState;\nimport com.refinedmods.refinedstorage.blockentity.DiskDriveBlockEntity;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.client.renderer.block.model.BakedQuad;\nimport net.minecraft.client.resources.model.BakedModel;\nimport net.minecraft.core.Direction;\nimport net.minecraft.util.RandomSource;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.model.BakedModelWrapper;\nimport net.neoforged.neoforge.client.model.data.ModelData;\nimport org.joml.Vector3f;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.function.BiFunction;\nimport java.util.function.Function;\n\npublic class DiskDriveBakedModel extends BakedModelWrapper<BakedModel> {\n    private final Function<Direction, BakedModel> baseModelBakery;\n    private final BiFunction<Direction, Vector3f, BakedModel> diskModelBakery;\n    private final BiFunction<Direction, Vector3f, BakedModel> diskNearCapacityModelBakery;\n    private final BiFunction<Direction, Vector3f, BakedModel> diskFullModelBakery;\n    private final BiFunction<Direction, Vector3f, BakedModel> diskDisconnectedModelBakery;\n\n    private final LoadingCache<CacheKey, List<BakedQuad>> cache = CacheBuilder.newBuilder().build(new CacheLoader<CacheKey, List<BakedQuad>>() {\n        @Override\n        @SuppressWarnings(\"deprecation\")\n        public List<BakedQuad> load(CacheKey key) {\n            Direction facing = key.state.getValue(RSBlocks.DISK_DRIVE.get().getDirection().getProperty());\n\n            List<BakedQuad> quads = new ArrayList<>();\n            if (key.side != null) {\n                quads = baseModelBakery.apply(facing).getQuads(key.state, key.side, key.random);\n                return quads;\n            }\n\n            int x = 0;\n            int y = 0;\n            for (int i = 0; i < 8; ++i) {\n                if (key.diskState[i] != DiskState.NONE) {\n                    BakedModel diskModel = getDiskModelBakery(key.diskState[i]).apply(facing, getDiskTranslation(x, y));\n                    quads.addAll(diskModel.getQuads(key.state, key.side, key.random));\n                }\n\n                x++;\n                if ((i + 1) % 2 == 0) {\n                    y++;\n                    x = 0;\n                }\n            }\n\n            return quads;\n        }\n\n        private BiFunction<Direction, Vector3f, BakedModel> getDiskModelBakery(DiskState diskState) {\n            return switch (diskState) {\n                case DISCONNECTED -> diskDisconnectedModelBakery;\n                case NEAR_CAPACITY -> diskNearCapacityModelBakery;\n                case FULL -> diskFullModelBakery;\n                default -> diskModelBakery;\n            };\n        }\n\n        private Vector3f getDiskTranslation(int x, int y) {\n            Vector3f translation = new Vector3f();\n            translation.add(((2F / 16F) + ((float) x * 7F) / 16F) * -1, 0, 0); // Add to X\n            translation.add(0, -((2F / 16F) + ((float) y * 3F) / 16F), 0); // Remove from Y\n            return translation;\n        }\n    });\n\n    public DiskDriveBakedModel(BakedModel base, Function<Direction, BakedModel> baseModelBakery, BiFunction<Direction, Vector3f, BakedModel> diskModelBakery, BiFunction<Direction, Vector3f, BakedModel> diskNearCapacityModelBakery, BiFunction<Direction, Vector3f, BakedModel> diskFullModelBakery, BiFunction<Direction, Vector3f, BakedModel> diskDisconnectedModelBakery) {\n        super(base);\n        this.baseModelBakery = baseModelBakery;\n        this.diskModelBakery = diskModelBakery;\n        this.diskNearCapacityModelBakery = diskNearCapacityModelBakery;\n        this.diskFullModelBakery = diskFullModelBakery;\n        this.diskDisconnectedModelBakery = diskDisconnectedModelBakery;\n    }\n\n    @Nonnull\n    @Override\n    public List<BakedQuad> getQuads(@Nullable final BlockState state,\n                                    @Nullable final Direction side,\n                                    @Nonnull final RandomSource rand,\n                                    @Nonnull final ModelData extraData,\n                                    @Nullable final RenderType renderType) {\n        DiskState[] diskState = extraData.get(DiskDriveBlockEntity.DISK_STATE_PROPERTY);\n\n        if (diskState == null) {\n            return super.getQuads(state, side, rand, extraData, renderType);\n        }\n\n        CacheKey key = new CacheKey(state, side, diskState, rand);\n\n        return cache.getUnchecked(key);\n    }\n\n    private static class CacheKey {\n        private final BlockState state;\n        private final Direction side;\n        private final DiskState[] diskState;\n        private final RandomSource random;\n\n        CacheKey(BlockState state, @Nullable Direction side, DiskState[] diskState, RandomSource random) {\n            this.state = state;\n            this.side = side;\n            this.diskState = diskState;\n            this.random = random;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) {\n                return true;\n            }\n\n            if (o == null || getClass() != o.getClass()) {\n                return false;\n            }\n\n            CacheKey cacheKey = (CacheKey) o;\n\n            if (!state.equals(cacheKey.state)) {\n                return false;\n            }\n\n            if (side != cacheKey.side) {\n                return false;\n            }\n\n            return Arrays.equals(diskState, cacheKey.diskState);\n        }\n\n        @Override\n        public int hashCode() {\n            int result = state.hashCode();\n            result = 31 * result + (side != null ? side.hashCode() : 0);\n            result = 31 * result + Arrays.hashCode(diskState);\n            return result;\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/model/baked/DiskManipulatorBakedModel.java",
    "content": "package com.refinedmods.refinedstorage.render.model.baked;\n\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.cache.CacheLoader;\nimport com.google.common.cache.LoadingCache;\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.DiskState;\nimport com.refinedmods.refinedstorage.block.DiskManipulatorBlock;\nimport com.refinedmods.refinedstorage.block.NetworkNodeBlock;\nimport com.refinedmods.refinedstorage.blockentity.DiskManipulatorBlockEntity;\nimport com.refinedmods.refinedstorage.util.ColorMap;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.client.renderer.block.model.BakedQuad;\nimport net.minecraft.client.resources.model.BakedModel;\nimport net.minecraft.core.Direction;\nimport net.minecraft.util.RandomSource;\nimport net.minecraft.world.item.DyeColor;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.ChunkRenderTypeSet;\nimport net.neoforged.neoforge.client.RenderTypeGroup;\nimport net.neoforged.neoforge.client.model.BakedModelWrapper;\nimport net.neoforged.neoforge.client.model.data.ModelData;\nimport org.joml.Vector3f;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.function.BiFunction;\nimport java.util.function.Function;\n\npublic class DiskManipulatorBakedModel extends BakedModelWrapper<BakedModel> {\n    private final BiFunction<Direction, DyeColor, BakedModel> baseConnectedModelBakery;\n    private final Function<Direction, BakedModel> baseDisconnectedModelBakery;\n    private final BiFunction<Direction, Vector3f, BakedModel> diskModelBakery;\n    private final BiFunction<Direction, Vector3f, BakedModel> diskNearCapacityModelBakery;\n    private final BiFunction<Direction, Vector3f, BakedModel> diskFullModelBakery;\n    private final BiFunction<Direction, Vector3f, BakedModel> diskDisconnectedModelBakery;\n\n    private final RenderTypeGroup renderType;\n\n    private final LoadingCache<CacheKey, List<BakedQuad>> cache = CacheBuilder.newBuilder().build(new CacheLoader<CacheKey, List<BakedQuad>>() {\n        @Override\n        @SuppressWarnings(\"deprecation\")\n        public List<BakedQuad> load(CacheKey key) {\n            Direction facing = key.state.getValue(RSBlocks.DISK_MANIPULATOR.get(ColorMap.DEFAULT_COLOR).get().getDirection().getProperty());\n            boolean connected = key.state.getValue(NetworkNodeBlock.CONNECTED);\n            List<BakedQuad> quads;\n            if (connected) {\n                quads = new ArrayList<>(baseConnectedModelBakery.apply(facing, key.color).getQuads(key.state, key.side, key.random));\n            } else {\n                quads = new ArrayList<>(baseDisconnectedModelBakery.apply(facing).getQuads(key.state, key.side, key.random));\n            }\n\n            int x = 0;\n            int y = 0;\n            for (int i = 0; i < 6; ++i) {\n                if (key.diskState[i] != DiskState.NONE) {\n                    BakedModel diskModel = getDiskModelBakery(key.diskState[i]).apply(facing, getDiskTranslation(facing, x, y));\n                    quads.addAll(diskModel.getQuads(key.state, key.side, key.random));\n                }\n\n                y++;\n                if ((i + 1) % 3 == 0) {\n                    x++;\n                    y = 0;\n                }\n            }\n\n            return quads;\n        }\n\n        private BiFunction<Direction, Vector3f, BakedModel> getDiskModelBakery(DiskState diskState) {\n            return switch (diskState) {\n                case DISCONNECTED -> diskDisconnectedModelBakery;\n                case NEAR_CAPACITY -> diskNearCapacityModelBakery;\n                case FULL -> diskFullModelBakery;\n                default -> diskModelBakery;\n            };\n        }\n\n        private Vector3f getDiskTranslation(Direction facing, int x, int y) {\n            Vector3f translation = new Vector3f();\n\n            translation.add((2F / 16F + ((float) x * 7F) / 16F) * -1, 0, 0); // Add to X\n            translation.add(0, -((6F / 16F) + (3F * y) / 16F), 0); // Remove from Y\n\n            return translation;\n        }\n    });\n\n    public DiskManipulatorBakedModel(BakedModel originalModel, BiFunction<Direction, DyeColor, BakedModel> baseConnectedModelBakery, Function<Direction, BakedModel> baseDisconnectedModelBakery, BiFunction<Direction, Vector3f, BakedModel> diskModelBakery, BiFunction<Direction, Vector3f, BakedModel> diskNearCapacityModelBakery, BiFunction<Direction, Vector3f, BakedModel> diskFullModelBakery, BiFunction<Direction, Vector3f, BakedModel> diskDisconnectedModelBakery, RenderTypeGroup renderTypes) {\n        super(originalModel);\n        this.baseConnectedModelBakery = baseConnectedModelBakery;\n        this.baseDisconnectedModelBakery = baseDisconnectedModelBakery;\n        this.diskModelBakery = diskModelBakery;\n        this.diskNearCapacityModelBakery = diskNearCapacityModelBakery;\n        this.diskFullModelBakery = diskFullModelBakery;\n        this.diskDisconnectedModelBakery = diskDisconnectedModelBakery;\n        this.renderType = renderTypes;\n    }\n\n    @Override\n    public ChunkRenderTypeSet getRenderTypes(BlockState state, RandomSource rand, ModelData data) {\n        return ChunkRenderTypeSet.of(renderType.block());\n    }\n\n    @Override\n    @Nonnull\n    public List<BakedQuad> getQuads(@Nullable final BlockState state,\n                                    @Nullable final Direction side,\n                                    @Nonnull final RandomSource rand,\n                                    @Nonnull final ModelData extraData,\n                                    @Nullable final RenderType renderType) {\n        DiskState[] diskState = extraData.get(DiskManipulatorBlockEntity.DISK_STATE_PROPERTY);\n\n        var color = RSBlocks.DISK_MANIPULATOR.getColorFromObject((DiskManipulatorBlock) state.getBlock());\n\n        if (diskState == null) {\n            return super.getQuads(state, side, rand, extraData, renderType);\n        }\n        CacheKey key = new CacheKey(state, side, diskState, rand, color);\n        return cache.getUnchecked(key);\n    }\n\n    private static class CacheKey {\n        private final BlockState state;\n        private final Direction side;\n        private final DiskState[] diskState;\n        private final RandomSource random;\n        private final DyeColor color;\n\n        CacheKey(BlockState state, @Nullable Direction side, DiskState[] diskState, RandomSource random, DyeColor color) {\n            this.state = state;\n            this.side = side;\n            this.diskState = diskState;\n            this.random = random;\n            this.color = color;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) {\n                return true;\n            }\n\n            if (o == null || getClass() != o.getClass()) {\n                return false;\n            }\n\n            CacheKey cacheKey = (CacheKey) o;\n\n            if (!state.equals(cacheKey.state)) {\n                return false;\n            }\n\n            if (side != cacheKey.side) {\n                return false;\n            }\n\n            if (color != cacheKey.color) {\n                return false;\n            }\n\n            return Arrays.equals(diskState, cacheKey.diskState);\n        }\n\n        @Override\n        public int hashCode() {\n            int result = state.hashCode();\n            result = 31 * result + (side != null ? side.hashCode() : 0);\n            result = 31 * result + Arrays.hashCode(diskState);\n            return result;\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/model/baked/PatternBakedModel.java",
    "content": "package com.refinedmods.refinedstorage.render.model.baked;\n\nimport com.google.common.collect.ImmutableList;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternRenderHandler;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.item.PatternItem;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.multiplayer.ClientLevel;\nimport net.minecraft.client.renderer.block.model.ItemOverrides;\nimport net.minecraft.client.resources.model.BakedModel;\nimport net.minecraft.world.entity.LivingEntity;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.client.model.BakedModelWrapper;\nimport javax.annotation.Nullable;\n\npublic class PatternBakedModel extends BakedModelWrapper<BakedModel> {\n    public PatternBakedModel(BakedModel base) {\n        super(base);\n    }\n\n    public static boolean canDisplayOutput(ItemStack patternStack, ICraftingPattern pattern) {\n        if (pattern.isValid() && pattern.getOutputs().size() == 1) {\n            for (ICraftingPatternRenderHandler renderHandler : API.instance().getPatternRenderHandlers()) {\n                if (renderHandler.canRenderOutput(patternStack)) {\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public ItemOverrides getOverrides() {\n        return new ItemOverrides() {\n            @Nullable\n            @Override\n            public BakedModel resolve(BakedModel model, ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int p) {\n                if (entity != null) {\n                    ICraftingPattern pattern = PatternItem.fromCache(entity.level(), stack);\n\n                    if (canDisplayOutput(stack, pattern)) {\n                        ItemStack outputToRender = pattern.getOutputs().get(0);\n\n                        return Minecraft.getInstance().getItemRenderer().getModel(outputToRender, level, entity, p);\n                    }\n                }\n\n                return super.resolve(model, stack, level, entity, p);\n            }\n\n            @Override\n            public ImmutableList<BakedOverride> getOverrides() {\n                return originalModel.getOverrides().getOverrides();\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/model/baked/PortableGridBakedModel.java",
    "content": "package com.refinedmods.refinedstorage.render.model.baked;\n\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.cache.CacheLoader;\nimport com.google.common.cache.LoadingCache;\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.block.PortableGridBlock;\nimport com.refinedmods.refinedstorage.blockentity.grid.portable.PortableGrid;\nimport com.refinedmods.refinedstorage.blockentity.grid.portable.PortableGridDiskState;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport net.minecraft.client.multiplayer.ClientLevel;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.client.renderer.block.model.BakedQuad;\nimport net.minecraft.client.renderer.block.model.ItemOverrides;\nimport net.minecraft.client.resources.model.BakedModel;\nimport net.minecraft.core.Direction;\nimport net.minecraft.util.RandomSource;\nimport net.minecraft.world.entity.LivingEntity;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.ChunkRenderTypeSet;\nimport net.neoforged.neoforge.client.RenderTypeGroup;\nimport net.neoforged.neoforge.client.model.BakedModelWrapper;\nimport net.neoforged.neoforge.client.model.data.ModelData;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.function.Function;\n\npublic class PortableGridBakedModel extends BakedModelWrapper<BakedModel> {\n    private final Function<Direction, BakedModel> baseConnectedModelBakery;\n    private final Function<Direction, BakedModel> baseDisconnectedModelBakery;\n    private final Function<Direction, BakedModel> diskModelBakery;\n    private final Function<Direction, BakedModel> diskNearCapacityModelBakery;\n    private final Function<Direction, BakedModel> diskFullModelBakery;\n    private final Function<Direction, BakedModel> diskDisconnectedModelBakery;\n\n    private final RenderTypeGroup renderTypes;\n\n    private final CustomItemOverrideList itemOverrideList = new CustomItemOverrideList();\n\n    private final LoadingCache<CacheKey, List<BakedQuad>> cache = CacheBuilder.newBuilder().build(new CacheLoader<CacheKey, List<BakedQuad>>() {\n        @Override\n        @SuppressWarnings(\"deprecation\")\n        public List<BakedQuad> load(@Nonnull CacheKey key) {\n            Direction direction = key.state.getValue(RSBlocks.PORTABLE_GRID.get().getDirection().getProperty());\n            boolean active = key.state.getValue(PortableGridBlock.ACTIVE);\n            PortableGridDiskState diskState = key.state.getValue(PortableGridBlock.DISK_STATE);\n\n            List<BakedQuad> quads = new ArrayList<>((active ? baseConnectedModelBakery : baseDisconnectedModelBakery)\n                .apply(direction).getQuads(key.state, key.side, key.random));\n\n            Function<Direction, BakedModel> diskModel = getDiskModelBakery(diskState);\n            if (diskModel != null) {\n                quads.addAll(diskModel.apply(direction).getQuads(key.state, key.side, key.random));\n            }\n\n            return quads;\n        }\n    });\n\n    public PortableGridBakedModel(BakedModel baseModel, Function<Direction, BakedModel> baseConnectedModelBakery, Function<Direction, BakedModel> baseDisconnectedModelBakery, Function<Direction, BakedModel> diskModelBakery, Function<Direction, BakedModel> diskNearCapacityModelBakery, Function<Direction, BakedModel> diskFullModelBakery, Function<Direction, BakedModel> diskDisconnectedModelBakery, RenderTypeGroup renderTypes) {\n        super(baseModel);\n        this.baseConnectedModelBakery = baseConnectedModelBakery;\n        this.baseDisconnectedModelBakery = baseDisconnectedModelBakery;\n        this.diskModelBakery = diskModelBakery;\n        this.diskNearCapacityModelBakery = diskNearCapacityModelBakery;\n        this.diskFullModelBakery = diskFullModelBakery;\n        this.diskDisconnectedModelBakery = diskDisconnectedModelBakery;\n        this.renderTypes = renderTypes;\n    }\n\n    @Nullable\n    private Function<Direction, BakedModel> getDiskModelBakery(PortableGridDiskState state) {\n        return switch (state) {\n            case NORMAL -> diskModelBakery;\n            case NEAR_CAPACITY -> diskNearCapacityModelBakery;\n            case FULL -> diskFullModelBakery;\n            case DISCONNECTED -> diskDisconnectedModelBakery;\n            case NONE -> null;\n        };\n    }\n\n    @Override\n    public ChunkRenderTypeSet getRenderTypes(BlockState state, RandomSource rand, ModelData data) {\n        return ChunkRenderTypeSet.of(renderTypes.block());\n    }\n\n    @Override\n    public ItemOverrides getOverrides() {\n        return itemOverrideList;\n    }\n\n    @Override\n    public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, RandomSource rand, ModelData extraData, @Nullable RenderType renderType) {\n        if (state != null) {\n            return cache.getUnchecked(new CacheKey(state, side, rand));\n        }\n        return super.getQuads(state, side, rand, extraData, renderType);\n    }\n\n    private static class CacheKey {\n        private final BlockState state;\n        private final Direction side;\n        private final RandomSource random;\n\n        public CacheKey(BlockState state, Direction side, RandomSource random) {\n            this.state = state;\n            this.side = side;\n            this.random = random;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) return true;\n            if (o == null || getClass() != o.getClass()) return false;\n            CacheKey cacheKey = (CacheKey) o;\n            return state.equals(cacheKey.state) &&\n                side == cacheKey.side &&\n                random.equals(cacheKey.random);\n        }\n\n        @Override\n        public int hashCode() {\n            return Objects.hash(state, side, random);\n        }\n    }\n\n    private class CustomItemOverrideList extends ItemOverrides {\n        @Nullable\n        @Override\n        public BakedModel resolve(BakedModel model, ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int p) {\n            PortableGrid portableGrid = new PortableGrid(null, stack, new PlayerSlot(-1));\n\n            Function<Direction, BakedModel> diskModelBakery = getDiskModelBakery(portableGrid.getDiskState());\n            BakedModel diskModel = diskModelBakery == null ? null : diskModelBakery.apply(Direction.NORTH);\n\n            if (portableGrid.isGridActive()) {\n                return new PortableGridItemBakedModel(\n                    baseConnectedModelBakery.apply(Direction.NORTH),\n                    diskModel\n                );\n            } else {\n                return new PortableGridItemBakedModel(\n                    baseDisconnectedModelBakery.apply(Direction.NORTH),\n                    diskModel\n                );\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/model/baked/PortableGridItemBakedModel.java",
    "content": "package com.refinedmods.refinedstorage.render.model.baked;\n\nimport net.minecraft.client.renderer.block.model.BakedQuad;\nimport net.minecraft.client.renderer.block.model.ItemOverrides;\nimport net.minecraft.client.resources.model.BakedModel;\nimport net.minecraft.core.Direction;\nimport net.minecraft.util.RandomSource;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.model.BakedModelWrapper;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class PortableGridItemBakedModel extends BakedModelWrapper<BakedModel> {\n    @Nullable\n    private final BakedModel disk;\n\n    public PortableGridItemBakedModel(BakedModel base, @Nullable BakedModel disk) {\n        super(base);\n        this.disk = disk;\n    }\n\n    @Override\n    public ItemOverrides getOverrides() {\n        return ItemOverrides.EMPTY;\n    }\n\n    @Override\n    @Nonnull\n    @SuppressWarnings(\"deprecation\")\n    public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull RandomSource rand) {\n        List<BakedQuad> quads = new ArrayList<>(super.getQuads(state, side, rand));\n\n        if (disk != null) {\n            quads.addAll(disk.getQuads(state, side, rand));\n        }\n\n        return quads;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/resourcepack/RSResourcePackSection.java",
    "content": "package com.refinedmods.refinedstorage.render.resourcepack;\n\npublic class RSResourcePackSection {\n    public static final RSResourcePackSectionDeserializer DESERIALIZER = new RSResourcePackSectionDeserializer();\n\n    private final int primaryColor;\n    private final int secondaryColor;\n\n    public RSResourcePackSection(int primaryColor, int secondaryColor) {\n        this.primaryColor = primaryColor;\n        this.secondaryColor = secondaryColor;\n    }\n\n    public int getPrimaryColor() {\n        return primaryColor;\n    }\n\n    public int getSecondaryColor() {\n        return secondaryColor;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/resourcepack/RSResourcePackSectionDeserializer.java",
    "content": "package com.refinedmods.refinedstorage.render.resourcepack;\n\nimport com.google.gson.JsonObject;\nimport net.minecraft.server.packs.metadata.MetadataSectionSerializer;\n\npublic class RSResourcePackSectionDeserializer implements MetadataSectionSerializer<RSResourcePackSection> {\n    @Override\n    public String getMetadataSectionName() {\n        return \"refinedstorage\";\n    }\n\n    @Override\n    public RSResourcePackSection fromJson(JsonObject json) {\n        int primaryColor = -1;\n        int secondaryColor = -1;\n\n        if (json.has(\"primary_color\")) {\n            primaryColor = json.getAsJsonPrimitive(\"primary_color\").getAsInt();\n        }\n\n        if (json.has(\"secondary_color\")) {\n            secondaryColor = json.getAsJsonPrimitive(\"secondary_color\").getAsInt();\n        }\n\n        return new RSResourcePackSection(primaryColor, secondaryColor);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/render/resourcepack/ResourcePackListener.java",
    "content": "package com.refinedmods.refinedstorage.render.resourcepack;\n\nimport com.refinedmods.refinedstorage.render.RenderSettings;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.server.packs.repository.Pack;\nimport net.minecraft.server.packs.resources.ResourceManager;\nimport net.minecraft.server.packs.resources.SimplePreparableReloadListener;\nimport net.minecraft.util.profiling.ProfilerFiller;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\n\nimport javax.annotation.Nullable;\nimport java.io.IOException;\n\npublic class ResourcePackListener extends SimplePreparableReloadListener<RSResourcePackSection> {\n    private final Logger logger = LogManager.getLogger(getClass());\n\n    @Override\n    protected RSResourcePackSection prepare(ResourceManager resourceManager, ProfilerFiller profiler) {\n        for (Pack info : Minecraft.getInstance().getResourcePackRepository().getSelectedPacks()) {\n            try {\n                RSResourcePackSection section = info.open().getMetadataSection(RSResourcePackSection.DESERIALIZER);\n\n                if (section != null) {\n                    return section;\n                }\n            } catch (IOException e) {\n                logger.error(\"Could not read Refined Storage resource pack section\", e);\n            }\n        }\n\n        return null;\n    }\n\n    @Override\n    protected void apply(@Nullable RSResourcePackSection section, ResourceManager resourceManager, ProfilerFiller profiler) {\n        if (section != null) {\n            RenderSettings.INSTANCE.setColors(section.getPrimaryColor(), section.getSecondaryColor());\n        } else {\n            RenderSettings.INSTANCE.setColors(-1, -1);\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/AmountSpecifyingScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.render.RenderSettings;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.gui.components.Button;\nimport net.minecraft.client.gui.components.EditBox;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport org.apache.commons.lang3.tuple.Pair;\nimport org.lwjgl.glfw.GLFW;\n\npublic abstract class AmountSpecifyingScreen<T extends AbstractContainerMenu> extends BaseScreen<T> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/amount_specifying.png\");\n\n    private final BaseScreen<T> parent;\n\n    protected EditBox amountField;\n    protected Button okButton;\n    protected Button cancelButton;\n\n    protected AmountSpecifyingScreen(BaseScreen<T> parent, T container, int width, int height, Inventory playerInventory, Component title) {\n        super(container, width, height, playerInventory, title);\n\n        this.parent = parent;\n    }\n\n    protected abstract Component getOkButtonText();\n\n    protected ResourceLocation getTexture() {\n        return TEXTURE;\n    }\n\n    protected abstract int[] getIncrements();\n\n    protected abstract int getDefaultAmount();\n\n    protected abstract boolean canAmountGoNegative();\n\n    protected abstract int getMaxAmount();\n\n    protected Pair<Integer, Integer> getAmountPos() {\n        return Pair.of(7 + 2, 50 + 1);\n    }\n\n    protected Pair<Integer, Integer> getOkCancelPos() {\n        return Pair.of(114, 33);\n    }\n\n    protected int getOkCancelButtonWidth() {\n        return 50;\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        Pair<Integer, Integer> pos = getOkCancelPos();\n\n        okButton = addButton(x + pos.getLeft(), y + pos.getRight(), getOkCancelButtonWidth(), 20, getOkButtonText(), true, true, btn -> onOkButtonPressed(hasShiftDown()));\n        cancelButton = addButton(x + pos.getLeft(), y + pos.getRight() + 24, getOkCancelButtonWidth(), 20, Component.translatable(\"gui.cancel\"), true, true, btn -> close());\n\n        amountField = new EditBox(font, x + getAmountPos().getLeft(), y + getAmountPos().getRight(), 69 - 6, font.lineHeight, Component.literal(\"\"));\n        amountField.setBordered(false);\n        amountField.setVisible(true);\n        amountField.setValue(String.valueOf(getDefaultAmount()));\n        amountField.setTextColor(RenderSettings.INSTANCE.getSecondaryColor());\n        amountField.setCanLoseFocus(false);\n        amountField.setFocused(true);\n        amountField.setResponder(text -> {\n            int amount = 0;\n            try {\n                amount = Integer.parseInt(amountField.getValue());\n            } catch (NumberFormatException e) {\n                // NO OP\n            }\n\n            if (amount > getMaxAmount()) {\n                amountField.setValue(String.valueOf(getMaxAmount()));\n            }\n        });\n\n        addRenderableWidget(amountField);\n\n        setFocused(amountField);\n\n        int[] increments = getIncrements();\n\n        int xx = 7;\n        int width = 30;\n\n        for (int i = 0; i < 3; ++i) {\n            int increment = increments[i];\n\n            Component text = Component.literal(\"+\" + increment);\n            if (text.getString().equals(\"+1000\")) {\n                text = Component.literal(\"+1B\");\n            }\n\n            addButton(x + xx, y + 20, width, 20, text, true, true, btn -> onIncrementButtonClicked(increment));\n\n            xx += width + 3;\n        }\n\n        xx = 7;\n\n        for (int i = 0; i < 3; ++i) {\n            int increment = increments[i];\n\n            Component text = Component.literal(\"-\" + increment);\n            if (text.getString().equals(\"-1000\")) {\n                text = Component.literal(\"-1B\");\n            }\n\n            addButton(x + xx, y + imageHeight - 20 - 7, width, 20, text, true, true, btn -> onIncrementButtonClicked(-increment));\n\n            xx += width + 3;\n        }\n    }\n\n    @Override\n    public boolean keyPressed(int key, int scanCode, int modifiers) {\n        if (key == GLFW.GLFW_KEY_ESCAPE) {\n            close();\n\n            return true;\n        }\n\n        if ((key == GLFW.GLFW_KEY_ENTER || key == GLFW.GLFW_KEY_KP_ENTER) && amountField.isFocused()) {\n            onOkButtonPressed(hasShiftDown());\n\n            return true;\n        }\n\n        if (amountField.keyPressed(key, scanCode, modifiers)) {\n            return true;\n        }\n\n        return super.keyPressed(key, scanCode, modifiers);\n    }\n\n    private void onIncrementButtonClicked(int increment) {\n        int oldAmount = 0;\n\n        try {\n            oldAmount = Integer.parseInt(amountField.getValue());\n        } catch (NumberFormatException e) {\n            // NO OP\n        }\n\n        int newAmount = increment;\n\n        if (!canAmountGoNegative()) {\n            newAmount = Math.max(1, ((oldAmount == 1 && newAmount != 1) ? 0 : oldAmount) + newAmount);\n        } else {\n            newAmount = oldAmount + newAmount;\n        }\n\n        if (newAmount > getMaxAmount()) {\n            newAmount = getMaxAmount();\n        }\n\n        amountField.setValue(String.valueOf(newAmount));\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        // NO OP\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        graphics.blit(getTexture(), x, y, 0, 0, imageWidth, imageHeight);\n        amountField.render(graphics, 0, 0, 0);\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, title.getString());\n    }\n\n    protected void onOkButtonPressed(boolean shiftDown) {\n        // NO OP\n    }\n\n    @Override\n    public boolean mouseScrolled(double x, double y, double z, double delta) {\n        if (delta > 0) {\n            onIncrementButtonClicked(1);\n        } else {\n            onIncrementButtonClicked(-1);\n        }\n\n        return super.mouseScrolled(x, y, z, delta);\n    }\n\n    public void close() {\n        minecraft.setScreen(parent);\n    }\n\n    public BaseScreen<T> getParent() {\n        return parent;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/BaseScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.mojang.blaze3d.platform.InputConstants;\nimport com.mojang.blaze3d.systems.RenderSystem;\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.container.slot.filter.FilterSlot;\nimport com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot;\nimport com.refinedmods.refinedstorage.render.FluidRenderer;\nimport com.refinedmods.refinedstorage.render.RenderSettings;\nimport com.refinedmods.refinedstorage.screen.grid.AlternativesScreen;\nimport com.refinedmods.refinedstorage.screen.widget.SmallCheckboxWidget;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.SideButton;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.client.KeyMapping;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.gui.components.Button;\nimport net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.minecraft.world.inventory.ClickType;\nimport net.minecraft.world.inventory.Slot;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\nimport org.lwjgl.opengl.GL11;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.*;\nimport java.util.function.Consumer;\nimport java.util.stream.Collectors;\n\npublic abstract class BaseScreen<T extends AbstractContainerMenu> extends AbstractContainerScreen<T> {\n    public static final ResourceLocation ICONS_TEXTURE = new ResourceLocation(RS.ID, \"textures/icons.png\");\n\n    private static final int Z_LEVEL_QTY = 300;\n    private static final Map<Class<?>, Queue<Consumer<?>>> ACTIONS = new HashMap<>();\n\n    private static final Component ALTERNATIVES_TEXT = Component.translatable(\"gui.refinedstorage.alternatives\");\n    protected final Inventory inventory;\n    private final List<SideButton> sideButtons = new ArrayList<>();\n    private final Logger logger = LogManager.getLogger(getClass());\n    private int sideButtonY;\n\n    protected BaseScreen(T containerMenu, int xSize, int ySize, Inventory inventory, Component title) {\n        super(containerMenu, inventory, title);\n\n        this.imageWidth = xSize;\n        this.imageHeight = ySize;\n        this.inventory = inventory;\n    }\n\n    public static boolean isKeyDown(KeyMapping keybinding) {\n        return !keybinding.isUnbound() && InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), keybinding.getKey().getValue()) &&\n            keybinding.getKeyConflictContext().isActive() &&\n            keybinding.getKeyModifier().isActive(keybinding.getKeyConflictContext());\n    }\n\n    public static <T> void executeLater(Class<T> clazz, Consumer<T> callback) {\n        ACTIONS.computeIfAbsent(clazz, key -> new ArrayDeque<>()).add(callback);\n    }\n\n    public static void executeLater(Consumer<AbstractContainerScreen> callback) {\n        executeLater(AbstractContainerScreen.class, callback);\n    }\n\n    public void runActions() {\n        runActions(getClass());\n        runActions(AbstractContainerScreen.class);\n    }\n\n    private void runActions(Class<?> clazz) {\n        Queue<Consumer<?>> queue = ACTIONS.get(clazz);\n\n        if (queue != null && !queue.isEmpty()) {\n            Consumer callback;\n            while ((callback = queue.poll()) != null) {\n                callback.accept(this);\n            }\n        }\n    }\n\n    @Override\n    public void init() {\n        onPreInit();\n\n        super.init();\n\n        // TODO: what about craft tweaker buttons?\n        this.clearWidgets();\n\n        sideButtonY = 6;\n        sideButtons.clear();\n\n        onPostInit(leftPos, topPos);\n\n        runActions();\n    }\n\n    @Override\n    protected void containerTick() {\n        super.containerTick();\n        runActions();\n        tick(leftPos, topPos);\n    }\n\n    @Override\n    public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {\n        renderBackground(graphics, mouseX, mouseY, partialTicks);\n\n        super.render(graphics, mouseX, mouseY, partialTicks);\n\n        renderTooltip(graphics, mouseX, mouseY);\n    }\n\n    @Override\n    protected void renderBg(GuiGraphics graphics, float renderPartialTicks, int mouseX, int mouseY) {\n        RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);\n\n        renderBackground(graphics, leftPos, topPos, mouseX, mouseY);\n\n        for (int i = 0; i < this.menu.slots.size(); ++i) {\n            Slot slot = menu.slots.get(i);\n\n            if (slot.isActive() && slot instanceof FluidFilterSlot) {\n                FluidStack stack = ((FluidFilterSlot) slot).getFluidInventory().getFluid(slot.getSlotIndex());\n\n                if (!stack.isEmpty()) {\n                    FluidRenderer.INSTANCE.render(graphics, leftPos + slot.x, topPos + slot.y, stack);\n\n                    if (((FluidFilterSlot) slot).isSizeAllowed()) {\n                        renderQuantity(graphics, leftPos + slot.x, topPos + slot.y, API.instance().getQuantityFormatter().formatInBucketForm(stack.getAmount()), RenderSettings.INSTANCE.getSecondaryColor());\n\n                        GL11.glDisable(GL11.GL_LIGHTING);\n                    }\n                }\n            }\n        }\n    }\n\n    @Override\n    protected void renderLabels(GuiGraphics graphics, int mouseX, int mouseY) {\n        RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);\n\n        mouseX -= leftPos;\n        mouseY -= topPos;\n\n        renderForeground(graphics, mouseX, mouseY);\n\n        for (int i = 0; i < this.menu.slots.size(); ++i) {\n            Slot slot = menu.slots.get(i);\n\n            if (slot.isActive() && slot instanceof FluidFilterSlot) {\n                FluidStack stack = ((FluidFilterSlot) slot).getFluidInventory().getFluid(slot.getSlotIndex());\n\n                if (!stack.isEmpty() && RenderUtils.inBounds(slot.x, slot.y, 17, 17, mouseX, mouseY)) {\n                    renderTooltip(graphics, mouseX, mouseY, stack.getDisplayName().getString());\n                }\n            }\n        }\n    }\n\n    @Override\n    protected void slotClicked(Slot slot, int slotId, int mouseButton, ClickType type) {\n        boolean valid = type != ClickType.QUICK_MOVE && minecraft.player.containerMenu.getCarried().isEmpty();\n\n        if (valid && slot instanceof FilterSlot && slot.isActive() && ((FilterSlot) slot).isSizeAllowed()) {\n            if (!slot.getItem().isEmpty()) {\n                if (((FilterSlot) slot).isAlternativesAllowed() && hasControlDown()) {\n                    minecraft.setScreen(new AlternativesScreen(\n                        this,\n                        minecraft.player,\n                        ALTERNATIVES_TEXT,\n                        slot.getItem(),\n                        slot.getSlotIndex()\n                    ));\n                } else {\n                    minecraft.setScreen(new ItemAmountScreen(\n                        this,\n                        minecraft.player,\n                        slot.index,\n                        slot.getItem(),\n                        Math.min(slot.getMaxStackSize(), slot.getItem().getMaxStackSize()),\n                        ((FilterSlot) slot).isAlternativesAllowed() ? (parent -> new AlternativesScreen(\n                            parent,\n                            minecraft.player,\n                            ALTERNATIVES_TEXT,\n                            slot.getItem(),\n                            slot.getSlotIndex()\n                        )) : null\n                    ));\n                }\n            }\n        } else if (valid && slot instanceof FluidFilterSlot && slot.isActive() && ((FluidFilterSlot) slot).isSizeAllowed()) {\n            FluidStack stack = ((FluidFilterSlot) slot).getFluidInventory().getFluid(slot.getSlotIndex());\n\n            if (!stack.isEmpty()) {\n                if (((FluidFilterSlot) slot).isAlternativesAllowed() && hasControlDown()) {\n                    minecraft.setScreen(new AlternativesScreen(\n                        this,\n                        minecraft.player,\n                        ALTERNATIVES_TEXT,\n                        stack,\n                        slot.getSlotIndex()\n                    ));\n                } else {\n                    minecraft.setScreen(new FluidAmountScreen(\n                        this,\n                        minecraft.player,\n                        slot.index,\n                        stack,\n                        ((FluidFilterSlot) slot).getFluidInventory().getMaxAmount(),\n                        ((FluidFilterSlot) slot).isAlternativesAllowed() ? (parent -> new AlternativesScreen(\n                            this,\n                            minecraft.player,\n                            ALTERNATIVES_TEXT,\n                            stack,\n                            slot.getSlotIndex()\n                        )) : null\n                    ));\n                }\n            } else {\n                super.slotClicked(slot, slotId, mouseButton, type);\n            }\n        } else {\n            super.slotClicked(slot, slotId, mouseButton, type);\n        }\n    }\n\n    public SmallCheckboxWidget addCheckBox(int x, int y, Component text, boolean checked, Consumer<SmallCheckboxWidget> onPress) {\n        SmallCheckboxWidget checkBox = new SmallCheckboxWidget(x, y, text, checked, onPress);\n\n        this.addRenderableWidget(checkBox);\n\n        return checkBox;\n    }\n\n    public Button addButton(int x, int y, int w, int h, Component text, boolean enabled, boolean visible, Button.OnPress onPress) {\n        Button button = Button.builder(text, onPress).pos(x, y).size(w, h).build();\n        button.active = enabled;\n        button.visible = visible;\n        addRenderableWidget(button);\n        return button;\n    }\n\n    public void addSideButton(SideButton button) {\n        button.setX(leftPos - button.getWidth() - 2);\n        button.setY(topPos + sideButtonY);\n        sideButtonY += button.getHeight() + 2;\n        sideButtons.add(button);\n        addRenderableWidget(button);\n    }\n\n    public List<SideButton> getSideButtons() {\n        return sideButtons;\n    }\n\n    public void renderItem(GuiGraphics graphics, int x, int y, ItemStack stack) {\n        renderItem(graphics, x, y, stack, false, null, 0);\n    }\n\n    public void renderItem(GuiGraphics graphics, int x, int y, ItemStack stack, boolean overlay, @Nullable String text, int textColor) {\n        try {\n            graphics.renderItem(stack, x, y);\n            if (overlay) {\n                graphics.renderItemDecorations(font, stack, x, y, \"\");\n            }\n            if (text != null) {\n                renderQuantity(graphics, x, y, text, textColor);\n            }\n        } catch (Throwable t) {\n            logger.warn(\"Couldn't render stack: {}\", BuiltInRegistries.ITEM.getKey(stack.getItem()));\n        }\n    }\n\n    public void renderQuantity(GuiGraphics graphics, int x, int y, String qty, int color) {\n        boolean large = minecraft.isEnforceUnicode() || RS.CLIENT_CONFIG.getGrid().getLargeFont();\n\n        graphics.pose().pushPose();\n        graphics.pose().translate(x, y, Z_LEVEL_QTY);\n\n        if (!large) {\n            graphics.pose().scale(0.5F, 0.5F, 1);\n        }\n\n        graphics.drawString(font, qty, (large ? 16 : 30) - font.width(qty), large ? 8 : 22, color);\n\n        graphics.pose().popPose();\n    }\n\n    public void renderString(GuiGraphics graphics, int x, int y, String message) {\n        renderString(graphics, x, y, message, RenderSettings.INSTANCE.getPrimaryColor());\n    }\n\n    public void renderString(GuiGraphics graphics, int x, int y, String message, int color) {\n        graphics.drawString(font, message, x, y, color, false);\n    }\n\n    public void renderTooltip(GuiGraphics graphics, int x, int y, String lines) {\n        renderTooltip(graphics, ItemStack.EMPTY, x, y, lines);\n    }\n\n    public void renderTooltip(GuiGraphics graphics, @Nonnull ItemStack stack, int x, int y, String lines) {\n        renderTooltip(graphics, stack, x, y, Arrays.stream(lines.split(\"\\n\")).map(Component::literal).collect(Collectors.toList()));\n    }\n\n    public void renderTooltip(GuiGraphics graphics, @Nonnull ItemStack stack, int x, int y, List<Component> lines) {\n        graphics.renderComponentTooltip(font, lines, x, y, stack);\n    }\n\n    protected void onPreInit() {\n        // NO OP\n    }\n\n    public abstract void onPostInit(int x, int y);\n\n    public abstract void tick(int x, int y);\n\n    public abstract void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY);\n\n    public abstract void renderForeground(GuiGraphics graphics, int mouseX, int mouseY);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/ConstructorScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.blockentity.ConstructorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.container.ConstructorContainerMenu;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.ConstructorDropSideButton;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.ExactModeSideButton;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.TypeSideButton;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\n\npublic class ConstructorScreen extends BaseScreen<ConstructorContainerMenu> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/constructor.png\");\n\n    public ConstructorScreen(ConstructorContainerMenu containerMenu, Inventory inventory, Component title) {\n        super(containerMenu, 211, 137, inventory, title);\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE));\n\n        addSideButton(new TypeSideButton(this, ConstructorBlockEntity.TYPE));\n\n        addSideButton(new ExactModeSideButton(this, ConstructorBlockEntity.COMPARE));\n        addSideButton(new ConstructorDropSideButton(this));\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        // NO OP\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight);\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, title.getString());\n        renderString(graphics, 7, 43, I18n.get(\"container.inventory\"));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/ControllerScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.mojang.blaze3d.platform.Lighting;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.apiimpl.network.Network;\nimport com.refinedmods.refinedstorage.blockentity.ClientNode;\nimport com.refinedmods.refinedstorage.blockentity.ControllerBlockEntity;\nimport com.refinedmods.refinedstorage.container.ControllerContainerMenu;\nimport com.refinedmods.refinedstorage.screen.widget.ScrollbarWidget;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\n\nimport java.util.List;\n\npublic class ControllerScreen extends BaseScreen<ControllerContainerMenu> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/controller.png\");\n\n    private static final int VISIBLE_ROWS = 2;\n\n    private static final int ENERGY_BAR_X = 8;\n    private static final int ENERGY_BAR_Y = 20;\n    private static final int ENERGY_BAR_WIDTH = 16;\n    private static final int ENERGY_BAR_HEIGHT = 59;\n\n    private final ScrollbarWidget scrollbar;\n\n    public ControllerScreen(ControllerContainerMenu containerMenu, Inventory inventory, Component title) {\n        super(containerMenu, 176, 181, inventory, title);\n\n        this.scrollbar = new ScrollbarWidget(this, 157, 20, 12, 59);\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        addSideButton(new RedstoneModeSideButton(this, ControllerBlockEntity.REDSTONE_MODE));\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        scrollbar.setEnabled(getRows() > VISIBLE_ROWS);\n        scrollbar.setMaxOffset(getRows() - VISIBLE_ROWS);\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight);\n\n        int energyBarHeightNew = Network.getEnergyScaled(ControllerBlockEntity.ENERGY_STORED.getValue(), ControllerBlockEntity.ENERGY_CAPACITY.getValue(), ENERGY_BAR_HEIGHT);\n\n        graphics.blit(TEXTURE, x + ENERGY_BAR_X, y + ENERGY_BAR_Y + ENERGY_BAR_HEIGHT - energyBarHeightNew, 178, ENERGY_BAR_HEIGHT - energyBarHeightNew, ENERGY_BAR_WIDTH, energyBarHeightNew);\n\n        scrollbar.render(graphics);\n    }\n\n    @Override\n    public void mouseMoved(double mx, double my) {\n        scrollbar.mouseMoved(mx, my);\n\n        super.mouseMoved(mx, my);\n    }\n\n    @Override\n    public boolean mouseClicked(double mx, double my, int button) {\n        return scrollbar.mouseClicked(mx, my, button) || super.mouseClicked(mx, my, button);\n    }\n\n    @Override\n    public boolean mouseReleased(double mx, double my, int button) {\n        return scrollbar.mouseReleased(mx, my, button) || super.mouseReleased(mx, my, button);\n    }\n\n    @Override\n    public boolean mouseScrolled(double x, double y, double z, double delta) {\n        return this.scrollbar.mouseScrolled(x, y, z, delta) || super.mouseScrolled(x, y, z, delta);\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, title.getString());\n        renderString(graphics, 7, 87, I18n.get(\"container.inventory\"));\n\n        int x = 33;\n        int y = 26;\n\n        int slot = scrollbar.getOffset() * 2;\n\n        Lighting.setupFor3DItems();\n\n        List<ClientNode> nodes = ControllerBlockEntity.NODES.getValue();\n\n        ClientNode hoveringNode = null;\n\n        for (int i = 0; i < 4; ++i) {\n            if (slot < nodes.size()) {\n                ClientNode node = nodes.get(slot);\n\n                renderItem(graphics, x, y + 5, node.getStack());\n\n                float scale = minecraft.isEnforceUnicode() ? 1F : 0.5F;\n\n                final PoseStack poseStack = graphics.pose();\n                poseStack.pushPose();\n                poseStack.scale(scale, scale, 1);\n\n                renderString(\n                    graphics,\n                    RenderUtils.getOffsetOnScale(x + 1, scale),\n                    RenderUtils.getOffsetOnScale(y - 2, scale),\n                    trimNameIfNeeded(!minecraft.isEnforceUnicode(), node.getStack().getHoverName().getString())\n                );\n                renderString(graphics, RenderUtils.getOffsetOnScale(x + 21, scale), RenderUtils.getOffsetOnScale(y + 10, scale), node.getAmount() + \"x\");\n\n                poseStack.popPose();\n\n                if (RenderUtils.inBounds(x, y, 16, 16, mouseX, mouseY)) {\n                    hoveringNode = node;\n                }\n            }\n\n            if (i == 1) {\n                x = 33;\n                y += 30;\n            } else {\n                x += 60;\n            }\n\n            slot++;\n        }\n\n        if (hoveringNode != null) {\n            renderTooltip(graphics, mouseX, mouseY, I18n.get(\"misc.refinedstorage.energy_usage_minimal\", hoveringNode.getEnergyUsage()));\n        }\n\n        if (RenderUtils.inBounds(ENERGY_BAR_X, ENERGY_BAR_Y, ENERGY_BAR_WIDTH, ENERGY_BAR_HEIGHT, mouseX, mouseY)) {\n            renderTooltip(graphics, mouseX, mouseY, I18n.get(\"misc.refinedstorage.energy_usage\", ControllerBlockEntity.ENERGY_USAGE.getValue()) + \"\\n\" + I18n.get(\"misc.refinedstorage.energy_stored\", ControllerBlockEntity.ENERGY_STORED.getValue(), ControllerBlockEntity.ENERGY_CAPACITY.getValue()));\n        }\n    }\n\n    private int getRows() {\n        return Math.max(0, (int) Math.ceil((float) ControllerBlockEntity.NODES.getValue().size() / 2F));\n    }\n\n    private String trimNameIfNeeded(boolean scaled, String name) {\n        int max = scaled ? 19 : 12;\n        if (name.length() > max) {\n            name = name.substring(0, max) + \"...\";\n        }\n        return name;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/CrafterBlockEntitySynchronizationClientListener.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.CrafterModeSideButton;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationClientListener;\n\npublic class CrafterBlockEntitySynchronizationClientListener implements BlockEntitySynchronizationClientListener<Boolean> {\n    @Override\n    public void onChanged(boolean initial, Boolean hasRoot) {\n        if (Boolean.FALSE.equals(hasRoot)) {\n            BaseScreen.executeLater(CrafterScreen.class, gui -> gui.addSideButton(new CrafterModeSideButton(gui)));\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/CrafterManagerScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.mojang.blaze3d.systems.RenderSystem;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.CrafterManagerNetworkNode;\nimport com.refinedmods.refinedstorage.container.CrafterManagerContainerMenu;\nimport com.refinedmods.refinedstorage.container.slot.CrafterManagerSlot;\nimport com.refinedmods.refinedstorage.screen.widget.ScrollbarWidget;\nimport com.refinedmods.refinedstorage.screen.widget.SearchWidget;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.CrafterManagerSearchBoxModeSideButton;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.GridSizeSideButton;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton;\nimport com.refinedmods.refinedstorage.blockentity.CrafterManagerBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.minecraft.world.inventory.Slot;\nimport yalter.mousetweaks.api.MouseTweaksDisableWheelTweak;\n\nimport java.util.Map;\n\n@MouseTweaksDisableWheelTweak\npublic class CrafterManagerScreen extends BaseScreen<CrafterManagerContainerMenu> implements IScreenInfoProvider {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/crafter_manager.png\");\n\n    private final CrafterManagerNetworkNode crafterManager;\n\n    private ScrollbarWidget scrollbar;\n    private SearchWidget searchField;\n\n    public CrafterManagerScreen(CrafterManagerContainerMenu containerMenu, Inventory inventory, Component title) {\n        super(containerMenu, 193, 0, inventory, title);\n\n        this.crafterManager = ((CrafterManagerBlockEntity) containerMenu.getBlockEntity()).getNode();\n    }\n\n    @Override\n    protected void onPreInit() {\n        this.imageHeight = getTopHeight() + getBottomHeight() + (getVisibleRows() * 18);\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE));\n        addSideButton(new CrafterManagerSearchBoxModeSideButton(this));\n        addSideButton(new GridSizeSideButton(this, crafterManager::getSize, size -> BlockEntitySynchronizationManager.setParameter(CrafterManagerBlockEntity.SIZE, size)));\n\n        this.scrollbar = new ScrollbarWidget(this, 174, getTopHeight(), 12, (getVisibleRows() * 18) - 2);\n        this.scrollbar.addListener((oldOffset, newOffset) -> menu.initSlots(null));\n\n        menu.initSlots(null);\n\n        int sx = x + 97 + 1;\n        int sy = y + 6 + 1;\n\n        if (searchField == null) {\n            searchField = new SearchWidget(font, sx, sy, 88 - 6);\n            searchField.setResponder(value -> {\n                searchField.updateJei();\n\n                menu.initSlots(null);\n            });\n            searchField.setMode(crafterManager.getSearchBoxMode());\n        } else {\n            searchField.setX(sx);\n            searchField.setY(sy);\n        }\n\n        addRenderableWidget(searchField);\n        if (searchField.isFocused()) {\n            setFocused(searchField);\n        }\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        scrollbar.setEnabled((getRows() - 1) >= getVisibleRows());\n        scrollbar.setMaxOffset(getRows() - getVisibleRows());\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, getTopHeight());\n\n        int rows = getVisibleRows();\n\n        int yy = y;\n\n        for (int i = 0; i < rows; ++i) {\n            yy += 18;\n\n            int yTextureStart = getTopHeight();\n            if (i > 0) {\n                if (i == rows - 1) {\n                    yTextureStart += 18 * 2;\n                } else {\n                    yTextureStart += 18;\n                }\n            }\n\n            graphics.blit(TEXTURE, x, yy, 0, yTextureStart, imageWidth, 18);\n        }\n\n        yy += 18;\n\n        graphics.blit(TEXTURE, x, yy, 0, getTopHeight() + (18 * 3), imageWidth, getBottomHeight());\n\n        if (crafterManager.isActiveOnClient()) {\n            for (Slot slot : menu.slots) {\n                if (slot instanceof CrafterManagerSlot && slot.isActive()) {\n                    graphics.blit(TEXTURE, x + slot.x - 1, y + slot.y - 1, 0, 193, 18, 18);\n                }\n            }\n        }\n\n        searchField.render(graphics, 0, 0, 0);\n\n        scrollbar.render(graphics);\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, title.getString());\n        renderString(graphics, 7, getYPlayerInventory() - 12, I18n.get(\"container.inventory\"));\n\n        if (crafterManager.isActiveOnClient()) {\n            for (Map.Entry<String, Integer> heading : menu.getHeadings().entrySet()) {\n                int y = heading.getValue();\n\n                if (y >= getTopHeight() - 1 && y < getTopHeight() + getVisibleRows() * 18 - 1) {\n                    RenderSystem.setShaderColor(1, 1, 1, 1);\n\n                    graphics.blit(TEXTURE, 7, y, 0, 174, 18 * 9, 18);\n                    renderString(graphics, 7 + 4, y + 6, RenderUtils.shorten(I18n.get(heading.getKey()), 25));\n                }\n            }\n        }\n    }\n\n    @Override\n    public boolean mouseClicked(double mouseX, double mouseY, int clickedButton) {\n        if (scrollbar.mouseClicked(mouseX, mouseY, clickedButton)) {\n            return true;\n        }\n\n        return super.mouseClicked(mouseX, mouseY, clickedButton);\n    }\n\n    @Override\n    public boolean charTyped(char unknown1, int unknown2) {\n        if (searchField.charTyped(unknown1, unknown2)) {\n            return true;\n        }\n\n        return super.charTyped(unknown1, unknown2);\n    }\n\n    @Override\n    public boolean keyPressed(int key, int scanCode, int modifiers) {\n        if (searchField.keyPressed(key, scanCode, modifiers)) {\n            return true;\n        }\n\n        return super.keyPressed(key, scanCode, modifiers);\n    }\n\n    @Override\n    public void mouseMoved(double mx, double my) {\n        scrollbar.mouseMoved(mx, my);\n\n        super.mouseMoved(mx, my);\n    }\n\n    @Override\n    public boolean mouseReleased(double mx, double my, int button) {\n        return scrollbar.mouseReleased(mx, my, button) || super.mouseReleased(mx, my, button);\n    }\n\n    @Override\n    public boolean mouseScrolled(double x, double y, double z, double delta) {\n        return this.scrollbar.mouseScrolled(x, y, z, delta) || super.mouseScrolled(x, y, z, delta);\n    }\n\n    public SearchWidget getSearchField() {\n        return searchField;\n    }\n\n    public CrafterManagerNetworkNode getCrafterManager() {\n        return crafterManager;\n    }\n\n    @Override\n    public int getTopHeight() {\n        return 19;\n    }\n\n    @Override\n    public int getBottomHeight() {\n        return 99;\n    }\n\n    @Override\n    public int getVisibleRows() {\n        switch (crafterManager.getSize()) {\n            case IGrid.SIZE_STRETCH:\n                int screenSpaceAvailable = height - getTopHeight() - getBottomHeight();\n\n                return Math.max(3, Math.min((screenSpaceAvailable / 18) - 3, RS.CLIENT_CONFIG.getCrafterManager().getMaxRowsStretch()));\n            case IGrid.SIZE_SMALL:\n                return 3;\n            case IGrid.SIZE_MEDIUM:\n                return 5;\n            case IGrid.SIZE_LARGE:\n                return 8;\n            default:\n                return 3;\n        }\n    }\n\n    @Override\n    public int getRows() {\n        return !crafterManager.isActiveOnClient() ? 0 : menu.getRows();\n    }\n\n    @Override\n    public int getCurrentOffset() {\n        return scrollbar == null ? 0 : scrollbar.getOffset();\n    }\n\n    @Override\n    public String getSearchFieldText() {\n        return searchField == null ? \"\" : searchField.getValue();\n    }\n\n    @Override\n    public int getYPlayerInventory() {\n        return getTopHeight() + (getVisibleRows() * 18) + 16;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/CrafterScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.container.CrafterContainerMenu;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\n\npublic class CrafterScreen extends BaseScreen<CrafterContainerMenu> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/crafter.png\");\n\n    public CrafterScreen(CrafterContainerMenu containerMenu, Inventory inventory, Component title) {\n        super(containerMenu, 211, 137, inventory, title);\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        // NO OP\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        // NO OP\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight);\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, RenderUtils.shorten(title.getString(), 26));\n        renderString(graphics, 7, 43, I18n.get(\"container.inventory\"));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/CraftingMonitorScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.google.common.collect.Lists;\nimport com.mojang.blaze3d.platform.Lighting;\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement;\nimport com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingRequestInfo;\nimport com.refinedmods.refinedstorage.api.network.grid.IGridTab;\nimport com.refinedmods.refinedstorage.api.render.IElementDrawer;\nimport com.refinedmods.refinedstorage.api.render.IElementDrawers;\nimport com.refinedmods.refinedstorage.api.util.IFilter;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.render.CraftingMonitorElementDrawers;\nimport com.refinedmods.refinedstorage.apiimpl.render.ElementDrawers;\nimport com.refinedmods.refinedstorage.blockentity.craftingmonitor.ICraftingMonitor;\nimport com.refinedmods.refinedstorage.container.CraftingMonitorContainerMenu;\nimport com.refinedmods.refinedstorage.network.craftingmonitor.CraftingMonitorCancelMessage;\nimport com.refinedmods.refinedstorage.network.craftingmonitor.CraftingMonitorSyncTask;\nimport com.refinedmods.refinedstorage.screen.widget.ScrollbarWidget;\nimport com.refinedmods.refinedstorage.screen.widget.TabListWidget;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.gui.Font;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.gui.components.Button;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport javax.annotation.Nullable;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.UUID;\n\npublic class CraftingMonitorScreen extends BaseScreen<CraftingMonitorContainerMenu> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/crafting_preview.png\");\n\n    private static final int ROWS = 5;\n    private static final int ITEM_WIDTH = 73;\n    private static final int ITEM_HEIGHT = 29;\n    private final ScrollbarWidget scrollbar;\n    private final ICraftingMonitor craftingMonitor;\n    private final TabListWidget<CraftingMonitorContainerMenu> tabs;\n    private final IElementDrawers drawers = new CraftingMonitorElementDrawers(this, ITEM_WIDTH, ITEM_HEIGHT);\n    private Button cancelButton;\n    private Button cancelAllButton;\n    private List<IGridTab> tasks = Collections.emptyList();\n\n    public CraftingMonitorScreen(CraftingMonitorContainerMenu containerMenu, Inventory inventory, Component title) {\n        super(containerMenu, 254, 201, inventory, title);\n\n        this.craftingMonitor = containerMenu.getCraftingMonitor();\n\n        this.tabs = new TabListWidget<>(this, new ElementDrawers<>(this), () -> tasks, () -> (int) Math.floor((float) Math.max(0, tasks.size() - 1) / (float) ICraftingMonitor.TABS_PER_PAGE), craftingMonitor::getTabPage, () -> {\n            IGridTab tab = getCurrentTab();\n\n            if (tab == null) {\n                return -1;\n            }\n\n            return tasks.indexOf(tab);\n        }, ICraftingMonitor.TABS_PER_PAGE);\n        this.tabs.addListener(new TabListWidget.ITabListListener() {\n            @Override\n            public void onSelectionChanged(int tab) {\n                craftingMonitor.onTabSelectionChanged(Optional.of(((Task) tasks.get(tab)).id));\n\n                scrollbar.setOffset(0);\n            }\n\n            @Override\n            public void onPageChanged(int page) {\n                craftingMonitor.onTabPageChanged(page);\n            }\n        });\n\n        this.scrollbar = new ScrollbarWidget(this, 235, 20, 12, 149);\n    }\n\n    public void setTasks(List<CraftingMonitorSyncTask> tasks) {\n        this.tasks = tasks.stream().map(Task::new).collect(Lists::newArrayList, List::add, List::addAll);\n    }\n\n    public List<ICraftingMonitorElement> getElements() {\n        if (!craftingMonitor.isActiveOnClient()) {\n            return Collections.emptyList();\n        }\n\n        IGridTab tab = getCurrentTab();\n\n        if (tab == null) {\n            return Collections.emptyList();\n        }\n\n        return ((Task) tab).elements;\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        this.tabs.init(imageWidth);\n\n        if (craftingMonitor.getRedstoneModeParameter() != null) {\n            addSideButton(new RedstoneModeSideButton(this, craftingMonitor.getRedstoneModeParameter()));\n        }\n\n        Component cancel = Component.translatable(\"gui.cancel\");\n        Component cancelAll = Component.translatable(\"misc.refinedstorage.cancel_all\");\n\n        int cancelButtonWidth = 14 + font.width(cancel.getString());\n        int cancelAllButtonWidth = 14 + font.width(cancelAll.getString());\n\n        this.cancelButton = addButton(x + 7, y + 201 - 20 - 7, cancelButtonWidth, 20, cancel, false, true, btn -> {\n            if (hasValidTabSelected()) {\n                RS.NETWORK_HANDLER.sendToServer(new CraftingMonitorCancelMessage(((Task) getCurrentTab()).id));\n            }\n        });\n        this.cancelAllButton = addButton(x + 7 + cancelButtonWidth + 4, y + 201 - 20 - 7, cancelAllButtonWidth, 20, cancelAll, false, true, btn -> {\n            if (!tasks.isEmpty()) {\n                RS.NETWORK_HANDLER.sendToServer(new CraftingMonitorCancelMessage(null));\n            }\n        });\n    }\n\n    private void updateScrollbar() {\n        if (scrollbar != null) {\n            scrollbar.setEnabled(getRows() > ROWS);\n            scrollbar.setMaxOffset(getRows() - ROWS);\n        }\n    }\n\n    private int getRows() {\n        return Math.max(0, (int) Math.ceil((float) getElements().size() / 3F));\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        updateScrollbar();\n\n        this.tabs.update();\n\n        if (cancelButton != null) {\n            cancelButton.active = hasValidTabSelected();\n        }\n\n        if (cancelAllButton != null) {\n            cancelAllButton.active = !tasks.isEmpty();\n        }\n    }\n\n    private boolean hasValidTabSelected() {\n        return getCurrentTab() != null;\n    }\n\n    @Nullable\n    private IGridTab getCurrentTab() {\n        Optional<UUID> currentTab = craftingMonitor.getTabSelected();\n\n        if (currentTab.isPresent()) {\n            IGridTab tab = getTabById(currentTab.get());\n\n            if (tab != null) {\n                return tab;\n            }\n        }\n\n        if (tasks.isEmpty()) {\n            return null;\n        }\n\n        return tasks.get(0);\n    }\n\n    @Nullable\n    private IGridTab getTabById(UUID id) {\n        return tasks.stream().filter(t -> ((Task) t).id.equals(id)).findFirst().orElse(null);\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        if (craftingMonitor.isActiveOnClient()) {\n            tabs.drawBackground(graphics, x, y - tabs.getHeight());\n        }\n\n        graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight);\n\n        scrollbar.render(graphics);\n\n        tabs.drawForeground(graphics, x, y - tabs.getHeight(), mouseX, mouseY, craftingMonitor.isActiveOnClient());\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, title.getString());\n\n        int item = scrollbar != null ? scrollbar.getOffset() * 3 : 0;\n\n        Lighting.setupFor3DItems();\n\n        int x = 7;\n        int y = 20;\n\n        List<Component> tooltip = null;\n\n        for (int i = 0; i < 3 * 5; ++i) {\n            if (item < getElements().size()) {\n                ICraftingMonitorElement element = getElements().get(item);\n\n                element.draw(graphics, x, y, drawers);\n\n                if (RenderUtils.inBounds(x, y, ITEM_WIDTH, ITEM_HEIGHT, mouseX, mouseY)) {\n                    tooltip = element.getTooltip();\n                }\n\n                if ((i + 1) % 3 == 0) {\n                    x = 7;\n                    y += 30;\n                } else {\n                    x += 74;\n                }\n            }\n\n            item++;\n        }\n\n        if (tooltip != null && !tooltip.isEmpty()) {\n            renderTooltip(graphics, ItemStack.EMPTY, mouseX, mouseY, tooltip);\n        }\n\n        tabs.drawTooltip(graphics, font, mouseX, mouseY);\n    }\n\n    @Override\n    public boolean mouseClicked(double mouseX, double mouseY, int clickedButton) {\n        if (tabs.mouseClicked()) {\n            return true;\n        }\n\n        if (scrollbar.mouseClicked(mouseX, mouseY, clickedButton)) {\n            return true;\n        }\n\n        return super.mouseClicked(mouseX, mouseY, clickedButton);\n    }\n\n    @Override\n    public void mouseMoved(double mx, double my) {\n        scrollbar.mouseMoved(mx, my);\n\n        super.mouseMoved(mx, my);\n    }\n\n    @Override\n    public boolean mouseReleased(double mx, double my, int button) {\n        return scrollbar.mouseReleased(mx, my, button) || super.mouseReleased(mx, my, button);\n    }\n\n    @Override\n    public boolean mouseScrolled(double x, double y, double z, double delta) {\n        return this.scrollbar.mouseScrolled(x, y, z, delta) || super.mouseScrolled(x, y, z, delta);\n    }\n\n    public static class Task implements IGridTab {\n        private final UUID id;\n        private final ICraftingRequestInfo requested;\n        private final int qty;\n        private final long executionStarted;\n        private final int completionPercentage;\n        private final List<ICraftingMonitorElement> elements;\n\n        public Task(CraftingMonitorSyncTask syncTask) {\n            this.id = syncTask.id();\n            this.requested = syncTask.requestInfo();\n            this.qty = syncTask.quantity();\n            this.executionStarted = syncTask.startTime();\n            this.completionPercentage = syncTask.completionPercentage();\n            this.elements = syncTask.elements();\n        }\n\n        @Override\n        public void drawTooltip(Font font, GuiGraphics graphics, int x, int y) {\n            List<Component> lines = Lists.newArrayList(requested.getItem() != null ? requested.getItem().getHoverName() : requested.getFluid().getDisplayName());\n\n            int totalSecs = (int) (System.currentTimeMillis() - executionStarted) / 1000;\n            int hours = totalSecs / 3600;\n            int minutes = (totalSecs % 3600) / 60;\n            int seconds = totalSecs % 60;\n\n            lines.add(Component.translatable(\n                \"gui.refinedstorage.crafting_monitor.tooltip.requested\",\n                requested.getFluid() != null ? API.instance().getQuantityFormatter().formatInBucketForm(qty) : API.instance().getQuantityFormatter().format(qty)\n            ).withStyle(ChatFormatting.GRAY));\n\n            if (hours > 0) {\n                lines.add(Component.literal(String.format(\"%02d:%02d:%02d\", hours, minutes, seconds)).withStyle(ChatFormatting.GRAY));\n            } else {\n                lines.add(Component.literal(String.format(\"%02d:%02d\", minutes, seconds)).withStyle(ChatFormatting.GRAY));\n            }\n\n            lines.add(Component.literal(String.format(\"%d%%\", completionPercentage)).withStyle(ChatFormatting.GRAY));\n\n            graphics.renderComponentTooltip(font, lines, x, y);\n        }\n\n        @Override\n        public List<IFilter> getFilters() {\n            throw new UnsupportedOperationException();\n        }\n\n        @Override\n        public void drawIcon(GuiGraphics graphics, int x, int y, IElementDrawer<ItemStack> itemDrawer, IElementDrawer<FluidStack> fluidDrawer) {\n            if (requested.getItem() != null) {\n                Lighting.setupFor3DItems();\n                itemDrawer.draw(graphics, x, y, requested.getItem());\n            } else {\n                fluidDrawer.draw(graphics, x, y, requested.getFluid());\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/DestructorScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.blockentity.DestructorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.container.DestructorContainerMenu;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.*;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\n\npublic class DestructorScreen extends BaseScreen<DestructorContainerMenu> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/destructor.png\");\n\n    public DestructorScreen(DestructorContainerMenu containerMenu, Inventory playerInventory, Component title) {\n        super(containerMenu, 211, 137, playerInventory, title);\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE));\n\n        addSideButton(new TypeSideButton(this, DestructorBlockEntity.TYPE));\n\n        addSideButton(new WhitelistBlacklistSideButton(this, DestructorBlockEntity.WHITELIST_BLACKLIST));\n\n        addSideButton(new ExactModeSideButton(this, DestructorBlockEntity.COMPARE));\n\n        addSideButton(new DestructorPickupSideButton(this));\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        // NO OP\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight);\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, title.getString());\n        renderString(graphics, 7, 43, I18n.get(\"container.inventory\"));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/DetectorScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.blockentity.DetectorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport com.refinedmods.refinedstorage.container.DetectorContainerMenu;\nimport com.refinedmods.refinedstorage.render.RenderSettings;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.DetectorModeSideButton;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.ExactModeSideButton;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.TypeSideButton;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.gui.components.EditBox;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\nimport org.lwjgl.glfw.GLFW;\n\npublic class DetectorScreen extends BaseScreen<DetectorContainerMenu> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/detector.png\");\n\n    private EditBox amountField;\n\n    public DetectorScreen(DetectorContainerMenu containerMenu, Inventory inventory, Component title) {\n        super(containerMenu, 176, 137, inventory, title);\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        addSideButton(new TypeSideButton(this, DetectorBlockEntity.TYPE));\n\n        addSideButton(new DetectorModeSideButton(this));\n\n        addSideButton(new ExactModeSideButton(this, DetectorBlockEntity.COMPARE));\n\n        amountField = new EditBox(font, x + 41 + 1, y + 23 + 1, 50, font.lineHeight, Component.literal(\"\"));\n        amountField.setValue(String.valueOf(DetectorBlockEntity.AMOUNT.getValue()));\n        amountField.setBordered(false);\n        amountField.setVisible(true);\n        amountField.setCanLoseFocus(true);\n        amountField.setFocused(false);\n        amountField.setTextColor(RenderSettings.INSTANCE.getSecondaryColor());\n        amountField.setResponder(value -> {\n            try {\n                int result = Integer.parseInt(value);\n\n                BlockEntitySynchronizationManager.setParameter(DetectorBlockEntity.AMOUNT, result);\n            } catch (NumberFormatException e) {\n                // NO OP\n            }\n        });\n\n        addRenderableWidget(amountField);\n    }\n\n    public void updateAmountField(int amount) {\n        amountField.setValue(String.valueOf(amount));\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        // NO OP\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight);\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, title.getString());\n        renderString(graphics, 7, 43, I18n.get(\"container.inventory\"));\n    }\n\n    @Override\n    public boolean keyPressed(int key, int scanCode, int modifiers) {\n        if (key == GLFW.GLFW_KEY_ESCAPE) {\n            minecraft.player.closeContainer();\n\n            return true;\n        }\n\n        if (amountField.keyPressed(key, scanCode, modifiers) || amountField.canConsumeInput()) {\n            return true;\n        }\n\n        return super.keyPressed(key, scanCode, modifiers);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/DiskDriveScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.blockentity.DiskDriveBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.container.DiskDriveContainerMenu;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\n\npublic class DiskDriveScreen extends StorageScreen<DiskDriveContainerMenu> {\n    public DiskDriveScreen(DiskDriveContainerMenu containerMenu, Inventory inventory, Component title) {\n        super(\n            containerMenu,\n            inventory,\n            title,\n            new ResourceLocation(RS.ID, \"textures/gui/disk_drive.png\"),\n            new StorageScreenSynchronizationParameters(\n                DiskDriveBlockEntity.TYPE,\n                NetworkNodeBlockEntity.REDSTONE_MODE,\n                DiskDriveBlockEntity.COMPARE,\n                DiskDriveBlockEntity.WHITELIST_BLACKLIST,\n                DiskDriveBlockEntity.PRIORITY,\n                DiskDriveBlockEntity.ACCESS_TYPE\n            ),\n            DiskDriveBlockEntity.STORED::getValue,\n            DiskDriveBlockEntity.CAPACITY::getValue\n        );\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 79, 42, I18n.get(\"gui.refinedstorage.disk_drive.disks\"));\n        super.renderForeground(graphics, mouseX, mouseY);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/DiskManipulatorScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.blockentity.DiskManipulatorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.container.DiskManipulatorContainerMenu;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.*;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\n\npublic class DiskManipulatorScreen extends BaseScreen<DiskManipulatorContainerMenu> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/disk_manipulator.png\");\n\n    public DiskManipulatorScreen(DiskManipulatorContainerMenu containerMenu, Inventory playerInventory, Component title) {\n        super(containerMenu, 211, 211, playerInventory, title);\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE));\n        addSideButton(new IoModeSideButton(this));\n        addSideButton(new TypeSideButton(this, DiskManipulatorBlockEntity.TYPE));\n        addSideButton(new WhitelistBlacklistSideButton(this, DiskManipulatorBlockEntity.WHITELIST_BLACKLIST));\n        addSideButton(new ExactModeSideButton(this, DiskManipulatorBlockEntity.COMPARE));\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        // NO OP\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight);\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, title.getString());\n        renderString(graphics, 7, 117, I18n.get(\"container.inventory\"));\n        renderString(graphics, 43, 45, I18n.get(\"gui.refinedstorage.disk_manipulator.in\"));\n        renderString(graphics, 115, 45, I18n.get(\"gui.refinedstorage.disk_manipulator.out\"));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/EmptyScreenInfoProvider.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\npublic class EmptyScreenInfoProvider implements IScreenInfoProvider {\n    @Override\n    public int getVisibleRows() {\n        return 3;\n    }\n\n    @Override\n    public int getRows() {\n        return 0;\n    }\n\n    @Override\n    public int getCurrentOffset() {\n        return 0;\n    }\n\n    @Override\n    public String getSearchFieldText() {\n        return \"\";\n    }\n\n    @Override\n    public int getTopHeight() {\n        return 0;\n    }\n\n    @Override\n    public int getBottomHeight() {\n        return 0;\n    }\n\n    @Override\n    public int getYPlayerInventory() {\n        return 0;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/ExporterScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.blockentity.ExporterBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.container.ExporterContainerMenu;\nimport com.refinedmods.refinedstorage.item.UpgradeItem;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.ExactModeSideButton;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.TypeSideButton;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\n\npublic class ExporterScreen extends BaseScreen<ExporterContainerMenu> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/exporter.png\");\n\n    private boolean hasRegulatorMode;\n\n    public ExporterScreen(ExporterContainerMenu containerMenu, Inventory playerInventory, Component title) {\n        super(containerMenu, 211, 137, playerInventory, title);\n\n        this.hasRegulatorMode = hasRegulatorMode();\n    }\n\n    private boolean hasRegulatorMode() {\n        return ((ExporterBlockEntity) menu.getBlockEntity()).getNode().getUpgrades().hasUpgrade(UpgradeItem.Type.REGULATOR);\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE));\n\n        addSideButton(new TypeSideButton(this, ExporterBlockEntity.TYPE));\n\n        addSideButton(new ExactModeSideButton(this, ExporterBlockEntity.COMPARE));\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        boolean updatedHasRegulatorMode = hasRegulatorMode();\n        if (hasRegulatorMode != updatedHasRegulatorMode) {\n            hasRegulatorMode = updatedHasRegulatorMode;\n\n            menu.initSlots();\n        }\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight);\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, title.getString());\n        renderString(graphics, 7, 43, I18n.get(\"container.inventory\"));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/ExternalStorageScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.blockentity.ExternalStorageBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.container.ExternalStorageContainerMenu;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\n\npublic class ExternalStorageScreen extends StorageScreen<ExternalStorageContainerMenu> {\n    public ExternalStorageScreen(ExternalStorageContainerMenu containerMenu, Inventory inventory, Component title) {\n        super(\n            containerMenu,\n            inventory,\n            title,\n            new ResourceLocation(RS.ID, \"textures/gui/storage.png\"),\n            new StorageScreenSynchronizationParameters(\n                ExternalStorageBlockEntity.TYPE,\n                NetworkNodeBlockEntity.REDSTONE_MODE,\n                ExternalStorageBlockEntity.COMPARE,\n                ExternalStorageBlockEntity.WHITELIST_BLACKLIST,\n                ExternalStorageBlockEntity.PRIORITY,\n                ExternalStorageBlockEntity.ACCESS_TYPE\n            ),\n            ExternalStorageBlockEntity.STORED::getValue,\n            ExternalStorageBlockEntity.CAPACITY::getValue\n        );\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/FilterScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.api.util.IFilter;\nimport com.refinedmods.refinedstorage.container.FilterContainerMenu;\nimport com.refinedmods.refinedstorage.item.FilterItem;\nimport com.refinedmods.refinedstorage.network.FilterUpdateMessage;\nimport com.refinedmods.refinedstorage.render.RenderSettings;\nimport com.refinedmods.refinedstorage.screen.widget.SmallCheckboxWidget;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.FilterTypeSideButton;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.gui.components.Button;\nimport net.minecraft.client.gui.components.EditBox;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.minecraft.world.item.ItemStack;\nimport org.lwjgl.glfw.GLFW;\n\npublic class FilterScreen extends BaseScreen<FilterContainerMenu> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/filter.png\");\n\n    private final ItemStack stack;\n    private final String name;\n    private int compare;\n    private int mode;\n    private boolean modFilter;\n    private int type;\n\n    private SmallCheckboxWidget modFilterCheckBox;\n    private Button modeButton;\n    private EditBox nameField;\n\n    public FilterScreen(FilterContainerMenu containerMenu, Inventory inventory, Component title) {\n        super(containerMenu, 176, 231, inventory, title);\n\n        this.stack = containerMenu.getFilterItem();\n\n        this.compare = FilterItem.getCompare(containerMenu.getFilterItem());\n        this.mode = FilterItem.getMode(containerMenu.getFilterItem());\n        this.modFilter = FilterItem.isModFilter(containerMenu.getFilterItem());\n        this.name = FilterItem.getFilterName(containerMenu.getFilterItem());\n        this.type = FilterItem.getType(containerMenu.getFilterItem());\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        addCheckBox(x + 7, y + 77, Component.translatable(\"gui.refinedstorage.filter.compare_nbt\"), (compare & IComparer.COMPARE_NBT) == IComparer.COMPARE_NBT, btn -> {\n            compare ^= IComparer.COMPARE_NBT;\n\n            sendUpdate();\n        });\n\n        modFilterCheckBox = addCheckBox(0, y + 71 + 25, Component.translatable(\"gui.refinedstorage.filter.mod_filter\"), modFilter, btn -> {\n            modFilter = !modFilter;\n\n            sendUpdate();\n        });\n\n        modeButton = addButton(x + 7, y + 71 + 21, 0, 20, Component.literal(\"\"), true, true, btn -> {\n            mode = mode == IFilter.MODE_WHITELIST ? IFilter.MODE_BLACKLIST : IFilter.MODE_WHITELIST;\n\n            updateModeButton(mode);\n\n            sendUpdate();\n        });\n\n        updateModeButton(mode);\n\n        nameField = new EditBox(font, x + 34, y + 121, 137 - 6, font.lineHeight, Component.literal(\"\"));\n        nameField.setValue(name);\n        nameField.setBordered(false);\n        nameField.setVisible(true);\n        nameField.setCanLoseFocus(true);\n        nameField.setFocused(false);\n        nameField.setTextColor(RenderSettings.INSTANCE.getSecondaryColor());\n        nameField.setResponder(content -> sendUpdate());\n\n        addRenderableWidget(nameField);\n\n        addSideButton(new FilterTypeSideButton(this));\n    }\n\n    private void updateModeButton(int mode) {\n        Component text = mode == IFilter.MODE_WHITELIST\n            ? Component.translatable(\"sidebutton.refinedstorage.mode.whitelist\")\n            : Component.translatable(\"sidebutton.refinedstorage.mode.blacklist\");\n\n        modeButton.setWidth(font.width(text.getString()) + 12);\n        modeButton.setMessage(text);\n        modFilterCheckBox.setX(modeButton.getX() + modeButton.getWidth() + 4);\n    }\n\n    @Override\n    public boolean keyPressed(int key, int scanCode, int modifiers) {\n        if (key == GLFW.GLFW_KEY_ESCAPE) {\n            minecraft.player.closeContainer();\n\n            return true;\n        }\n\n        if (nameField.keyPressed(key, scanCode, modifiers) || nameField.canConsumeInput()) {\n            return true;\n        }\n\n        return super.keyPressed(key, scanCode, modifiers);\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        // NO OP\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight);\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, title.getString());\n        renderString(graphics, 7, 137, I18n.get(\"container.inventory\"));\n    }\n\n    public int getType() {\n        return type;\n    }\n\n    public void setType(int type) {\n        this.type = type;\n\n        FilterItem.setType(stack, type);\n    }\n\n    public void sendUpdate() {\n        RS.NETWORK_HANDLER.sendToServer(new FilterUpdateMessage(compare, mode, modFilter, nameField.getValue(), type));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/FluidAmountScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.container.FluidAmountContainerMenu;\nimport com.refinedmods.refinedstorage.network.SetFluidFilterSlotMessage;\nimport com.refinedmods.refinedstorage.util.StackUtils;\nimport net.minecraft.client.gui.screens.Screen;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Player;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport org.apache.commons.lang3.tuple.Pair;\n\nimport javax.annotation.Nullable;\nimport java.util.function.UnaryOperator;\n\npublic class FluidAmountScreen extends AmountSpecifyingScreen<FluidAmountContainerMenu> {\n    private static final ResourceLocation TEXTURE_WIDE = new ResourceLocation(RS.ID, \"textures/gui/amount_specifying_wide.png\");\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/amount_specifying.png\");\n\n    private final int containerSlot;\n    private final FluidStack stack;\n    private final int maxAmount;\n    @Nullable\n    private final UnaryOperator<Screen> alternativesScreenFactory;\n\n    public FluidAmountScreen(BaseScreen parent, Player player, int containerSlot, FluidStack stack, int maxAmount, @Nullable UnaryOperator<Screen> alternativesScreenFactory) {\n        super(parent, new FluidAmountContainerMenu(player, stack), alternativesScreenFactory != null ? 194 : 172, 99, player.getInventory(), Component.translatable(\"gui.refinedstorage.fluid_amount\"));\n\n        this.containerSlot = containerSlot;\n        this.stack = stack;\n        this.maxAmount = maxAmount;\n        this.alternativesScreenFactory = alternativesScreenFactory;\n    }\n\n    @Override\n    protected int getOkCancelButtonWidth() {\n        return alternativesScreenFactory != null ? 75 : super.getOkCancelButtonWidth();\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        super.onPostInit(x, y);\n\n        if (alternativesScreenFactory != null) {\n            addButton(x + 114, cancelButton.getY() + 24, getOkCancelButtonWidth(), 20, Component.translatable(\"gui.refinedstorage.alternatives\"), true, true, btn -> minecraft.setScreen(alternativesScreenFactory.apply(this)));\n        }\n    }\n\n    @Override\n    protected Pair<Integer, Integer> getOkCancelPos() {\n        if (alternativesScreenFactory == null) {\n            return super.getOkCancelPos();\n        }\n\n        return Pair.of(114, 22);\n    }\n\n    @Override\n    protected int getDefaultAmount() {\n        return stack.getAmount();\n    }\n\n    @Override\n    protected boolean canAmountGoNegative() {\n        return false;\n    }\n\n    @Override\n    protected int getMaxAmount() {\n        return maxAmount;\n    }\n\n    @Override\n    protected Component getOkButtonText() {\n        return Component.translatable(\"misc.refinedstorage.set\");\n    }\n\n    @Override\n    protected ResourceLocation getTexture() {\n        return alternativesScreenFactory != null ? TEXTURE_WIDE : TEXTURE;\n    }\n\n    @Override\n    protected int[] getIncrements() {\n        return new int[]{\n            100, 500, 1000,\n            -100, -500, -1000\n        };\n    }\n\n    @Override\n    protected void onOkButtonPressed(boolean shiftDown) {\n        try {\n            int amount = Integer.parseInt(amountField.getValue());\n\n            RS.NETWORK_HANDLER.sendToServer(new SetFluidFilterSlotMessage(containerSlot, StackUtils.copy(stack, amount)));\n\n            close();\n        } catch (NumberFormatException e) {\n            // NO OP\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/FluidInterfaceScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.FluidInterfaceNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.FluidInterfaceBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.container.FluidInterfaceContainerMenu;\nimport com.refinedmods.refinedstorage.render.FluidRenderer;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\n\npublic class FluidInterfaceScreen extends BaseScreen<FluidInterfaceContainerMenu> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/fluid_interface.png\");\n    private static final FluidRenderer TANK_RENDERER = new FluidRenderer(FluidInterfaceNetworkNode.TANK_CAPACITY, 12, 47, 1);\n\n    public FluidInterfaceScreen(FluidInterfaceContainerMenu containerMenu, Inventory inventory, Component title) {\n        super(containerMenu, 211, 204, inventory, title);\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE));\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        // NO OP\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight);\n\n        if (!FluidInterfaceBlockEntity.TANK_IN.getValue().isEmpty()) {\n            TANK_RENDERER.render(graphics, x + 46, y + 56, FluidInterfaceBlockEntity.TANK_IN.getValue());\n        }\n\n        if (!FluidInterfaceBlockEntity.TANK_OUT.getValue().isEmpty()) {\n            TANK_RENDERER.render(graphics, x + 118, y + 56, FluidInterfaceBlockEntity.TANK_OUT.getValue());\n        }\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, title.getString());\n        renderString(graphics, 43 + 4, 20, I18n.get(\"gui.refinedstorage.fluid_interface.in\"));\n        renderString(graphics, 115 + 1, 20, I18n.get(\"gui.refinedstorage.fluid_interface.out\"));\n        renderString(graphics, 7, 111, I18n.get(\"container.inventory\"));\n\n        if (RenderUtils.inBounds(46, 56, 12, 47, mouseX, mouseY) && !FluidInterfaceBlockEntity.TANK_IN.getValue().isEmpty()) {\n            renderTooltip(graphics, mouseX, mouseY, FluidInterfaceBlockEntity.TANK_IN.getValue().getDisplayName().getString() + \"\\n\" + ChatFormatting.GRAY + API.instance().getQuantityFormatter().formatInBucketForm(FluidInterfaceBlockEntity.TANK_IN.getValue().getAmount()) + ChatFormatting.RESET);\n        }\n\n        if (RenderUtils.inBounds(118, 56, 12, 47, mouseX, mouseY) && !FluidInterfaceBlockEntity.TANK_OUT.getValue().isEmpty()) {\n            renderTooltip(graphics, mouseX, mouseY, FluidInterfaceBlockEntity.TANK_OUT.getValue().getDisplayName().getString() + \"\\n\" + ChatFormatting.GRAY + API.instance().getQuantityFormatter().formatInBucketForm(FluidInterfaceBlockEntity.TANK_OUT.getValue().getAmount()) + ChatFormatting.RESET);\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/FluidStorageBlockScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.blockentity.FluidStorageBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.container.FluidStorageContainerMenu;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\n\npublic class FluidStorageBlockScreen extends StorageScreen<FluidStorageContainerMenu> {\n    public FluidStorageBlockScreen(FluidStorageContainerMenu containerMenu, Inventory inventory, Component title) {\n        super(\n            containerMenu,\n            inventory,\n            title,\n            new ResourceLocation(RS.ID, \"textures/gui/storage.png\"),\n            new StorageScreenSynchronizationParameters(\n                null,\n                NetworkNodeBlockEntity.REDSTONE_MODE,\n                FluidStorageBlockEntity.COMPARE,\n                FluidStorageBlockEntity.WHITELIST_BLACKLIST,\n                FluidStorageBlockEntity.PRIORITY,\n                FluidStorageBlockEntity.ACCESS_TYPE\n            ),\n            FluidStorageBlockEntity.STORED::getValue,\n            () -> (long) ((FluidStorageBlockEntity) containerMenu.getBlockEntity()).getFluidStorageType().getCapacity()\n        );\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/IScreenInfoProvider.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\npublic interface IScreenInfoProvider {\n    int getVisibleRows();\n\n    int getRows();\n\n    int getCurrentOffset();\n\n    String getSearchFieldText();\n\n    int getTopHeight();\n\n    int getBottomHeight();\n\n    int getYPlayerInventory();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/ImporterScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.blockentity.ImporterBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.container.ImporterContainerMenu;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.ExactModeSideButton;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.TypeSideButton;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.WhitelistBlacklistSideButton;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\n\npublic class ImporterScreen extends BaseScreen<ImporterContainerMenu> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/importer.png\");\n\n    public ImporterScreen(ImporterContainerMenu containerMenu, Inventory inventory, Component title) {\n        super(containerMenu, 211, 137, inventory, title);\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE));\n\n        addSideButton(new TypeSideButton(this, ImporterBlockEntity.TYPE));\n\n        addSideButton(new WhitelistBlacklistSideButton(this, ImporterBlockEntity.WHITELIST_BLACKLIST));\n\n        addSideButton(new ExactModeSideButton(this, ImporterBlockEntity.COMPARE));\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        // NO OP\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight);\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, title.getString());\n        renderString(graphics, 7, 43, I18n.get(\"container.inventory\"));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/InterfaceScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.blockentity.InterfaceBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.container.InterfaceContainerMenu;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.ExactModeSideButton;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\n\npublic class InterfaceScreen extends BaseScreen<InterfaceContainerMenu> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/interface.png\");\n\n    public InterfaceScreen(InterfaceContainerMenu containerMenu, Inventory inventory, Component title) {\n        super(containerMenu, 211, 217, inventory, title);\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE));\n\n        addSideButton(new ExactModeSideButton(this, InterfaceBlockEntity.COMPARE));\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        // NO OP\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight);\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, I18n.get(\"gui.refinedstorage.interface.import\"));\n        renderString(graphics, 7, 42, I18n.get(\"gui.refinedstorage.interface.export\"));\n        renderString(graphics, 7, 122, I18n.get(\"container.inventory\"));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/ItemAmountScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.container.AmountContainerMenu;\nimport com.refinedmods.refinedstorage.network.SetFilterSlotMessage;\nimport net.minecraft.client.gui.screens.Screen;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\nimport org.apache.commons.lang3.tuple.Pair;\n\nimport javax.annotation.Nullable;\nimport java.util.function.UnaryOperator;\n\npublic class ItemAmountScreen extends AmountSpecifyingScreen<AmountContainerMenu> {\n    private static final ResourceLocation TEXTURE_WIDE = new ResourceLocation(RS.ID, \"textures/gui/amount_specifying_wide.png\");\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/amount_specifying.png\");\n\n    private final int containerSlot;\n    private final ItemStack stack;\n    private final int maxAmount;\n    @Nullable\n    private final UnaryOperator<Screen> alternativesScreenFactory;\n\n    public ItemAmountScreen(BaseScreen parent, Player player, int containerSlot, ItemStack stack, int maxAmount, @Nullable UnaryOperator<Screen> alternativesScreenFactory) {\n        super(parent, new AmountContainerMenu(player, stack), alternativesScreenFactory != null ? 194 : 172, 99, player.getInventory(), Component.translatable(\"gui.refinedstorage.item_amount\"));\n\n        this.containerSlot = containerSlot;\n        this.stack = stack;\n        this.maxAmount = maxAmount;\n        this.alternativesScreenFactory = alternativesScreenFactory;\n    }\n\n    @Override\n    protected int getOkCancelButtonWidth() {\n        return alternativesScreenFactory != null ? 75 : super.getOkCancelButtonWidth();\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        super.onPostInit(x, y);\n\n        if (alternativesScreenFactory != null) {\n            addButton(x + 114, cancelButton.getY() + 24, getOkCancelButtonWidth(), 20, Component.translatable(\"gui.refinedstorage.alternatives\"), true, true, btn -> minecraft.setScreen(alternativesScreenFactory.apply(this)));\n        }\n    }\n\n    @Override\n    protected Pair<Integer, Integer> getOkCancelPos() {\n        if (alternativesScreenFactory == null) {\n            return super.getOkCancelPos();\n        }\n\n        return Pair.of(114, 22);\n    }\n\n    @Override\n    protected int getDefaultAmount() {\n        return stack.getCount();\n    }\n\n    @Override\n    protected boolean canAmountGoNegative() {\n        return false;\n    }\n\n    @Override\n    protected int getMaxAmount() {\n        return maxAmount;\n    }\n\n    @Override\n    protected Component getOkButtonText() {\n        return Component.translatable(\"misc.refinedstorage.set\");\n    }\n\n    @Override\n    protected ResourceLocation getTexture() {\n        return alternativesScreenFactory != null ? TEXTURE_WIDE : TEXTURE;\n    }\n\n    @Override\n    protected int[] getIncrements() {\n        return new int[]{\n            1, 10, 64,\n            -1, -10, -64\n        };\n    }\n\n    @Override\n    protected void onOkButtonPressed(boolean shiftDown) {\n        try {\n            int amount = Integer.parseInt(amountField.getValue());\n\n            RS.NETWORK_HANDLER.sendToServer(new SetFilterSlotMessage(containerSlot, ItemHandlerHelper.copyStackWithSize(stack, amount)));\n\n            close();\n        } catch (NumberFormatException e) {\n            // NO OP\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/KeyInputListener.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.RSKeyBindings;\nimport com.refinedmods.refinedstorage.integration.curios.CuriosIntegration;\nimport com.refinedmods.refinedstorage.inventory.player.PlayerSlot;\nimport com.refinedmods.refinedstorage.network.OpenNetworkItemMessage;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.network.chat.MutableComponent;\nimport net.minecraft.world.Container;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.bus.api.SubscribeEvent;\nimport net.neoforged.neoforge.client.event.InputEvent;\nimport org.apache.commons.lang3.tuple.ImmutableTriple;\nimport top.theillusivec4.curios.api.CuriosApi;\n\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Optional;\nimport java.util.Set;\n\npublic class KeyInputListener {\n    //These are static to be accessible from RSAddons\n    public static void findAndOpen(Item... items) {\n        Set<Item> validItems = new HashSet<>(Arrays.asList(items));\n        Container inv = Minecraft.getInstance().player.getInventory();\n        int slotFound = -1;\n\n        for (int i = 0; i < inv.getContainerSize(); ++i) {\n            ItemStack slot = inv.getItem(i);\n\n            if (validItems.contains(slot.getItem())) {\n                if (slotFound != -1) {\n                    sendError(Component.translatable(\"misc.refinedstorage.network_item.shortcut_duplicate\", Component.translatable(items[0].getDescriptionId())));\n                    return;\n                }\n\n                slotFound = i;\n            }\n        }\n\n        if (CuriosIntegration.isLoaded() && slotFound == -1) {\n            Optional<ImmutableTriple<String, Integer, ItemStack>> curio = CuriosApi.getCuriosHelper().findEquippedCurio(stack -> validItems.contains(stack.getItem()), Minecraft.getInstance().player);\n\n            if (curio.isPresent()) {\n                RS.NETWORK_HANDLER.sendToServer(new OpenNetworkItemMessage(new PlayerSlot(curio.get().getMiddle(), curio.get().getLeft())));\n                return;\n            }\n        }\n\n        if (slotFound == -1) {\n            sendError(Component.translatable(\"misc.refinedstorage.network_item.shortcut_not_found\", Component.translatable(items[0].getDescriptionId())));\n        } else {\n            RS.NETWORK_HANDLER.sendToServer(new OpenNetworkItemMessage(new PlayerSlot(slotFound)));\n        }\n    }\n\n    public static void sendError(MutableComponent error) {\n        Minecraft.getInstance().player.sendSystemMessage(error);\n    }\n\n    @SubscribeEvent\n    public void onKeyInput(InputEvent.Key e) {\n        if (Minecraft.getInstance().player != null) {\n            if (RSKeyBindings.OPEN_WIRELESS_GRID.isDown()) {\n                findAndOpen(RSItems.WIRELESS_GRID.get(), RSItems.CREATIVE_WIRELESS_GRID.get());\n            } else if (RSKeyBindings.OPEN_WIRELESS_FLUID_GRID.isDown()) {\n                findAndOpen(RSItems.WIRELESS_FLUID_GRID.get(), RSItems.CREATIVE_WIRELESS_FLUID_GRID.get());\n            } else if (RSKeyBindings.OPEN_PORTABLE_GRID.isDown()) {\n                findAndOpen(RSItems.PORTABLE_GRID.get(), RSItems.CREATIVE_PORTABLE_GRID.get());\n            } else if (RSKeyBindings.OPEN_WIRELESS_CRAFTING_MONITOR.isDown()) {\n                findAndOpen(RSItems.WIRELESS_CRAFTING_MONITOR.get(), RSItems.CREATIVE_WIRELESS_CRAFTING_MONITOR.get());\n            }\n        }\n    }\n\n\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/NetworkTransmitterScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.NetworkTransmitterBlockEntity;\nimport com.refinedmods.refinedstorage.container.NetworkTransmitterContainerMenu;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\n\nimport java.util.Optional;\n\npublic class NetworkTransmitterScreen extends BaseScreen<NetworkTransmitterContainerMenu> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/network_transmitter.png\");\n\n    public NetworkTransmitterScreen(NetworkTransmitterContainerMenu containerMenu, Inventory inventory, Component title) {\n        super(containerMenu, 176, 137, inventory, title);\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE));\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        // NO OP\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight);\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, title.getString());\n\n        String text;\n\n        Optional<ResourceLocation> receiverDim = NetworkTransmitterBlockEntity.RECEIVER_DIMENSION.getValue();\n        int distance = NetworkTransmitterBlockEntity.DISTANCE.getValue();\n\n        if (!receiverDim.isPresent()) {\n            text = I18n.get(\"gui.refinedstorage.network_transmitter.missing_card\");\n        } else if (distance != -1) {\n            text = I18n.get(\"gui.refinedstorage.network_transmitter.distance\", distance);\n        } else {\n            text = receiverDim.get().toString();\n        }\n\n        renderString(graphics, 51, 24, text);\n        renderString(graphics, 7, 42, I18n.get(\"container.inventory\"));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/PriorityScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.minecraft.world.item.ItemStack;\nimport org.apache.commons.lang3.tuple.Pair;\n\npublic class PriorityScreen extends AmountSpecifyingScreen<AbstractContainerMenu> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/priority.png\");\n\n    private final BlockEntitySynchronizationParameter<Integer, ?> priority;\n\n    public PriorityScreen(BaseScreen parent, BlockEntitySynchronizationParameter<Integer, ?> priority, Inventory inventory) {\n        super(parent, new AbstractContainerMenu(null, 0) {\n            @Override\n            public ItemStack quickMoveStack(Player p_38941_, int p_38942_) {\n                return ItemStack.EMPTY;\n            }\n\n            @Override\n            public boolean stillValid(Player player) {\n                return false;\n            }\n        }, 164, 92, inventory, Component.translatable(\"misc.refinedstorage.priority\"));\n\n        this.priority = priority;\n    }\n\n    @Override\n    protected int getDefaultAmount() {\n        return priority.getValue();\n    }\n\n    @Override\n    protected Component getOkButtonText() {\n        return Component.translatable(\"misc.refinedstorage.set\");\n    }\n\n    @Override\n    protected ResourceLocation getTexture() {\n        return TEXTURE;\n    }\n\n    @Override\n    protected Pair<Integer, Integer> getAmountPos() {\n        return Pair.of(18 + 1, 47 + 1);\n    }\n\n    @Override\n    protected Pair<Integer, Integer> getOkCancelPos() {\n        return Pair.of(107, 30);\n    }\n\n    @Override\n    protected boolean canAmountGoNegative() {\n        return true;\n    }\n\n    @Override\n    protected int getMaxAmount() {\n        return Integer.MAX_VALUE;\n    }\n\n    @Override\n    protected int[] getIncrements() {\n        return new int[]{\n            1, 5, 10,\n            -1, -5, -10\n        };\n    }\n\n    @Override\n    protected void onOkButtonPressed(boolean noPreview) {\n        try {\n            int amount = Integer.parseInt(amountField.getValue());\n\n            BlockEntitySynchronizationManager.setParameter(priority, amount);\n\n            close();\n        } catch (NumberFormatException e) {\n            // NO OP\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/RelayScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.container.RelayContainerMenu;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\n\npublic class RelayScreen extends BaseScreen<RelayContainerMenu> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/relay.png\");\n\n    public RelayScreen(RelayContainerMenu containerMenu, Inventory inventory, Component title) {\n        super(containerMenu, 176, 131, inventory, title);\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE));\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        // NO OP\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight);\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, title.getString());\n        renderString(graphics, 7, 39, I18n.get(\"container.inventory\"));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/SecurityManagerScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.SecurityManagerBlockEntity;\nimport com.refinedmods.refinedstorage.container.SecurityManagerContainerMenu;\nimport com.refinedmods.refinedstorage.item.SecurityCardItem;\nimport com.refinedmods.refinedstorage.network.SecurityManagerUpdateMessage;\nimport com.refinedmods.refinedstorage.screen.widget.SmallCheckboxWidget;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.minecraft.world.item.ItemStack;\n\npublic class SecurityManagerScreen extends BaseScreen<SecurityManagerContainerMenu> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/security_manager.png\");\n\n    private final SecurityManagerBlockEntity securityManager;\n    private final SmallCheckboxWidget[] permissions = new SmallCheckboxWidget[Permission.values().length];\n\n    public SecurityManagerScreen(SecurityManagerContainerMenu containerMenu, Inventory inventory, Component title) {\n        super(containerMenu, 176, 234, inventory, title);\n\n        this.securityManager = (SecurityManagerBlockEntity) containerMenu.getBlockEntity();\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE));\n\n        int padding = 15;\n\n        permissions[0] = addCheckBox(x + 7, y + 93, Component.translatable(\"gui.refinedstorage.security_manager.permission.0\"), false, btn -> handle(0));\n        permissions[1] = addCheckBox(permissions[0].getX(), permissions[0].getY() + padding, Component.translatable(\"gui.refinedstorage.security_manager.permission.1\"), false, btn -> handle(1));\n        permissions[2] = addCheckBox(permissions[1].getX(), permissions[1].getY() + padding, Component.translatable(\"gui.refinedstorage.security_manager.permission.2\"), false, btn -> handle(2));\n        permissions[3] = addCheckBox(permissions[0].getX() + 90, permissions[0].getY(), Component.translatable(\"gui.refinedstorage.security_manager.permission.3\"), false, btn -> handle(3));\n        permissions[4] = addCheckBox(permissions[3].getX(), permissions[3].getY() + padding, Component.translatable(\"gui.refinedstorage.security_manager.permission.4\"), false, btn -> handle(4));\n        permissions[5] = addCheckBox(permissions[4].getX(), permissions[4].getY() + padding, Component.translatable(\"gui.refinedstorage.security_manager.permission.5\"), false, btn -> handle(5));\n    }\n\n    private void handle(int i) {\n        RS.NETWORK_HANDLER.sendToServer(new SecurityManagerUpdateMessage(Permission.values()[i], permissions[i].isSelected()));\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        ItemStack card = securityManager.getNode().getEditCard().getStackInSlot(0);\n\n        for (Permission permission : Permission.values()) {\n            permissions[permission.getId()].setSelected(!card.isEmpty() && SecurityCardItem.hasPermission(card, permission));\n        }\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight);\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, title.getString());\n        renderString(graphics, 7, 59, I18n.get(\"gui.refinedstorage.security_manager.configure\"));\n        renderString(graphics, 7, 140, I18n.get(\"container.inventory\"));\n\n        for (int i = 0; i < permissions.length; ++i) {\n            SmallCheckboxWidget permission = permissions[i];\n            if (RenderUtils.inBounds(permission.getX() - leftPos, permission.getY() - topPos, permission.getWidth(), permission.getHeight(), mouseX, mouseY)) {\n                renderTooltip(graphics, mouseX, mouseY, I18n.get(\"gui.refinedstorage.security_manager.permission.\" + i + \".tooltip\"));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/StorageBlockScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.StorageBlockEntity;\nimport com.refinedmods.refinedstorage.container.StorageContainerMenu;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\n\npublic class StorageBlockScreen extends StorageScreen<StorageContainerMenu> {\n    public StorageBlockScreen(StorageContainerMenu containerMenu, Inventory inventory, Component title) {\n        super(\n            containerMenu,\n            inventory,\n            title,\n            new ResourceLocation(RS.ID, \"textures/gui/storage.png\"),\n            new StorageScreenSynchronizationParameters(\n                null,\n                NetworkNodeBlockEntity.REDSTONE_MODE,\n                StorageBlockEntity.COMPARE,\n                StorageBlockEntity.WHITELIST_BLACKLIST,\n                StorageBlockEntity.PRIORITY,\n                StorageBlockEntity.ACCESS_TYPE\n            ),\n            StorageBlockEntity.STORED::getValue,\n            () -> (long) ((StorageBlockEntity) containerMenu.getBlockEntity()).getItemStorageType().getCapacity()\n        );\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/StorageMonitorScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.blockentity.StorageMonitorBlockEntity;\nimport com.refinedmods.refinedstorage.container.StorageMonitorContainerMenu;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.ExactModeSideButton;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.TypeSideButton;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\n\npublic class StorageMonitorScreen extends BaseScreen<StorageMonitorContainerMenu> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/storage_monitor.png\");\n\n    public StorageMonitorScreen(StorageMonitorContainerMenu containerMenu, Inventory inventory, Component title) {\n        super(containerMenu, 211, 137, inventory, title);\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        addSideButton(new TypeSideButton(this, StorageMonitorBlockEntity.TYPE));\n        addSideButton(new ExactModeSideButton(this, StorageMonitorBlockEntity.COMPARE));\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        // NO OP\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight);\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, title.getString());\n        renderString(graphics, 7, 43, I18n.get(\"container.inventory\"));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/StorageScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.*;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\n\nimport java.util.function.Supplier;\n\npublic class StorageScreen<T extends AbstractContainerMenu> extends BaseScreen<T> {\n    private static final int BAR_X = 8;\n    private static final int BAR_Y = 54;\n    private static final int BAR_WIDTH = 16;\n    private static final int BAR_HEIGHT = 70;\n\n    private final ResourceLocation texture;\n    private final StorageScreenSynchronizationParameters parameters;\n    private final Supplier<Long> storedSupplier;\n    private final Supplier<Long> capacitySupplier;\n\n    public StorageScreen(T containerMenu,\n                         Inventory inventory,\n                         Component title,\n                         ResourceLocation texture,\n                         StorageScreenSynchronizationParameters parameters,\n                         Supplier<Long> storedSupplier,\n                         Supplier<Long> capacitySupplier) {\n        super(containerMenu, 176, 223, inventory, title);\n\n        this.texture = texture;\n        this.parameters = parameters;\n        this.storedSupplier = storedSupplier;\n        this.capacitySupplier = capacitySupplier;\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        if (parameters.getRedstoneModeParameter() != null) {\n            addSideButton(new RedstoneModeSideButton(this, parameters.getRedstoneModeParameter()));\n        }\n\n        if (parameters.getTypeParameter() != null) {\n            addSideButton(new TypeSideButton(this, parameters.getTypeParameter()));\n        }\n\n        if (parameters.getWhitelistBlacklistParameter() != null) {\n            addSideButton(new WhitelistBlacklistSideButton(this, parameters.getWhitelistBlacklistParameter()));\n        }\n\n        if (parameters.getExactModeParameter() != null) {\n            addSideButton(new ExactModeSideButton(this, parameters.getExactModeParameter()));\n        }\n\n        if (parameters.getAccessTypeParameter() != null) {\n            addSideButton(new AccessTypeSideButton(this, parameters.getAccessTypeParameter()));\n        }\n\n        int buttonWidth = 10 + font.width(I18n.get(\"misc.refinedstorage.priority\"));\n\n        addButton(\n            x + 169 - buttonWidth,\n            y + 41, buttonWidth,\n            20,\n            Component.translatable(\"misc.refinedstorage.priority\"),\n            true,\n            true,\n            btn -> minecraft.setScreen(new PriorityScreen(this, parameters.getPriorityParameter(), inventory))\n        );\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        // NO OP\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        graphics.blit(texture, x, y, 0, 0, imageWidth, imageHeight);\n\n        int barHeightNew = capacitySupplier.get() < 0 ? 0 : (int) ((float) storedSupplier.get() / (float) capacitySupplier.get() * (float) BAR_HEIGHT);\n\n        graphics.blit(texture, x + BAR_X, y + BAR_Y + BAR_HEIGHT - barHeightNew, 179, BAR_HEIGHT - barHeightNew, BAR_WIDTH, barHeightNew);\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, title.getString());\n        renderString(graphics, 7, 42, capacitySupplier.get() == -1 ?\n            I18n.get(\"misc.refinedstorage.storage.stored_minimal\", API.instance().getQuantityFormatter().formatWithUnits(storedSupplier.get())) :\n            I18n.get(\"misc.refinedstorage.storage.stored_capacity_minimal\", API.instance().getQuantityFormatter().formatWithUnits(storedSupplier.get()), API.instance().getQuantityFormatter().formatWithUnits(capacitySupplier.get()))\n        );\n\n        renderString(graphics, 7, 129, I18n.get(\"container.inventory\"));\n\n        if (RenderUtils.inBounds(BAR_X, BAR_Y, BAR_WIDTH, BAR_HEIGHT, mouseX, mouseY)) {\n            int full = 0;\n\n            if (capacitySupplier.get() >= 0) {\n                full = (int) ((float) storedSupplier.get() / (float) capacitySupplier.get() * 100f);\n            }\n\n            renderTooltip(graphics, mouseX, mouseY, (capacitySupplier.get() == -1 ?\n                I18n.get(\"misc.refinedstorage.storage.stored_minimal\", API.instance().getQuantityFormatter().format(storedSupplier.get())) :\n                I18n.get(\"misc.refinedstorage.storage.stored_capacity_minimal\", API.instance().getQuantityFormatter().format(storedSupplier.get()), API.instance().getQuantityFormatter().format(capacitySupplier.get()))\n            ) + \"\\n\" + ChatFormatting.GRAY + I18n.get(\"misc.refinedstorage.storage.full\", full));\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/StorageScreenSynchronizationParameters.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\n\nimport javax.annotation.Nullable;\n\npublic class StorageScreenSynchronizationParameters {\n    @Nullable\n    private final BlockEntitySynchronizationParameter<Integer, ?> typeParameter;\n    @Nullable\n    private final BlockEntitySynchronizationParameter<Integer, ?> redstoneModeParameter;\n    @Nullable\n    private final BlockEntitySynchronizationParameter<Integer, ?> exactModeParameter;\n    @Nullable\n    private final BlockEntitySynchronizationParameter<Integer, ?> whitelistBlacklistParameter;\n    private final BlockEntitySynchronizationParameter<Integer, ?> priorityParameter;\n    @Nullable\n    private final BlockEntitySynchronizationParameter<AccessType, ?> accessTypeParameter;\n\n    public StorageScreenSynchronizationParameters(@Nullable BlockEntitySynchronizationParameter<Integer, ?> typeParameter, @Nullable BlockEntitySynchronizationParameter<Integer, ?> redstoneModeParameter, @Nullable BlockEntitySynchronizationParameter<Integer, ?> exactModeParameter, @Nullable BlockEntitySynchronizationParameter<Integer, ?> whitelistBlacklistParameter, BlockEntitySynchronizationParameter<Integer, ?> priorityParameter, @Nullable BlockEntitySynchronizationParameter<AccessType, ?> accessTypeParameter) {\n        this.typeParameter = typeParameter;\n        this.redstoneModeParameter = redstoneModeParameter;\n        this.exactModeParameter = exactModeParameter;\n        this.whitelistBlacklistParameter = whitelistBlacklistParameter;\n        this.priorityParameter = priorityParameter;\n        this.accessTypeParameter = accessTypeParameter;\n    }\n\n    @Nullable\n    public BlockEntitySynchronizationParameter<Integer, ?> getTypeParameter() {\n        return typeParameter;\n    }\n\n    @Nullable\n    public BlockEntitySynchronizationParameter<Integer, ?> getRedstoneModeParameter() {\n        return redstoneModeParameter;\n    }\n\n    @Nullable\n    public BlockEntitySynchronizationParameter<Integer, ?> getExactModeParameter() {\n        return exactModeParameter;\n    }\n\n    @Nullable\n    public BlockEntitySynchronizationParameter<Integer, ?> getWhitelistBlacklistParameter() {\n        return whitelistBlacklistParameter;\n    }\n\n    public BlockEntitySynchronizationParameter<Integer, ?> getPriorityParameter() {\n        return priorityParameter;\n    }\n\n    @Nullable\n    public BlockEntitySynchronizationParameter<AccessType, ?> getAccessTypeParameter() {\n        return accessTypeParameter;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/WirelessTransmitterScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.WirelessTransmitterBlockEntity;\nimport com.refinedmods.refinedstorage.container.WirelessTransmitterContainerMenu;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\n\npublic class WirelessTransmitterScreen extends BaseScreen<WirelessTransmitterContainerMenu> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/wireless_transmitter.png\");\n\n    public WirelessTransmitterScreen(WirelessTransmitterContainerMenu containerMenu, Inventory inventory, Component title) {\n        super(containerMenu, 211, 137, inventory, title);\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE));\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        // NO OP\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight);\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, title.getString());\n        renderString(graphics, 28, 25, I18n.get(\"gui.refinedstorage.wireless_transmitter.distance\", WirelessTransmitterBlockEntity.RANGE.getValue()));\n        renderString(graphics, 7, 43, I18n.get(\"container.inventory\"));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/factory/CrafterManagerScreenFactory.java",
    "content": "package com.refinedmods.refinedstorage.screen.factory;\n\nimport com.refinedmods.refinedstorage.container.CrafterManagerContainerMenu;\nimport com.refinedmods.refinedstorage.screen.CrafterManagerScreen;\nimport net.minecraft.client.gui.screens.MenuScreens;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.world.entity.player.Inventory;\n\npublic class CrafterManagerScreenFactory implements MenuScreens.ScreenConstructor<CrafterManagerContainerMenu, CrafterManagerScreen> {\n    @Override\n    public CrafterManagerScreen create(CrafterManagerContainerMenu container, Inventory playerInventory, Component title) {\n        CrafterManagerScreen screen = new CrafterManagerScreen(container, playerInventory, title);\n\n        container.setScreenInfoProvider(screen);\n\n        return screen;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/factory/GridScreenFactory.java",
    "content": "package com.refinedmods.refinedstorage.screen.factory;\n\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport com.refinedmods.refinedstorage.screen.grid.GridScreen;\nimport net.minecraft.client.gui.screens.MenuScreens;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.world.entity.player.Inventory;\n\npublic class GridScreenFactory implements MenuScreens.ScreenConstructor<GridContainerMenu, GridScreen> {\n    @Override\n    public GridScreen create(GridContainerMenu container, Inventory inv, Component title) {\n        GridScreen screen = new GridScreen(container, container.getGrid(), inv, title);\n\n        container.setScreenInfoProvider(screen);\n\n        return screen;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/AlternativesScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid;\n\nimport com.mojang.blaze3d.systems.RenderSystem;\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport com.refinedmods.refinedstorage.blockentity.grid.GridBlockEntity;\nimport com.refinedmods.refinedstorage.container.AlternativesContainerMenu;\nimport com.refinedmods.refinedstorage.render.FluidRenderer;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.screen.widget.SmallCheckboxWidget;\nimport com.refinedmods.refinedstorage.screen.widget.ScrollbarWidget;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.gui.components.Button;\nimport net.minecraft.client.gui.screens.Screen;\nimport net.minecraft.core.Holder;\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.tags.TagKey;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.material.Fluid;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.fluids.FluidType;\nimport org.lwjgl.glfw.GLFW;\n\nimport java.util.*;\nimport java.util.stream.Collectors;\n\npublic class AlternativesScreen extends BaseScreen<AlternativesContainerMenu> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/alternatives.png\");\n\n    private static final int VISIBLE_ROWS = 5;\n\n    private final Screen parent;\n    private final ScrollbarWidget scrollbar;\n\n    private final List<Line> lines = new ArrayList<>();\n\n    private int type;\n    private int slot;\n    private ItemStack item;\n    private FluidStack fluid;\n\n    private AlternativesScreen(Screen parent, Player player, Component title) {\n        super(new AlternativesContainerMenu(player), 175, 143, player.getInventory(), title);\n\n        this.parent = parent;\n        this.scrollbar = new ScrollbarWidget(this, 155, 20, 12, 89);\n    }\n\n    public AlternativesScreen(Screen parent, Player player, Component title, ItemStack item, int slot) {\n        this(parent, player, title);\n\n        this.type = IType.ITEMS;\n        this.slot = slot;\n        this.item = item;\n        this.fluid = null;\n    }\n\n    public AlternativesScreen(Screen parent, Player player, Component title, FluidStack fluid, int slot) {\n        this(parent, player, title);\n\n        this.type = IType.FLUIDS;\n        this.slot = slot;\n        this.item = null;\n        this.fluid = fluid;\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        lines.clear();\n\n        if (item != null) {\n            lines.add(new ItemLine(item));\n\n            Collection<TagKey<Item>> tagsOfItem = BuiltInRegistries.ITEM.getResourceKey(item.getItem())\n                .flatMap(k -> BuiltInRegistries.ITEM.getHolder(k)\n                    .map(holder -> holder.tags().collect(Collectors.toSet())))\n                .orElse(Collections.emptySet());\n\n            for (TagKey<Item> owningTag : tagsOfItem) {\n                lines.add(new TagLine(owningTag.location(), GridBlockEntity.ALLOWED_ITEM_TAGS.getValue().get(slot).contains(owningTag.location())));\n\n                int itemCount = 0;\n\n                ItemListLine line = new ItemListLine();\n\n                for (Holder<Item> itemInTag : BuiltInRegistries.ITEM.getTagOrEmpty(owningTag)) {\n                    if (itemCount > 0 && itemCount % 8 == 0) {\n                        lines.add(line);\n                        line = new ItemListLine();\n                    }\n\n                    itemCount++;\n\n                    line.addItem(new ItemStack(itemInTag));\n                }\n\n                lines.add(line);\n            }\n        } else if (fluid != null) {\n            lines.add(new FluidLine(fluid));\n\n            Collection<TagKey<Fluid>> tagsOfFluid = BuiltInRegistries.FLUID.getResourceKey(fluid.getFluid())\n                .flatMap(k -> BuiltInRegistries.FLUID.getHolder(k)\n                    .map(holder -> holder.tags().collect(Collectors.toSet())))\n                .orElse(Collections.emptySet());\n\n            for (TagKey<Fluid> owningTag : tagsOfFluid) {\n                lines.add(new TagLine(owningTag.location(), GridBlockEntity.ALLOWED_FLUID_TAGS.getValue().get(slot).contains(owningTag.location())));\n\n                int fluidCount = 0;\n\n                FluidListLine line = new FluidListLine();\n\n                for (Holder<Fluid> fluidInTag : BuiltInRegistries.FLUID.getTagOrEmpty(owningTag)) {\n                    if (fluidCount > 0 && fluidCount % 8 == 0) {\n                        lines.add(line);\n                        line = new FluidListLine();\n                    }\n\n                    fluidCount++;\n\n                    line.addFluid(new FluidStack(fluidInTag, FluidType.BUCKET_VOLUME));\n                }\n\n                lines.add(line);\n            }\n        }\n\n        // Do an initial layout\n        int xx = 8;\n        int yy = 20;\n\n        for (int i = 0; i < lines.size(); ++i) {\n            boolean visible = i >= scrollbar.getOffset() && i < scrollbar.getOffset() + VISIBLE_ROWS;\n\n            if (visible) {\n                lines.get(i).layoutDependantControls(true, leftPos + xx + 3, topPos + yy + 3);\n\n                yy += 18;\n            }\n        }\n\n        Button apply = addButton(x + 7, y + 114, 50, 20, Component.translatable(\"gui.refinedstorage.alternatives.apply\"), lines.size() > 1, true, btn -> apply());\n        addButton(x + apply.getWidth() + 7 + 4, y + 114, 50, 20, Component.translatable(\"gui.cancel\"), true, true, btn -> close());\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        scrollbar.setEnabled(getRows() > VISIBLE_ROWS);\n        scrollbar.setMaxOffset(getRows() - VISIBLE_ROWS);\n    }\n\n    private int getRows() {\n        return lines.size();\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight);\n        scrollbar.render(graphics);\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, title.getString());\n\n        int x = 8;\n        int y = 20;\n\n        for (int i = 0; i < lines.size(); ++i) {\n            boolean visible = i >= scrollbar.getOffset() && i < scrollbar.getOffset() + VISIBLE_ROWS;\n\n            if (visible) {\n                lines.get(i).layoutDependantControls(true, leftPos + x + 3, topPos + y + 3);\n                lines.get(i).render(graphics, x, y);\n\n                y += 18;\n            } else {\n                lines.get(i).layoutDependantControls(false, -100, -100);\n            }\n        }\n\n        x = 8;\n        y = 20;\n\n        for (int i = 0; i < lines.size(); ++i) {\n            boolean visible = i >= scrollbar.getOffset() && i < scrollbar.getOffset() + VISIBLE_ROWS;\n\n            if (visible) {\n                lines.get(i).renderTooltip(graphics, x, y, mouseX, mouseY);\n\n                y += 18;\n            }\n        }\n    }\n\n    @Override\n    public void mouseMoved(double mx, double my) {\n        scrollbar.mouseMoved(mx, my);\n\n        super.mouseMoved(mx, my);\n    }\n\n    @Override\n    public boolean mouseClicked(double mx, double my, int button) {\n        return scrollbar.mouseClicked(mx, my, button) || super.mouseClicked(mx, my, button);\n    }\n\n    @Override\n    public boolean mouseReleased(double mx, double my, int button) {\n        return scrollbar.mouseReleased(mx, my, button) || super.mouseReleased(mx, my, button);\n    }\n\n    @Override\n    public boolean mouseScrolled(double x, double y, double z, double delta) {\n        return this.scrollbar.mouseScrolled(x, y, z, delta) || super.mouseScrolled(x, y, z, delta);\n    }\n\n    @Override\n    public boolean keyPressed(int key, int scanCode, int modifiers) {\n        if (key == GLFW.GLFW_KEY_ESCAPE) {\n            close();\n\n            return true;\n        }\n\n        return super.keyPressed(key, scanCode, modifiers);\n    }\n\n    private void close() {\n        minecraft.setScreen(parent);\n    }\n\n    private void apply() {\n        Set<ResourceLocation> allowed = new HashSet<>();\n\n        for (Line line : lines) {\n            if (line instanceof TagLine) {\n                TagLine tagLine = (TagLine) line;\n\n                if (tagLine.widget.isSelected()) {\n                    allowed.add(tagLine.tagName);\n                }\n            }\n        }\n\n        if (type == IType.ITEMS) {\n            List<Set<ResourceLocation>> existing = GridBlockEntity.ALLOWED_ITEM_TAGS.getValue();\n\n            existing.set(slot, allowed);\n\n            BlockEntitySynchronizationManager.setParameter(GridBlockEntity.ALLOWED_ITEM_TAGS, existing);\n        } else if (type == IType.FLUIDS) {\n            List<Set<ResourceLocation>> existing = GridBlockEntity.ALLOWED_FLUID_TAGS.getValue();\n\n            existing.set(slot, allowed);\n\n            BlockEntitySynchronizationManager.setParameter(GridBlockEntity.ALLOWED_FLUID_TAGS, existing);\n        }\n\n        close();\n    }\n\n    private interface Line {\n        default void render(GuiGraphics graphics, int x, int y) {\n        }\n\n        default void renderTooltip(GuiGraphics graphics, int x, int y, int mx, int my) {\n        }\n\n        default void layoutDependantControls(boolean visible, int x, int y) {\n        }\n    }\n\n    private class ItemLine implements Line {\n        private final ItemStack item;\n\n        public ItemLine(ItemStack item) {\n            this.item = item;\n        }\n\n        @Override\n        public void render(GuiGraphics graphics, int x, int y) {\n            RenderSystem.setShaderColor(1, 1, 1, 1);\n            renderItem(graphics, x + 3, y + 2, item);\n            renderString(graphics, x + 4 + 19, y + 7, item.getHoverName().getString());\n        }\n    }\n\n    private class FluidLine implements Line {\n        private final FluidStack fluid;\n\n        public FluidLine(FluidStack item) {\n            this.fluid = item;\n        }\n\n        @Override\n        public void render(GuiGraphics graphics, int x, int y) {\n            FluidRenderer.INSTANCE.render(graphics, x + 3, y + 2, fluid);\n            renderString(graphics, x + 4 + 19, y + 7, fluid.getDisplayName().getString());\n        }\n    }\n\n    private class TagLine implements Line {\n        private final ResourceLocation tagName;\n        private final SmallCheckboxWidget widget;\n\n        public TagLine(ResourceLocation tagName, boolean checked) {\n            this.tagName = tagName;\n            this.widget = addCheckBox(-100, -100, Component.literal(RenderUtils.shorten(tagName.toString(), 22)), checked, btn -> {\n                // NO OP\n            });\n            widget.setFGColor(0xFF373737);\n            widget.setShadow(false);\n        }\n\n        @Override\n        public void layoutDependantControls(boolean visible, int x, int y) {\n            widget.visible = visible;\n            widget.setX(x);\n            widget.setY(y);\n        }\n    }\n\n    private class ItemListLine implements Line {\n        private final List<ItemStack> items = new ArrayList<>();\n\n        public void addItem(ItemStack stack) {\n            items.add(stack);\n        }\n\n        @Override\n        public void render(GuiGraphics graphics, int x, int y) {\n            for (ItemStack itemInList : items) {\n                renderItem(graphics, x + 3, y, itemInList);\n\n                x += 17;\n            }\n        }\n\n        @Override\n        public void renderTooltip(GuiGraphics graphics, int x, int y, int mx, int my) {\n            for (ItemStack itemInList : items) {\n                if (RenderUtils.inBounds(x + 3, y, 16, 16, mx, my)) {\n                    AlternativesScreen.this.renderTooltip(graphics, itemInList, mx, my, RenderUtils.getTooltipFromItem(itemInList));\n                }\n\n                x += 17;\n            }\n        }\n    }\n\n    private class FluidListLine implements Line {\n        private final List<FluidStack> fluids = new ArrayList<>();\n\n        public void addFluid(FluidStack stack) {\n            fluids.add(stack);\n        }\n\n        @Override\n        public void render(GuiGraphics graphics, int x, int y) {\n            for (FluidStack fluidInList : fluids) {\n                FluidRenderer.INSTANCE.render(graphics, x + 3, y, fluidInList);\n\n                x += 17;\n            }\n        }\n\n        @Override\n        public void renderTooltip(GuiGraphics graphics, int x, int y, int mx, int my) {\n            for (FluidStack fluidInList : fluids) {\n                if (RenderUtils.inBounds(x + 3, y, 16, 16, mx, my)) {\n                    AlternativesScreen.this.renderTooltip(graphics, mx, my, fluidInList.getDisplayName().getString());\n                }\n\n                x += 17;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/CraftingPreviewScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid;\n\nimport com.mojang.blaze3d.platform.Lighting;\nimport com.mojang.blaze3d.systems.RenderSystem;\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;\nimport com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;\nimport com.refinedmods.refinedstorage.api.render.IElementDrawers;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.ErrorCraftingPreviewElement;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.FluidCraftingPreviewElement;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.ItemCraftingPreviewElement;\nimport com.refinedmods.refinedstorage.apiimpl.render.CraftingPreviewElementDrawers;\nimport com.refinedmods.refinedstorage.item.PatternItem;\nimport com.refinedmods.refinedstorage.network.grid.GridCraftingStartRequestMessage;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.screen.widget.ScrollbarWidget;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.gui.components.Button;\nimport net.minecraft.client.gui.screens.Screen;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.TooltipFlag;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport org.lwjgl.glfw.GLFW;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.UUID;\n\npublic class CraftingPreviewScreen extends BaseScreen<AbstractContainerMenu> {\n    private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/crafting_preview.png\");\n\n    private static final int VISIBLE_ROWS = 5;\n\n    private final List<ICraftingPreviewElement> elements;\n    private final Screen parent;\n\n    private final ScrollbarWidget scrollbar;\n\n    private final UUID id;\n    private final int quantity;\n    private final boolean fluids;\n    private final IElementDrawers drawers = new CraftingPreviewElementDrawers(this);\n    private ItemStack hoveringStack;\n    private FluidStack hoveringFluid;\n\n    public CraftingPreviewScreen(Screen parent, List<ICraftingPreviewElement> elements, UUID id, int quantity, boolean fluids, Component title, Inventory inventory) {\n        super(new AbstractContainerMenu(null, 0) {\n            @Override\n            public ItemStack quickMoveStack(Player p_38941_, int p_38942_) {\n                return ItemStack.EMPTY;\n            }\n\n            @Override\n            public boolean stillValid(@Nonnull Player player) {\n                return false;\n            }\n        }, 254, 201, inventory, title);\n\n        this.elements = new ArrayList<>(elements);\n        this.parent = parent;\n\n        this.id = id;\n        this.quantity = quantity;\n        this.fluids = fluids;\n\n        this.scrollbar = new ScrollbarWidget(this, 235, 20, 12, 149);\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        addButton(x + 55, y + 201 - 20 - 7, 50, 20, Component.translatable(\"gui.cancel\"), true, true, btn -> close());\n\n        Button startButton = addButton(x + 129, y + 201 - 20 - 7, 50, 20, Component.translatable(\"misc.refinedstorage.start\"), true, true, btn -> startRequest());\n        startButton.active = elements.stream().noneMatch(ICraftingPreviewElement::doesDisableTaskStarting);\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        scrollbar.setEnabled(getRows() > VISIBLE_ROWS);\n        scrollbar.setMaxOffset(getRows() - VISIBLE_ROWS);\n    }\n\n    @Nullable\n    private ErrorCraftingPreviewElement getError() {\n        if (elements.size() == 1 && elements.get(0) instanceof ErrorCraftingPreviewElement) {\n            return (ErrorCraftingPreviewElement) elements.get(0);\n        }\n\n        return null;\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight);\n\n        if (getError() != null) {\n            graphics.fill(x + 7, y + 20, x + 228, y + 169, 0xFFDBDBDB);\n        }\n\n        scrollbar.render(graphics);\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, title.getString());\n\n        int x = 7;\n        int y = 15;\n\n        float scale = Minecraft.getInstance().isEnforceUnicode() ? 1F : 0.5F;\n\n        ErrorCraftingPreviewElement error = getError();\n        if (error != null) {\n            renderError(graphics, x, y, scale, error);\n        } else {\n            renderPreview(graphics, mouseX, mouseY, x, y);\n        }\n    }\n\n    private void renderPreview(GuiGraphics graphics, int mouseX, int mouseY, int x, int y) {\n        int slot = scrollbar != null ? (scrollbar.getOffset() * 3) : 0;\n\n        Lighting.setupFor3DItems();\n        RenderSystem.enableDepthTest();\n\n        this.hoveringStack = null;\n        this.hoveringFluid = null;\n\n        for (int i = 0; i < 3 * 5; ++i) {\n            if (slot < elements.size()) {\n                renderElement(graphics, mouseX, mouseY, x, y, elements.get(slot));\n            }\n\n            if ((i + 1) % 3 == 0) {\n                x = 7;\n                y += 30;\n            } else {\n                x += 74;\n            }\n\n            slot++;\n        }\n    }\n\n    private void renderElement(GuiGraphics graphics, int mouseX, int mouseY, int x, int y, ICraftingPreviewElement element) {\n        element.draw(graphics, x, y + 5, drawers);\n\n        if (RenderUtils.inBounds(x + 5, y + 7, 16, 16, mouseX, mouseY)) {\n            this.hoveringStack = element instanceof ItemCraftingPreviewElement ? ((ItemCraftingPreviewElement) element).getStack() : null;\n\n            if (this.hoveringStack == null) {\n                this.hoveringFluid = element instanceof FluidCraftingPreviewElement ? ((FluidCraftingPreviewElement) element).getStack() : null;\n            }\n        }\n    }\n\n    private void renderError(GuiGraphics graphics, int x, int y, float scale, ErrorCraftingPreviewElement errorElement) {\n        final PoseStack poseStack = graphics.pose();\n        poseStack.pushPose();\n        poseStack.scale(scale, scale, 1);\n\n        renderString(graphics, RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 11, scale), I18n.get(\"gui.refinedstorage.crafting_preview.error\"));\n\n        switch (errorElement.getType()) {\n            case RECURSIVE:\n                renderRecursiveError(graphics, x, y, scale, errorElement.getRecursedPattern());\n                break;\n            case TOO_COMPLEX:\n                renderTooComplexError(graphics, x, y, scale);\n                break;\n            default:\n                break;\n        }\n\n        poseStack.popPose();\n    }\n\n    private void renderTooComplexError(GuiGraphics graphics, int x, int y, float scale) {\n        renderString(graphics, RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 21, scale), I18n.get(\"gui.refinedstorage.crafting_preview.error.too_complex.0\"));\n        renderString(graphics, RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 31, scale), I18n.get(\"gui.refinedstorage.crafting_preview.error.too_complex.1\"));\n    }\n\n    private void renderRecursiveError(GuiGraphics graphics, int x, int y, float scale, ItemStack recursedPattern) {\n        renderString(graphics, RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 21, scale), I18n.get(\"gui.refinedstorage.crafting_preview.error.recursive.0\"));\n        renderString(graphics, RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 31, scale), I18n.get(\"gui.refinedstorage.crafting_preview.error.recursive.1\"));\n        renderString(graphics, RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 41, scale), I18n.get(\"gui.refinedstorage.crafting_preview.error.recursive.2\"));\n        renderString(graphics, RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 51, scale), I18n.get(\"gui.refinedstorage.crafting_preview.error.recursive.3\"));\n\n        renderString(graphics, RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 61, scale), I18n.get(\"gui.refinedstorage.crafting_preview.error.recursive.4\"));\n\n        ICraftingPattern pattern = PatternItem.fromCache(parent.getMinecraft().level, recursedPattern);\n\n        int yy = 83;\n        for (ItemStack output : pattern.getOutputs()) {\n            if (output != null) {\n                renderString(graphics, RenderUtils.getOffsetOnScale(x + 25, scale), RenderUtils.getOffsetOnScale(yy + 6, scale), output.getHoverName().getString());\n\n                Lighting.setupFor3DItems();\n                RenderSystem.enableDepthTest();\n                renderItem(graphics, x + 5, yy, output);\n\n                yy += 17;\n            }\n        }\n    }\n\n    @Override\n    public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {\n        super.render(graphics, mouseX, mouseY, partialTicks);\n\n        if (hoveringStack != null) {\n            renderTooltip(\n                graphics,\n                hoveringStack,\n                mouseX,\n                mouseY,\n                hoveringStack.getTooltipLines(\n                    Minecraft.getInstance().player,\n                    Minecraft.getInstance().options.advancedItemTooltips ? TooltipFlag.Default.ADVANCED : TooltipFlag.Default.NORMAL\n                )\n            );\n        } else if (hoveringFluid != null) {\n            renderTooltip(graphics, mouseX, mouseY, hoveringFluid.getDisplayName().getString());\n        }\n    }\n\n    @Override\n    public void mouseMoved(double mx, double my) {\n        scrollbar.mouseMoved(mx, my);\n\n        super.mouseMoved(mx, my);\n    }\n\n    @Override\n    public boolean mouseClicked(double mx, double my, int button) {\n        return scrollbar.mouseClicked(mx, my, button) || super.mouseClicked(mx, my, button);\n    }\n\n    @Override\n    public boolean mouseReleased(double mx, double my, int button) {\n        return scrollbar.mouseReleased(mx, my, button) || super.mouseReleased(mx, my, button);\n    }\n\n    @Override\n    public boolean mouseScrolled(double x, double y, double z, double delta) {\n        return this.scrollbar.mouseScrolled(x, y, z, delta) || super.mouseScrolled(x, y, z, delta);\n    }\n\n    @Override\n    public boolean keyPressed(int key, int scanCode, int modifiers) {\n        if (key == GLFW.GLFW_KEY_ENTER || key == GLFW.GLFW_KEY_KP_ENTER) {\n            startRequest();\n\n            return true;\n        }\n\n        if (key == GLFW.GLFW_KEY_ESCAPE) {\n            close();\n\n            return true;\n        }\n\n        return super.keyPressed(key, scanCode, modifiers);\n    }\n\n    private void startRequest() {\n        RS.NETWORK_HANDLER.sendToServer(new GridCraftingStartRequestMessage(id, quantity, fluids));\n\n        close();\n    }\n\n    private int getRows() {\n        return Math.max(0, (int) Math.ceil((float) elements.size() / 3F));\n    }\n\n    private void close() {\n        minecraft.setScreen(parent);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/CraftingSettingsScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.container.CraftingSettingsContainerMenu;\nimport com.refinedmods.refinedstorage.network.grid.GridCraftingPreviewRequestMessage;\nimport com.refinedmods.refinedstorage.screen.AmountSpecifyingScreen;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.screen.grid.stack.FluidGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.world.entity.player.Player;\nimport net.neoforged.neoforge.fluids.FluidType;\n\npublic class CraftingSettingsScreen extends AmountSpecifyingScreen<CraftingSettingsContainerMenu> {\n    private final IGridStack stack;\n\n    public CraftingSettingsScreen(BaseScreen parent, Player player, IGridStack stack) {\n        super(parent, new CraftingSettingsContainerMenu(player, stack), 172, 99, player.getInventory(), Component.translatable(\"container.crafting\"));\n\n        this.stack = stack;\n    }\n\n    @Override\n    protected Component getOkButtonText() {\n        return Component.translatable(\"misc.refinedstorage.start\");\n    }\n\n    @Override\n    protected int[] getIncrements() {\n        if (stack instanceof FluidGridStack) {\n            return new int[]{\n                100, 500, 1000,\n                -100, -500, -1000\n            };\n        } else {\n            return new int[]{\n                1, 10, 64,\n                -1, -10, -64\n            };\n        }\n    }\n\n    @Override\n    protected int getDefaultAmount() {\n        return stack instanceof FluidGridStack ? FluidType.BUCKET_VOLUME : 1;\n    }\n\n    @Override\n    protected boolean canAmountGoNegative() {\n        return false;\n    }\n\n    @Override\n    protected int getMaxAmount() {\n        return Integer.MAX_VALUE;\n    }\n\n    @Override\n    protected void onOkButtonPressed(boolean shiftDown) {\n        try {\n            int quantity = Integer.parseInt(amountField.getValue());\n\n            RS.NETWORK_HANDLER.sendToServer(new GridCraftingPreviewRequestMessage(stack.getId(), quantity, shiftDown, stack instanceof FluidGridStack));\n\n            okButton.active = false;\n        } catch (NumberFormatException e) {\n            // NO OP\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/GridScreen.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid;\n\nimport com.mojang.blaze3d.platform.Lighting;\nimport com.mojang.blaze3d.systems.RenderSystem;\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSKeyBindings;\nimport com.refinedmods.refinedstorage.api.network.grid.GridType;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.render.ElementDrawers;\nimport com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport com.refinedmods.refinedstorage.blockentity.grid.GridBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.grid.portable.IPortableGrid;\nimport com.refinedmods.refinedstorage.blockentity.grid.portable.PortableGridBlockEntity;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport com.refinedmods.refinedstorage.network.grid.*;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.screen.IScreenInfoProvider;\nimport com.refinedmods.refinedstorage.screen.grid.sorting.*;\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.view.GridViewImpl;\nimport com.refinedmods.refinedstorage.screen.grid.view.IGridView;\nimport com.refinedmods.refinedstorage.screen.widget.SmallCheckboxWidget;\nimport com.refinedmods.refinedstorage.screen.widget.ScrollbarWidget;\nimport com.refinedmods.refinedstorage.screen.widget.SearchWidget;\nimport com.refinedmods.refinedstorage.screen.widget.TabListWidget;\nimport com.refinedmods.refinedstorage.screen.widget.sidebutton.*;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport com.refinedmods.refinedstorage.util.TimeUtils;\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent;\nimport net.minecraft.client.gui.screens.inventory.tooltip.DefaultTooltipPositioner;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.client.resources.sounds.SimpleSoundInstance;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.network.chat.FormattedText;\nimport net.minecraft.network.chat.MutableComponent;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.sounds.SoundEvents;\nimport net.minecraft.world.entity.player.Inventory;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.client.ClientHooks;\nimport org.lwjgl.glfw.GLFW;\nimport yalter.mousetweaks.api.MouseTweaksDisableWheelTweak;\n\nimport java.util.ArrayList;\nimport java.util.LinkedList;\nimport java.util.List;\n\n@MouseTweaksDisableWheelTweak\npublic class GridScreen extends BaseScreen<GridContainerMenu> implements IScreenInfoProvider {\n    private static final ResourceLocation PORTABLE_GRID_TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/portable_grid.png\");\n    private static final ResourceLocation CRAFTING_GRID_TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/crafting_grid.png\");\n    private static final ResourceLocation PATTERN_GRID_TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/pattern_grid.png\");\n    private static final ResourceLocation PATTERN_GRID_PROCESSING_TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/pattern_grid_processing.png\");\n    private static final ResourceLocation GRID_TEXTURE = new ResourceLocation(RS.ID, \"textures/gui/grid.png\");\n\n    private static String searchQuery = \"\";\n    private final IGrid grid;\n    private final TabListWidget<GridContainerMenu> tabs;\n    private final int patternScrollOffsetAbsoluteMax = GridNetworkNode.PROCESSING_MATRIX_SIZE / 3 - 3;\n    private IGridView view;\n    private SearchWidget searchField;\n    private SmallCheckboxWidget exactPattern;\n    private SmallCheckboxWidget processingPattern;\n    private SmallCheckboxWidget fluidCheckBox;\n    private ScrollbarWidget scrollbar;\n    private ScrollbarWidget patternScrollbar;\n    private boolean wasConnected;\n    private boolean doSort;\n    private int slotNumber;\n    private int slotNumberX;\n    private int slotNumberY;\n    private int patternScrollOffset;\n    private int patternScrollOffsetMax;\n    private boolean updatePatternOffset;\n\n    public GridScreen(GridContainerMenu containerMenu, IGrid grid, Inventory inventory, Component title) {\n        super(containerMenu, 227, 0, inventory, title);\n\n        this.grid = grid;\n        this.view = new GridViewImpl(this, getDefaultSorter(), getSorters());\n        this.wasConnected = this.grid.isGridActive();\n        this.tabs = new TabListWidget<>(this, new ElementDrawers<>(this), grid::getTabs, grid::getTotalTabPages, grid::getTabPage, grid::getTabSelected, IGrid.TABS_PER_PAGE);\n        this.tabs.addListener(new TabListWidget.ITabListListener() {\n            @Override\n            public void onSelectionChanged(int tab) {\n                grid.onTabSelectionChanged(tab);\n            }\n\n            @Override\n            public void onPageChanged(int page) {\n                grid.onTabPageChanged(page);\n            }\n        });\n\n        if (grid instanceof GridNetworkNode && grid.getGridType() == GridType.PATTERN) {\n            GridNetworkNode node = (GridNetworkNode) grid;\n            node.getProcessingMatrix().addListener((handler, slot, reading) -> updatePatternOffset = true);\n            node.getProcessingMatrixFluids().addListener((handler, slot, reading) -> updatePatternOffset = true);\n        }\n    }\n\n    public static List<IGridSorter> getSorters() {\n        List<IGridSorter> sorters = new LinkedList<>();\n        sorters.add(getDefaultSorter());\n        sorters.add(new QuantityGridSorter());\n        sorters.add(new IdGridSorter());\n        sorters.add(new LastModifiedGridSorter());\n\n        return sorters;\n    }\n\n    public static IGridSorter getDefaultSorter() {\n        return new NameGridSorter();\n    }\n\n    @Override\n    protected void onPreInit() {\n        super.onPreInit();\n        this.doSort = true;\n        this.imageHeight = getTopHeight() + getBottomHeight() + (getVisibleRows() * 18);\n    }\n\n    @Override\n    public void onPostInit(int x, int y) {\n        this.menu.initSlots();\n\n        this.tabs.init(imageWidth - 32);\n\n        this.scrollbar = new ScrollbarWidget(this, 174, getTopHeight(), 12, (getVisibleRows() * 18) - 2);\n\n        if (grid instanceof GridNetworkNode || grid instanceof PortableGridBlockEntity) {\n            addSideButton(new RedstoneModeSideButton(this, grid instanceof GridNetworkNode ? NetworkNodeBlockEntity.REDSTONE_MODE : PortableGridBlockEntity.REDSTONE_MODE));\n        }\n\n        int sx = x + 80 + 1;\n        int sy = y + 6 + 1;\n\n        if (searchField == null) {\n            searchField = new SearchWidget(font, sx, sy, 88 - 6);\n            searchField.setResponder(value -> {\n                searchField.updateJei();\n\n                getView().sort(); // Use getter since this view can be replaced.\n\n                searchQuery = value;\n            });\n            searchField.setMode(grid.getSearchBoxMode());\n            searchField.setValue(searchQuery);\n        } else {\n            searchField.setX(sx);\n            searchField.setY(sy);\n        }\n\n        addRenderableWidget(searchField);\n        if (searchField.isFocused()) {\n            setFocused(searchField);\n        }\n\n        if (grid.getViewType() != -1) {\n            addSideButton(new GridViewTypeSideButton(this, grid));\n        }\n\n        addSideButton(new GridSortingDirectionSideButton(this, grid));\n        addSideButton(new GridSortingTypeSideButton(this, grid));\n        addSideButton(new GridSearchBoxModeSideButton(this));\n        addSideButton(new GridSizeSideButton(this, grid::getSize, grid::onSizeChanged));\n\n        if (grid.getGridType() == GridType.PATTERN) {\n            patternScrollbar = new ScrollbarWidget(this, 160, getTopHeight() + getVisibleRows() * 18 + 4, 6, 18 * 3 - 2, true);\n\n            patternScrollbar.setMaxOffset(patternScrollOffsetAbsoluteMax);\n            patternScrollbar.setOffset(patternScrollOffset); // keep offset when changing between fluid and item view\n\n            menu.updatePatternSlotPositions(patternScrollOffset);\n            patternScrollbar.addListener((oldOffset, newOffset) -> {\n                patternScrollOffset = newOffset;\n                menu.updatePatternSlotPositions(newOffset);\n            });\n\n            processingPattern = addCheckBox(x + 7, y + getTopHeight() + (getVisibleRows() * 18) + 60, Component.translatable(\"misc.refinedstorage.processing\"), GridBlockEntity.PROCESSING_PATTERN.getValue(), btn -> {\n                // Rebuild the inventory slots before the slot change packet arrives.\n                GridBlockEntity.PROCESSING_PATTERN.setValue(false, processingPattern.isSelected());\n                ((GridNetworkNode) grid).clearMatrix(); // The server does this but let's do it earlier so the client doesn't notice.\n                this.menu.initSlots();\n\n                patternScrollOffset = 0; // reset offset when switching between crafting and processing\n                BlockEntitySynchronizationManager.setParameter(GridBlockEntity.PROCESSING_PATTERN, processingPattern.isSelected());\n            });\n\n            if (!processingPattern.isSelected()) {\n                exactPattern = addCheckBox(\n                    processingPattern.getX() + processingPattern.getWidth() + 5,\n                    y + getTopHeight() + (getVisibleRows() * 18) + 60,\n                    Component.translatable(\"misc.refinedstorage.exact\"),\n                    GridBlockEntity.EXACT_PATTERN.getValue(),\n                    btn -> BlockEntitySynchronizationManager.setParameter(GridBlockEntity.EXACT_PATTERN, exactPattern.isSelected())\n                );\n                patternScrollbar.setEnabled(false);\n            } else {\n                patternScrollbar.setEnabled(true);\n\n                fluidCheckBox = addCheckBox(processingPattern.getX() + processingPattern.getWidth() + 5, y + getTopHeight() + (getVisibleRows() * 18) + 60, Component.translatable(\"misc.refinedstorage.fluidmode\"), ((GridNetworkNode) grid).getType() == IType.FLUIDS, button -> {\n                    BlockEntitySynchronizationManager.setParameter(GridBlockEntity.PROCESSING_TYPE, GridBlockEntity.PROCESSING_TYPE.getValue() == IType.ITEMS ? IType.FLUIDS : IType.ITEMS);\n                });\n            }\n        }\n\n        updateScrollbar();\n    }\n\n    public IGrid getGrid() {\n        return grid;\n    }\n\n    public IGridView getView() {\n        return view;\n    }\n\n    public void setView(IGridView view) {\n        this.view = view;\n    }\n\n    @Override\n    public void tick(int x, int y) {\n        if (wasConnected != grid.isGridActive()) {\n            wasConnected = grid.isGridActive();\n\n            view.sort();\n        }\n\n        if (updatePatternOffset) {\n            updatePatternOffsetMax();\n            updatePatternOffset = false;\n        }\n\n        if (isKeyDown(RSKeyBindings.CLEAR_GRID_CRAFTING_MATRIX)) {\n            RS.NETWORK_HANDLER.sendToServer(new GridClearMessage());\n        }\n\n        tabs.update();\n    }\n\n    @Override\n    public int getTopHeight() {\n        return 19;\n    }\n\n    @Override\n    public int getBottomHeight() {\n        if (grid.getGridType() == GridType.CRAFTING) {\n            return 156;\n        } else if (grid.getGridType() == GridType.PATTERN) {\n            return 169;\n        } else {\n            return 99;\n        }\n    }\n\n    @Override\n    public int getYPlayerInventory() {\n        int yp = getTopHeight() + (getVisibleRows() * 18);\n\n        if (grid.getGridType() == GridType.NORMAL || grid.getGridType() == GridType.FLUID) {\n            yp += 16;\n        } else if (grid.getGridType() == GridType.CRAFTING) {\n            yp += 73;\n        } else if (grid.getGridType() == GridType.PATTERN) {\n            yp += 86;\n        }\n\n        return yp;\n    }\n\n    @Override\n    public int getRows() {\n        return Math.max(0, (int) Math.ceil((float) view.getStacks().size() / 9F));\n    }\n\n    @Override\n    public int getCurrentOffset() {\n        return scrollbar.getOffset();\n    }\n\n    @Override\n    public String getSearchFieldText() {\n        return searchField.getValue();\n    }\n\n    @Override\n    public int getVisibleRows() {\n        switch (grid.getSize()) {\n            case IGrid.SIZE_STRETCH:\n                int screenSpaceAvailable = height - getTopHeight() - getBottomHeight();\n\n                return Math.max(3, Math.min((screenSpaceAvailable / 18) - 3, RS.CLIENT_CONFIG.getGrid().getMaxRowsStretch()));\n            case IGrid.SIZE_SMALL:\n                return 3;\n            case IGrid.SIZE_MEDIUM:\n                return 5;\n            case IGrid.SIZE_LARGE:\n                return 8;\n            default:\n                return 3;\n        }\n    }\n\n    private boolean isOverSlotWithStack() {\n        return grid.isGridActive() && isOverSlot() && slotNumber < view.getStacks().size();\n    }\n\n    private boolean isOverSlot() {\n        return slotNumber >= 0;\n    }\n\n    public boolean isOverSlotArea(double mouseX, double mouseY) {\n        return RenderUtils.inBounds(7, 19, 162, 18 * getVisibleRows(), mouseX, mouseY);\n    }\n\n    public int getSlotNumber() {\n        return slotNumber;\n    }\n\n    public int getSlotNumberX() {\n        return slotNumberX;\n    }\n\n    public int getSlotNumberY() {\n        return slotNumberY;\n    }\n\n    private boolean isOverClear(double mouseX, double mouseY) {\n        int y = getTopHeight() + (getVisibleRows() * 18) + 4;\n\n        switch (grid.getGridType()) {\n            case CRAFTING:\n                return RenderUtils.inBounds(82, y, 7, 7, mouseX, mouseY);\n            case PATTERN:\n                if (((GridNetworkNode) grid).isProcessingPattern()) {\n                    return RenderUtils.inBounds(149, y, 7, 7, mouseX, mouseY);\n                }\n\n                return RenderUtils.inBounds(82, y, 7, 7, mouseX, mouseY);\n            default:\n                return false;\n        }\n    }\n\n    private boolean isOverCreatePattern(double mouseX, double mouseY) {\n        return grid.getGridType() == GridType.PATTERN && RenderUtils.inBounds(172, getTopHeight() + (getVisibleRows() * 18) + 22, 16, 16, mouseX, mouseY) && ((GridNetworkNode) grid).canCreatePattern();\n    }\n\n    @Override\n    public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {\n        tabs.drawBackground(graphics, x, y - tabs.getHeight());\n\n        ResourceLocation texture;\n        if (grid instanceof IPortableGrid) {\n            texture = PORTABLE_GRID_TEXTURE;\n        } else if (grid.getGridType() == GridType.CRAFTING) {\n            texture = CRAFTING_GRID_TEXTURE;\n        } else if (grid.getGridType() == GridType.PATTERN) {\n            texture = ((GridNetworkNode) grid).isProcessingPattern() ? PATTERN_GRID_PROCESSING_TEXTURE : PATTERN_GRID_TEXTURE;\n        } else {\n            texture = GRID_TEXTURE;\n        }\n\n        int yy = y;\n\n        graphics.blit(texture, x, yy, 0, 0, imageWidth - 34, getTopHeight());\n\n        // Filters and/or portable grid disk\n        graphics.blit(texture, x + imageWidth - 34 + 4, y, 197, 0, 30, grid instanceof IPortableGrid ? 114 : 82);\n\n        int rows = getVisibleRows();\n\n        for (int i = 0; i < rows; ++i) {\n            yy += 18;\n\n            int yTextureStart = getTopHeight();\n            if (i > 0) {\n                if (i == rows - 1) {\n                    yTextureStart += 18 * 2;\n                } else {\n                    yTextureStart += 18;\n                }\n            }\n\n            graphics.blit(texture, x, yy, 0, yTextureStart, imageWidth - 34, 18);\n        }\n\n        yy += 18;\n\n        graphics.blit(texture, x, yy, 0, getTopHeight() + (18 * 3), imageWidth - 34, getBottomHeight());\n\n        if (grid.getGridType() == GridType.PATTERN) {\n            int ty = 0;\n\n            if (isOverCreatePattern(mouseX - leftPos, mouseY - topPos)) {\n                ty = 1;\n            }\n\n            if (!((GridNetworkNode) grid).canCreatePattern()) {\n                ty = 2;\n            }\n\n            graphics.blit(texture, x + 172, y + getTopHeight() + (getVisibleRows() * 18) + 22, 240, ty * 16, 16, 16);\n            if (processingPattern.isSelected()) {\n                updatePatternScrollbar();\n                patternScrollbar.render(graphics);\n            }\n        }\n\n        tabs.drawForeground(graphics, x, y - tabs.getHeight(), mouseX, mouseY, true);\n\n        searchField.render(graphics, 0, 0, 0);\n\n        scrollbar.render(graphics);\n    }\n\n    @Override\n    public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {\n        super.render(graphics, mouseX, mouseY, partialTicks);\n\n        // Drawn in here for bug #1844 (https://github.com/refinedmods/refinedstorage/issues/1844)\n        // Item tooltips can't be rendered in the foreground layer due to the X offset translation.\n        if (isOverSlotWithStack()) {\n            drawGridTooltip(graphics, view.getStacks().get(slotNumber), mouseX, mouseY);\n        }\n    }\n\n    @Override\n    public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) {\n        renderString(graphics, 7, 7, title.getString());\n        renderString(graphics, 7, getYPlayerInventory() - 12, I18n.get(\"container.inventory\"));\n\n        int x = 8;\n        int y = 19;\n\n        this.slotNumber = -1;\n        this.slotNumberX = -1;\n        this.slotNumberY = -1;\n\n        int slot = scrollbar != null ? (scrollbar.getOffset() * 9) : 0;\n\n        Lighting.setupFor3DItems();\n\n        for (int i = 0; i < 9 * getVisibleRows(); ++i) {\n            if (RenderUtils.inBounds(x, y, 16, 16, mouseX, mouseY) || !grid.isGridActive()) {\n                this.slotNumber = slot;\n                this.slotNumberX = x;\n                this.slotNumberY = y;\n            }\n\n            if (slot < view.getStacks().size()) {\n                view.getStacks().get(slot).draw(graphics, this, x, y);\n            }\n\n            if (RenderUtils.inBounds(x, y, 16, 16, mouseX, mouseY) || !grid.isGridActive()) {\n                int color = grid.isGridActive() ? -2130706433 : 0xFF5B5B5B;\n\n                graphics.pose().pushPose();\n                graphics.pose().translate(0, 0, 300);\n                RenderSystem.disableDepthTest();\n                RenderSystem.colorMask(true, true, true, false);\n                graphics.fillGradient(x, y, x + 16, y + 16, color, color);\n                RenderSystem.colorMask(true, true, true, true);\n                graphics.pose().popPose();\n            }\n\n            slot++;\n\n            x += 18;\n\n            if ((i + 1) % 9 == 0) {\n                x = 8;\n                y += 18;\n            }\n        }\n\n        if (isOverClear(mouseX, mouseY)) {\n            renderTooltip(graphics, mouseX, mouseY, I18n.get(\"misc.refinedstorage.clear\"));\n        }\n\n        if (isOverCreatePattern(mouseX, mouseY)) {\n            renderTooltip(graphics, mouseX, mouseY, I18n.get(\"gui.refinedstorage.grid.pattern_create\"));\n        }\n\n        tabs.drawTooltip(graphics, font, mouseX, mouseY);\n    }\n\n    private void drawGridTooltip(GuiGraphics graphics, IGridStack gridStack, int mouseX, int mouseY) {\n        ItemStack stackContext = gridStack instanceof ItemGridStack ? ((ItemGridStack) gridStack).getStack() : ItemStack.EMPTY;\n\n        List<? extends FormattedText> textElements = gridStack.getTooltip(true);\n        List<ClientTooltipComponent> components = new ArrayList<>(ClientHooks.gatherTooltipComponents(\n            stackContext,\n            textElements,\n            mouseX,\n            minecraft.getWindow().getGuiScaledWidth(),\n            minecraft.getWindow().getGuiScaledHeight(),\n            font\n        ));\n\n        if (RS.CLIENT_CONFIG.getGrid().getDetailedTooltip()) {\n            final float scale = (minecraft != null && minecraft.isEnforceUnicode()) ? 1F : 0.7F;\n            if (!gridStack.isCraftable()) {\n                MutableComponent total = Component.translatable(\"misc.refinedstorage.total\", gridStack.getFormattedFullQuantity())\n                    .withStyle(ChatFormatting.GRAY);\n                components.add(new SmallClientTooltipComponent(total, scale));\n            }\n\n            if (gridStack.getTrackerEntry() != null) {\n                MutableComponent time = Component.translatable(TimeUtils.getAgo(gridStack.getTrackerEntry().getTime(), gridStack.getTrackerEntry().getName()))\n                    .withStyle(ChatFormatting.GRAY);\n                components.add(new SmallClientTooltipComponent(time, scale));\n            }\n        }\n\n        graphics.renderTooltipInternal(font, components, mouseX, mouseY, DefaultTooltipPositioner.INSTANCE);\n    }\n\n    @Override\n    public boolean mouseClicked(double mouseX, double mouseY, int clickedButton) {\n        if (tabs.mouseClicked()) {\n            setFocused(null);\n            return true;\n        }\n        if (scrollbar.mouseClicked(mouseX, mouseY, clickedButton)) {\n            setFocused(null);\n            return true;\n        }\n        if (grid.getGridType() == GridType.PATTERN && patternScrollbar.mouseClicked(mouseX, mouseY, clickedButton)) {\n            setFocused(null);\n            return true;\n        }\n        if (RS.CLIENT_CONFIG.getGrid().getPreventSortingWhileShiftIsDown()) {\n            doSort = !isOverSlotArea(mouseX - leftPos, mouseY - topPos) && !isOverCraftingOutputArea(mouseX - leftPos, mouseY - topPos);\n        }\n\n        boolean clickedClear = clickedButton == 0 && isOverClear(mouseX - leftPos, mouseY - topPos);\n        boolean clickedCreatePattern = clickedButton == 0 && isOverCreatePattern(mouseX - leftPos, mouseY - topPos);\n\n        if (clickedCreatePattern) {\n            minecraft.getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F));\n\n            RS.NETWORK_HANDLER.sendToServer(new GridPatternCreateMessage(((GridNetworkNode) grid).getPos()));\n\n            setFocused(null);\n\n            return true;\n        } else if (clickedClear) {\n            minecraft.getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F));\n\n            RS.NETWORK_HANDLER.sendToServer(new GridClearMessage());\n\n            setFocused(null);\n\n            return true;\n        } else if (grid.isGridActive()) {\n            ItemStack held = menu.getCarried();\n\n            if (isOverSlotArea(mouseX - leftPos, mouseY - topPos) && !held.isEmpty() && (clickedButton == 0 || clickedButton == 1)) {\n                if (grid.getGridType() == GridType.FLUID) {\n                    RS.NETWORK_HANDLER.sendToServer(new GridFluidInsertHeldMessage());\n                } else {\n                    RS.NETWORK_HANDLER.sendToServer(new GridItemInsertHeldMessage(clickedButton == 1));\n                }\n                setFocused(null);\n\n                return true;\n            }\n\n            if (isOverSlotWithStack()) {\n                IGridStack stack = view.getStacks().get(slotNumber);\n\n                if (held.isEmpty()) {\n                    if (view.canCraft() && stack.isCraftable()) {\n                        minecraft.setScreen(new CraftingSettingsScreen(this, inventory.player, stack));\n                    } else if (view.canCraft() && !stack.isCraftable() && stack.getOtherId() != null && hasShiftDown() && hasControlDown()) {\n                        minecraft.setScreen(new CraftingSettingsScreen(this, inventory.player, view.get(stack.getOtherId())));\n                    } else if (grid.getGridType() == GridType.FLUID && held.isEmpty()) {\n                        RS.NETWORK_HANDLER.sendToServer(new GridFluidPullMessage(view.getStacks().get(slotNumber).getId(), hasShiftDown()));\n                    } else if (grid.getGridType() != GridType.FLUID) {\n                        int flags = 0;\n\n                        if (clickedButton == 1) {\n                            flags |= IItemGridHandler.EXTRACT_HALF;\n                        }\n\n                        if (hasShiftDown()) {\n                            flags |= IItemGridHandler.EXTRACT_SHIFT;\n                        }\n\n                        RS.NETWORK_HANDLER.sendToServer(new GridItemPullMessage(stack.getId(), flags));\n                    }\n                }\n\n                setFocused(null);\n                return true;\n            }\n        }\n\n        return super.mouseClicked(mouseX, mouseY, clickedButton);\n    }\n\n    private boolean isOverCraftingOutputArea(double mouseX, double mouseY) {\n        if (grid.getGridType() != GridType.CRAFTING) {\n            return false;\n        }\n        return RenderUtils.inBounds(130, getTopHeight() + getVisibleRows() * 18 + 18, 24, 24, mouseX, mouseY);\n    }\n\n    @Override\n    public void mouseMoved(double mx, double my) {\n        scrollbar.mouseMoved(mx, my);\n\n        if (grid.getGridType() == GridType.PATTERN) {\n            patternScrollbar.mouseMoved(mx, my);\n        }\n        super.mouseMoved(mx, my);\n    }\n\n    @Override\n    public boolean mouseReleased(double mx, double my, int button) {\n        if (grid.getGridType() == GridType.PATTERN && patternScrollbar.mouseReleased(mx, my, button)) {\n            return true;\n        }\n        return scrollbar.mouseReleased(mx, my, button) || super.mouseReleased(mx, my, button);\n    }\n\n    @Override\n    public boolean mouseScrolled(double x, double y, double z, double delta) {\n        if (hasShiftDown() || hasControlDown()) {\n            if (RS.CLIENT_CONFIG.getGrid().getPreventSortingWhileShiftIsDown()) {\n                doSort = !isOverSlotArea(x - leftPos, y - topPos) && !isOverCraftingOutputArea(x - leftPos, y - topPos);\n            }\n            if (grid.getGridType() != GridType.FLUID) {\n                if (isOverInventory(x - leftPos, y - topPos) && hoveredSlot != null && hoveredSlot.hasItem() && getMenu().getDisabledSlotNumber() != hoveredSlot.getSlotIndex()) {\n                    RS.NETWORK_HANDLER.sendToServer(new GridItemInventoryScrollMessage(hoveredSlot.getSlotIndex(), hasShiftDown(), delta > 0));\n                } else if (isOverSlotArea(x - leftPos, y - topPos)) {\n                    RS.NETWORK_HANDLER.sendToServer(new GridItemGridScrollMessage(isOverSlotWithStack() ? view.getStacks().get(slotNumber).getId() : null, hasShiftDown(), delta > 0));\n                }\n            }\n\n            return super.mouseScrolled(x, y, z, delta);\n        }\n\n        if (grid.getGridType() == GridType.PATTERN && isOverPatternArea(x - leftPos, y - topPos) && patternScrollbar.mouseScrolled(x, y, z, delta)) {\n            return true;\n        }\n\n        return this.scrollbar.mouseScrolled(x, y, z, delta) || super.mouseScrolled(x, y, z, delta);\n    }\n\n    private boolean isOverInventory(double x, double y) {\n        return RenderUtils.inBounds(8, getYPlayerInventory(), 9 * 18 - 2, 4 * 18 + 2, x, y);\n    }\n\n    private boolean isOverPatternArea(double x, double y) {\n        return RenderUtils.inBounds(8, getTopHeight() + getVisibleRows() * 18, 152, 54, x, y);\n    }\n\n    @Override\n    public boolean charTyped(char unknown1, int unknown2) {\n        if (searchField.charTyped(unknown1, unknown2)) {\n            return true;\n        }\n\n        return super.charTyped(unknown1, unknown2);\n    }\n\n    @Override\n    public boolean keyReleased(int keyCode, int scanCode, int modifiers) {\n        if (keyCode == GLFW.GLFW_KEY_LEFT_SHIFT ||\n            keyCode == GLFW.GLFW_KEY_RIGHT_SHIFT ||\n            keyCode == GLFW.GLFW_KEY_LEFT_CONTROL ||\n            keyCode == GLFW.GLFW_KEY_RIGHT_CONTROL) {\n            view.sort();\n        }\n\n        return super.keyReleased(keyCode, scanCode, modifiers);\n    }\n\n    @Override\n    public boolean keyPressed(int key, int scanCode, int modifiers) {\n        if (searchField.keyPressed(key, scanCode, modifiers)) {\n            return true;\n        }\n        return super.keyPressed(key, scanCode, modifiers);\n    }\n\n    @Override\n    public void removed() {\n        super.removed();\n\n        if (!RS.CLIENT_CONFIG.getGrid().getRememberSearchQuery()) {\n            searchQuery = \"\";\n        }\n        getView().removed();\n    }\n\n    public SearchWidget getSearchField() {\n        return searchField;\n    }\n\n    public void updateExactPattern(boolean checked) {\n        if (exactPattern != null) {\n            exactPattern.setSelected(checked);\n        }\n    }\n\n    //check processing matrix and update maximum offset depending on contents\n    private void updatePatternOffsetMax() {\n        int filledInputSlots = 0;\n        int filledOutputSlots = 0;\n        int lastFilledInputSlot = 0;\n        int lastFilledOutputSlot = 0;\n\n        for (int i = 0; i < GridNetworkNode.PROCESSING_MATRIX_SIZE * 2; i++) {\n            if (!isMatrixSlotEmpty(i)) {\n                if (i > GridNetworkNode.PROCESSING_MATRIX_SIZE - 1) {\n                    filledOutputSlots++;\n                    lastFilledOutputSlot = i - GridNetworkNode.PROCESSING_MATRIX_SIZE - 1;\n                } else {\n                    filledInputSlots++;\n                    lastFilledInputSlot = i;\n                }\n            }\n        }\n\n        int maxFilledSlots = Math.max(filledInputSlots, filledOutputSlots);\n        int maxLastFilledSlot = Math.max(lastFilledInputSlot, lastFilledOutputSlot);\n\n        // offset calculation to show next row if 4 of 9 slots are filled.\n        int filledSlotOffset = Math.floorDiv(maxFilledSlots - 1, 3);\n        // offset to show the last item in the matrix\n        int lastSlotOffset = Math.floorDiv(maxLastFilledSlot, 3) - 2;\n\n        patternScrollOffsetMax = Math.max(filledSlotOffset, lastSlotOffset);\n    }\n\n    private boolean isMatrixSlotEmpty(int slotNumber) {\n        return ((GridNetworkNode) grid).getProcessingMatrix().getStackInSlot(slotNumber).isEmpty()\n            && ((GridNetworkNode) grid).getProcessingMatrixFluids().getFluid(slotNumber).isEmpty();\n    }\n\n    public void updatePatternScrollbar() {\n        patternScrollbar.setEnabled(processingPattern.isSelected() && patternScrollOffsetMax > 0);\n        int oldOffset = patternScrollbar.getOffset();\n        patternScrollbar.setMaxOffset(Math.min(patternScrollOffsetMax, patternScrollOffsetAbsoluteMax));\n\n        if (oldOffset != patternScrollbar.getOffset()) {\n            menu.updatePatternSlotPositions(patternScrollbar.getOffset());\n        }\n    }\n\n    public void updateScrollbar() {\n        scrollbar.setEnabled(getRows() > getVisibleRows());\n        scrollbar.setMaxOffset(getRows() - getVisibleRows());\n    }\n\n    public boolean canSort() {\n        return doSort || (!hasShiftDown() && !hasControlDown());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/SmallClientTooltipComponent.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid;\n\nimport net.minecraft.client.gui.Font;\nimport net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent;\nimport net.minecraft.client.renderer.MultiBufferSource;\nimport net.minecraft.network.chat.Component;\nimport org.joml.Matrix4f;\n\npublic class SmallClientTooltipComponent implements ClientTooltipComponent {\n    private final Component component;\n    private final float scale;\n\n    public SmallClientTooltipComponent(Component component, float scale) {\n        this.component = component;\n        this.scale = scale;\n    }\n\n    @Override\n    public void renderText(Font font, int x, int y, Matrix4f pose, MultiBufferSource.BufferSource buffer) {\n        Matrix4f scaled = new Matrix4f(pose);\n        scaled.scale(scale, scale, 1);\n        font.drawInBatch(component, x / scale, y / scale, -1, true, scaled, buffer, Font.DisplayMode.NORMAL, 0, 15728880);\n    }\n\n    @Override\n    public int getHeight() {\n        return 9;\n    }\n\n    @Override\n    public int getWidth(Font font) {\n        return (int) (font.width(component) * scale);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/filtering/AndGridFilter.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid.filtering;\n\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\n\nimport java.util.List;\nimport java.util.function.Predicate;\n\npublic class AndGridFilter implements Predicate<IGridStack> {\n    private final List<Predicate<IGridStack>> andPartFilters;\n\n    private AndGridFilter(List<Predicate<IGridStack>> andPartFilters) {\n        this.andPartFilters = andPartFilters;\n    }\n\n    public static Predicate<IGridStack> of(List<Predicate<IGridStack>> filters) {\n        if (filters.isEmpty()) {\n            return t -> true;\n        }\n        if (filters.size() == 1) {\n            return filters.get(0);\n        }\n        return new AndGridFilter(filters);\n    }\n\n    @Override\n    public boolean test(IGridStack gridStack) {\n        for (Predicate<IGridStack> part : andPartFilters) {\n            if (!part.test(gridStack)) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/filtering/CraftableGridFilter.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid.filtering;\n\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\n\nimport java.util.function.Predicate;\n\npublic class CraftableGridFilter implements Predicate<IGridStack> {\n    private final boolean craftable;\n\n    public CraftableGridFilter(boolean craftable) {\n        this.craftable = craftable;\n    }\n\n    @Override\n    public boolean test(IGridStack stack) {\n        if (craftable) {\n            return stack.isCraftable();\n        } else {\n            return !stack.isCraftable() && stack.getOtherId() == null;\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/filtering/FilterGridFilter.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid.filtering;\n\nimport com.refinedmods.refinedstorage.api.util.IFilter;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.screen.grid.stack.FluidGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack;\n\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport java.util.List;\nimport java.util.function.Predicate;\n\npublic class FilterGridFilter implements Predicate<IGridStack> {\n    private final List<IFilter> filters;\n\n    public FilterGridFilter(List<IFilter> filters) {\n        this.filters = filters;\n    }\n\n    @Override\n    public boolean test(IGridStack stack) {\n        if (filters.isEmpty()) {\n            return true;\n        }\n\n        int lastMode = IFilter.MODE_WHITELIST;\n\n        for (IFilter filter : filters) {\n            lastMode = filter.getMode();\n\n            if (stack instanceof ItemGridStack && filter.getStack() instanceof ItemStack) {\n                ItemStack stackInFilter = (ItemStack) filter.getStack();\n\n                if (filter.isModFilter()) {\n                    String stackModId = stack.getModId();\n                    String filterModId = stackInFilter.getItem().getCreatorModId(stackInFilter);\n\n                    if (filterModId != null && filterModId.equals(stackModId)) {\n                        return filter.getMode() == IFilter.MODE_WHITELIST;\n                    }\n                } else if (API.instance().getComparer().isEqual(((ItemGridStack) stack).getStack(), stackInFilter, filter.getCompare())) {\n                    return filter.getMode() == IFilter.MODE_WHITELIST;\n                }\n            } else if (stack instanceof FluidGridStack && filter.getStack() instanceof FluidStack) {\n                FluidStack stackInFilter = (FluidStack) filter.getStack();\n\n                if (filter.isModFilter()) {\n                    ResourceLocation stackInFilterRegistryName = BuiltInRegistries.FLUID.getKey(stackInFilter.getFluid());\n                    String stackInFilterModId = stackInFilterRegistryName.getNamespace();\n\n                    if (stackInFilterModId.equalsIgnoreCase(stack.getModId())) {\n                        return filter.getMode() == IFilter.MODE_WHITELIST;\n                    }\n                } else if (API.instance().getComparer().isEqual(((FluidGridStack) stack).getStack(), stackInFilter, filter.getCompare())) {\n                    return filter.getMode() == IFilter.MODE_WHITELIST;\n                }\n            }\n        }\n\n        return lastMode != IFilter.MODE_WHITELIST;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/filtering/GridFilterParser.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid.filtering;\n\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.api.util.IFilter;\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\n\nimport javax.annotation.Nullable;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.function.Predicate;\n\npublic final class GridFilterParser {\n    private GridFilterParser() {\n    }\n\n    public static Predicate<IGridStack> getFilters(@Nullable IGrid grid, String query, List<IFilter> filters) {\n        List<Predicate<IGridStack>> gridFilters;\n\n        String[] orParts = query.split(\"\\\\|\");\n\n        if (orParts.length == 1) {\n            gridFilters = getFilters(orParts[0]);\n        } else {\n            List<Predicate<IGridStack>> orPartFilters = new LinkedList<>();\n\n            for (String orPart : orParts) {\n                orPartFilters.add(AndGridFilter.of(getFilters(orPart)));\n            }\n\n            gridFilters = new LinkedList<>();\n            gridFilters.add(OrGridFilter.of(orPartFilters));\n        }\n\n        if (grid != null) {\n            if (grid.getViewType() == IGrid.VIEW_TYPE_NON_CRAFTABLES) {\n                gridFilters.add(new CraftableGridFilter(false));\n            } else if (grid.getViewType() == IGrid.VIEW_TYPE_CRAFTABLES) {\n                gridFilters.add(new CraftableGridFilter(true));\n            }\n        }\n\n        if (!filters.isEmpty()) {\n            gridFilters.add(new FilterGridFilter(filters));\n        }\n\n        return AndGridFilter.of(gridFilters);\n    }\n\n    private static List<Predicate<IGridStack>> getFilters(String query) {\n        List<Predicate<IGridStack>> gridFilters = new LinkedList<>();\n\n        for (String part : query.toLowerCase().trim().split(\" \")) {\n            if (part.startsWith(\"@\")) {\n                gridFilters.add(new ModGridFilter(part.substring(1)));\n            } else if (part.startsWith(\"#\")) {\n                gridFilters.add(new TooltipGridFilter(part.substring(1)));\n            } else if (part.startsWith(\"$\")) {\n                gridFilters.add(new TagGridFilter(part.substring(1)));\n            } else {\n                gridFilters.add(new NameGridFilter(part));\n            }\n        }\n\n        return gridFilters;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/filtering/ModGridFilter.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid.filtering;\n\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\n\nimport java.util.function.Predicate;\n\npublic class ModGridFilter implements Predicate<IGridStack> {\n    private final String inputModName;\n\n    public ModGridFilter(String inputModName) {\n        this.inputModName = standardify(inputModName);\n    }\n\n    @Override\n    public boolean test(IGridStack stack) {\n        String modId = stack.getModId();\n\n        if (modId != null) {\n            if (modId.contains(inputModName)) {\n                return true;\n            }\n\n            String modName = stack.getModName();\n            if (modName != null) {\n                modName = standardify(modName);\n\n                if (modName.contains(inputModName)) {\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    private String standardify(String input) {\n        return input.toLowerCase().replace(\" \", \"\");\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/filtering/NameGridFilter.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid.filtering;\n\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\n\nimport java.util.function.Predicate;\n\npublic class NameGridFilter implements Predicate<IGridStack> {\n    private final String name;\n\n    public NameGridFilter(String name) {\n        this.name = name.toLowerCase();\n    }\n\n    @Override\n    public boolean test(IGridStack stack) {\n        return stack.getName().toLowerCase().contains(name);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/filtering/OrGridFilter.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid.filtering;\n\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\n\nimport java.util.List;\nimport java.util.function.Predicate;\n\npublic class OrGridFilter implements Predicate<IGridStack> {\n    private final List<Predicate<IGridStack>> orPartFilters;\n\n    private OrGridFilter(List<Predicate<IGridStack>> orPartFilters) {\n        this.orPartFilters = orPartFilters;\n    }\n\n    public static Predicate<IGridStack> of(List<Predicate<IGridStack>> filters) {\n        if (filters.isEmpty()) {\n            return t -> false;\n        }\n        if (filters.size() == 1) {\n            return filters.get(0);\n        }\n        return new OrGridFilter(filters);\n    }\n\n    @Override\n    public boolean test(IGridStack gridStack) {\n        for (Predicate<IGridStack> part : orPartFilters) {\n            if (part.test(gridStack)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/filtering/TagGridFilter.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid.filtering;\n\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\n\nimport java.util.function.Predicate;\n\npublic class TagGridFilter implements Predicate<IGridStack> {\n    private final String tagName;\n\n    public TagGridFilter(String tagName) {\n        this.tagName = tagName.toLowerCase();\n    }\n\n    @Override\n    public boolean test(IGridStack stack) {\n        return stack.getTags().stream().anyMatch(name -> name.toLowerCase().contains(this.tagName));\n    }\n}"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/filtering/TooltipGridFilter.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid.filtering;\n\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\nimport net.minecraft.network.chat.Component;\n\nimport java.util.List;\nimport java.util.function.Predicate;\n\npublic class TooltipGridFilter implements Predicate<IGridStack> {\n    private final String tooltip;\n\n    public TooltipGridFilter(String tooltip) {\n        this.tooltip = tooltip.toLowerCase();\n    }\n\n    @Override\n    public boolean test(IGridStack stack) {\n        List<Component> stackTooltip = stack.getTooltip(false);\n\n        for (int i = 1; i < stackTooltip.size(); ++i) {\n            if (stackTooltip.get(i).getString().toLowerCase().contains(tooltip.toLowerCase())) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/sorting/IGridSorter.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid.sorting;\n\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\n\npublic interface IGridSorter {\n    boolean isApplicable(IGrid grid);\n\n    int compare(IGridStack left, IGridStack right, SortingDirection direction);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/sorting/IdGridSorter.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid.sorting;\n\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\n\npublic class IdGridSorter implements IGridSorter {\n    @Override\n    public boolean isApplicable(IGrid grid) {\n        return grid.getSortingType() == IGrid.SORTING_TYPE_ID;\n    }\n\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public int compare(IGridStack left, IGridStack right, SortingDirection sortingDirection) {\n        int leftId = 0;\n        int rightId = 0;\n\n        if (left.getIngredient() instanceof ItemStack && right.getIngredient() instanceof ItemStack) {\n            leftId = Item.getId(((ItemStack) left.getIngredient()).getItem());\n            rightId = Item.getId(((ItemStack) right.getIngredient()).getItem());\n        } else if (left.getIngredient() instanceof FluidStack && right.getIngredient() instanceof FluidStack) {\n            leftId = BuiltInRegistries.FLUID.getId(((FluidStack) left.getIngredient()).getFluid());\n            rightId = BuiltInRegistries.FLUID.getId(((FluidStack) right.getIngredient()).getFluid());\n        }\n\n        if (leftId != rightId) {\n            if (sortingDirection == SortingDirection.DESCENDING) {\n                return Integer.compare(leftId, rightId);\n            } else if (sortingDirection == SortingDirection.ASCENDING) {\n                return Integer.compare(rightId, leftId);\n            }\n        }\n\n        return 0;\n    }\n}"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/sorting/LastModifiedGridSorter.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid.sorting;\n\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\n\npublic class LastModifiedGridSorter implements IGridSorter {\n    @Override\n    public boolean isApplicable(IGrid grid) {\n        return grid.getSortingType() == IGrid.SORTING_TYPE_LAST_MODIFIED;\n    }\n\n    @Override\n    public int compare(IGridStack left, IGridStack right, SortingDirection sortingDirection) {\n        long lt = left.getTrackerEntry() != null ? left.getTrackerEntry().getTime() : 0;\n        long rt = right.getTrackerEntry() != null ? right.getTrackerEntry().getTime() : 0;\n\n        if (lt != rt) {\n            // For \"last modified\" the comparison is reversed\n            if (sortingDirection == SortingDirection.DESCENDING) {\n                return Long.compare(rt, lt);\n            } else if (sortingDirection == SortingDirection.ASCENDING) {\n                return Long.compare(lt, rt);\n            }\n        }\n\n        return 0;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/sorting/NameGridSorter.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid.sorting;\n\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\n\npublic class NameGridSorter implements IGridSorter {\n    @Override\n    public boolean isApplicable(IGrid grid) {\n        return grid.getSortingType() == IGrid.SORTING_TYPE_NAME;\n    }\n\n    @Override\n    public int compare(IGridStack left, IGridStack right, SortingDirection sortingDirection) {\n        String leftName = left.getName();\n        String rightName = right.getName();\n\n        if (sortingDirection == SortingDirection.ASCENDING) {\n            return leftName.compareTo(rightName);\n        } else if (sortingDirection == SortingDirection.DESCENDING) {\n            return rightName.compareTo(leftName);\n        }\n\n        return 0;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/sorting/QuantityGridSorter.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid.sorting;\n\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\n\npublic class QuantityGridSorter implements IGridSorter {\n    @Override\n    public boolean isApplicable(IGrid grid) {\n        return grid.getSortingType() == IGrid.SORTING_TYPE_QUANTITY;\n    }\n\n    @Override\n    public int compare(IGridStack left, IGridStack right, SortingDirection sortingDirection) {\n        int leftSize = left.getQuantity();\n        int rightSize = right.getQuantity();\n\n        if (leftSize != rightSize) {\n            if (sortingDirection == SortingDirection.ASCENDING) {\n                return (leftSize > rightSize) ? 1 : -1;\n            } else if (sortingDirection == SortingDirection.DESCENDING) {\n                return (rightSize > leftSize) ? 1 : -1;\n            }\n        }\n\n        return 0;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/sorting/SortingDirection.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid.sorting;\n\npublic enum SortingDirection {\n    ASCENDING,\n    DESCENDING\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/stack/FluidGridStack.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid.stack;\n\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;\nimport com.refinedmods.refinedstorage.api.storage.tracker.IStorageTracker;\nimport com.refinedmods.refinedstorage.api.storage.tracker.StorageTrackerEntry;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.api.util.StackListEntry;\nimport com.refinedmods.refinedstorage.api.util.StackListResult;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.render.FluidRenderer;\nimport com.refinedmods.refinedstorage.render.RenderSettings;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.UUID;\nimport java.util.stream.Collectors;\nimport javax.annotation.Nullable;\n\nimport com.google.common.collect.Lists;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.tags.TagKey;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\n\npublic class FluidGridStack implements IGridStack {\n    private static final String ERROR_PLACEHOLDER = \"<Error>\";\n    private static final Logger LOGGER = LogManager.getLogger(FluidGridStack.class);\n\n    private final UUID id;\n    private final FluidStack stack;\n    private final boolean craftable;\n    @Nullable\n    private UUID otherId;\n    @Nullable\n    private StorageTrackerEntry entry;\n    private boolean zeroed;\n\n    private Set<String> cachedTags;\n    private String cachedName;\n    private List<Component> cachedTooltip;\n    private String cachedModId;\n    private String cachedModName;\n\n    public FluidGridStack(UUID id, @Nullable UUID otherId, FluidStack stack,\n                          boolean craftable, @Nullable StorageTrackerEntry entry) {\n        this.id = id;\n        this.otherId = otherId;\n        this.stack = stack;\n        this.craftable = craftable;\n        this.entry = entry;\n    }\n\n    public void setZeroed(boolean zeroed) {\n        this.zeroed = zeroed;\n    }\n\n    public FluidStack getStack() {\n        return stack;\n    }\n\n    @Override\n    public boolean isCraftable() {\n        return craftable;\n    }\n\n    @Override\n    public UUID getId() {\n        return id;\n    }\n\n    @Nullable\n    @Override\n    public UUID getOtherId() {\n        return otherId;\n    }\n\n    @Override\n    public void updateOtherId(@Nullable UUID otherId) {\n        this.otherId = otherId;\n    }\n\n    @Override\n    public String getName() {\n        if (cachedName == null) {\n            try {\n                cachedName = stack.getDisplayName().getString();\n            } catch (Throwable t) {\n                LOGGER.warn(\"Could not retrieve fluid name of {}\", BuiltInRegistries.FLUID.getKey(stack.getFluid()));\n\n                cachedName = ERROR_PLACEHOLDER;\n            }\n        }\n\n        return cachedName;\n    }\n\n    @Override\n    public String getModId() {\n        if (cachedModId == null) {\n            ResourceLocation registryName = BuiltInRegistries.FLUID.getKey(stack.getFluid());\n\n            if (registryName != null) {\n                cachedModId = registryName.getNamespace();\n            } else {\n                cachedModId = ERROR_PLACEHOLDER;\n            }\n        }\n\n        return cachedModId;\n    }\n\n    @Override\n    public String getModName() {\n        if (cachedModName == null) {\n            cachedModName = ItemGridStack.getModNameByModId(getModId());\n\n            if (cachedModName == null) {\n                cachedModName = ERROR_PLACEHOLDER;\n            }\n        }\n\n        return cachedModName;\n    }\n\n    @Override\n    public Set<String> getTags() {\n        if (cachedTags == null) {\n            cachedTags = BuiltInRegistries.FLUID.getResourceKey(stack.getFluid())\n                .flatMap(k -> BuiltInRegistries.FLUID.getHolder(k)\n                    .map(holder -> holder.tags()\n                        .map(TagKey::location)\n                        .map(ResourceLocation::getPath)\n                        .collect(Collectors.toSet())))\n                .orElse(Collections.emptySet());\n        }\n\n        return cachedTags;\n    }\n\n    @Override\n    public List<Component> getTooltip(boolean bypassCache) {\n        if (bypassCache || cachedTooltip == null) {\n            List<Component> tooltip;\n            try {\n                tooltip = Lists.newArrayList(stack.getDisplayName());\n            } catch (Throwable t) {\n                LOGGER.warn(\"Could not retrieve fluid tooltip of {}\", BuiltInRegistries.FLUID.getKey(stack.getFluid()));\n                tooltip = Lists.newArrayList(Component.literal(ERROR_PLACEHOLDER));\n            }\n\n            if (bypassCache) {\n                return tooltip;\n            } else {\n                cachedTooltip = tooltip;\n            }\n        }\n\n        return cachedTooltip;\n    }\n\n    @Override\n    public int getQuantity() {\n        // The isCraftable check is needed so sorting is applied correctly\n        return isCraftable() || zeroed ? 0 : stack.getAmount();\n    }\n\n    @Override\n    public void setQuantity(int amount) {\n        if (amount <= 0) {\n            setZeroed(true);\n        } else {\n            stack.setAmount(amount);\n        }\n    }\n\n    @Override\n    public String getFormattedFullQuantity() {\n        if (zeroed) {\n            return \"0 mB\";\n        }\n\n        return API.instance().getQuantityFormatter().format(getQuantity()) + \" mB\";\n    }\n\n    @Override\n    public void draw(GuiGraphics graphics, BaseScreen<?> screen, int x, int y) {\n        FluidRenderer.INSTANCE.render(graphics, x, y, stack);\n\n        String text;\n        int color = RenderSettings.INSTANCE.getSecondaryColor();\n\n        if (zeroed) {\n            text = \"0\";\n            color = 16733525;\n        } else if (isCraftable()) {\n            text = I18n.get(\"gui.refinedstorage.grid.craft\");\n        } else {\n            text = API.instance().getQuantityFormatter().formatInBucketFormWithOnlyTrailingDigitsIfZero(getQuantity());\n        }\n\n        screen.renderQuantity(graphics, x, y, text, color);\n    }\n\n    @Override\n    public Object getIngredient() {\n        return getStack();\n    }\n\n    @Nullable\n    @Override\n    public StorageTrackerEntry getTrackerEntry() {\n        return entry;\n    }\n\n    @Override\n    public void setTrackerEntry(@Nullable StorageTrackerEntry entry) {\n        this.entry = entry;\n    }\n\n    public static FluidGridStack of(\n        final IStorageCache<FluidStack> cache,\n        @Nullable final IStackList<FluidStack> craftablesList,\n        final IStorageTracker<FluidStack> storageTracker,\n        final StackListResult<FluidStack> delta\n    ) {\n        StackListEntry<FluidStack> craftingEntry = craftablesList == null ? null : cache.getCraftablesList().getEntry(delta.getStack(), IComparer.COMPARE_NBT);\n        return new FluidGridStack(\n            delta.getId(),\n            craftingEntry != null ? craftingEntry.getId() : null,\n            delta.getStack().copy(), // copy is very important as the same stack will be shared between server<->client on single player\n            false,\n            storageTracker.get(delta.getStack())\n        );\n    }\n\n    public static FluidGridStack of(\n        final StackListEntry<FluidStack> entry,\n        final IStorageTracker<FluidStack> storageTracker,\n        @Nullable final IStackList<FluidStack> oppositeList,\n        final boolean craftable\n    ) {\n        StackListEntry<FluidStack> otherEntry =\n            oppositeList == null ? null : oppositeList.getEntry(entry.getStack(), IComparer.COMPARE_NBT);\n        return new FluidGridStack(\n            entry.getId(),\n            otherEntry != null ? otherEntry.getId() : null,\n            entry.getStack().copy(), // copy is very important as the same stack will be shared between server<->client on single player\n            craftable,\n            storageTracker.get(entry.getStack())\n        );\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/stack/IGridStack.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid.stack;\n\nimport com.refinedmods.refinedstorage.api.storage.tracker.StorageTrackerEntry;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.network.chat.Component;\n\nimport javax.annotation.Nullable;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.UUID;\n\npublic interface IGridStack {\n    UUID getId();\n\n    @Nullable\n    UUID getOtherId();\n\n    void updateOtherId(@Nullable UUID otherId);\n\n    String getName();\n\n    String getModId();\n\n    String getModName();\n\n    Set<String> getTags();\n\n    List<Component> getTooltip(boolean bypassCache);\n\n    int getQuantity();\n\n    void setQuantity(int amount);\n\n    String getFormattedFullQuantity();\n\n    void draw(GuiGraphics graphics, BaseScreen<?> screen, int x, int y);\n\n    Object getIngredient();\n\n    @Nullable\n    StorageTrackerEntry getTrackerEntry();\n\n    void setTrackerEntry(@Nullable StorageTrackerEntry entry);\n\n    boolean isCraftable();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/stack/ItemGridStack.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid.stack;\n\nimport com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;\nimport com.refinedmods.refinedstorage.api.storage.tracker.IStorageTracker;\nimport com.refinedmods.refinedstorage.api.storage.tracker.StorageTrackerEntry;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.api.util.IStackList;\nimport com.refinedmods.refinedstorage.api.util.StackListEntry;\nimport com.refinedmods.refinedstorage.api.util.StackListResult;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.render.RenderSettings;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.UUID;\nimport java.util.stream.Collectors;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.tags.TagKey;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.fml.ModContainer;\nimport net.neoforged.fml.ModList;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\n\npublic class ItemGridStack implements IGridStack {\n    private static final String ERROR_PLACEHOLDER = \"<Error>\";\n\n    private static final Logger LOGGER = LogManager.getLogger(ItemGridStack.class);\n    private final ItemStack stack;\n    private UUID id;\n    @Nullable\n    private UUID otherId;\n    private boolean craftable;\n    @Nullable\n    private StorageTrackerEntry entry;\n    private boolean zeroed;\n\n    private Set<String> cachedTags;\n    private String cachedName;\n    private String cachedModId;\n    private String cachedModName;\n    private List<Component> cachedTooltip;\n\n    public ItemGridStack(ItemStack stack) {\n        this.stack = stack;\n    }\n\n    public ItemGridStack(UUID id, @Nullable UUID otherId, ItemStack stack, boolean craftable,\n                         StorageTrackerEntry entry) {\n        this.id = id;\n        this.otherId = otherId;\n        this.stack = stack;\n        this.craftable = craftable;\n        this.entry = entry;\n    }\n\n    @Nullable\n    static String getModNameByModId(String modId) {\n        Optional<? extends ModContainer> modContainer = ModList.get().getModContainerById(modId);\n\n        return modContainer.map(container -> container.getModInfo().getDisplayName()).orElse(null);\n    }\n\n    public void setZeroed(boolean zeroed) {\n        this.zeroed = zeroed;\n    }\n\n    public ItemStack getStack() {\n        return stack;\n    }\n\n    @Override\n    public boolean isCraftable() {\n        return craftable;\n    }\n\n    @Override\n    public UUID getId() {\n        return id;\n    }\n\n    @Nullable\n    @Override\n    public UUID getOtherId() {\n        return otherId;\n    }\n\n    @Override\n    public void updateOtherId(@Nullable UUID otherId) {\n        this.otherId = otherId;\n    }\n\n    @Override\n    public String getName() {\n        if (cachedName == null) {\n            try {\n                cachedName = stack.getHoverName().getString();\n            } catch (Throwable t) {\n                LOGGER.warn(\"Could not retrieve item name of {}\", BuiltInRegistries.ITEM.getKey(stack.getItem()));\n\n                cachedName = ERROR_PLACEHOLDER;\n            }\n        }\n\n        return cachedName;\n    }\n\n    @Override\n    public String getModId() {\n        if (cachedModId == null) {\n            cachedModId = stack.getItem().getCreatorModId(stack);\n\n            if (cachedModId == null) {\n                cachedModId = ERROR_PLACEHOLDER;\n            }\n\n            cachedModId = cachedModId.toLowerCase().replace(\" \", \"\");\n        }\n\n        return cachedModId;\n    }\n\n    @Override\n    public String getModName() {\n        if (cachedModName == null) {\n            cachedModName = getModNameByModId(getModId());\n\n            if (cachedModName == null) {\n                cachedModName = ERROR_PLACEHOLDER;\n            }\n        }\n\n        return cachedModName;\n    }\n\n    @Override\n    public Set<String> getTags() {\n        if (cachedTags == null) {\n            cachedTags = BuiltInRegistries.ITEM.getResourceKey(stack.getItem())\n                .flatMap(k -> BuiltInRegistries.ITEM.getHolder(k)\n                    .map(holder -> holder.tags()\n                        .map(TagKey::location)\n                        .map(ResourceLocation::getPath)\n                        .collect(Collectors.toSet())))\n                .orElse(Collections.emptySet());\n        }\n\n        return cachedTags;\n    }\n\n    @Override\n    public List<Component> getTooltip(boolean bypassCache) {\n        if (bypassCache || cachedTooltip == null) {\n            List<Component> tooltip;\n            try {\n                tooltip = RenderUtils.getTooltipFromItem(stack);\n            } catch (Throwable t) {\n                LOGGER.warn(\"Could not retrieve item tooltip of {}\", BuiltInRegistries.ITEM.getKey(stack.getItem()));\n\n                tooltip = new ArrayList<>();\n                tooltip.add(Component.literal(ERROR_PLACEHOLDER));\n            }\n\n            if (bypassCache) {\n                return tooltip;\n            } else {\n                cachedTooltip = tooltip;\n            }\n        }\n\n        return cachedTooltip;\n    }\n\n    @Override\n    public int getQuantity() {\n        // The isCraftable check is needed so sorting is applied correctly\n        return isCraftable() || zeroed ? 0 : stack.getCount();\n    }\n\n    @Override\n    public void setQuantity(int amount) {\n        if (amount <= 0) {\n            setZeroed(true);\n        } else {\n            stack.setCount(amount);\n        }\n    }\n\n    @Override\n    public String getFormattedFullQuantity() {\n        if (zeroed) {\n            return \"0\";\n        }\n\n        return API.instance().getQuantityFormatter().format(getQuantity());\n    }\n\n    @Override\n    public void draw(GuiGraphics graphics, BaseScreen<?> screen, int x, int y) {\n        String text = null;\n        int color = RenderSettings.INSTANCE.getSecondaryColor();\n\n        if (zeroed) {\n            text = \"0\";\n            color = 16733525;\n        } else if (craftable) {\n            text = I18n.get(\"gui.refinedstorage.grid.craft\");\n        } else if (stack.getCount() > 1) {\n            text = API.instance().getQuantityFormatter().formatWithUnits(getQuantity());\n        }\n\n        screen.renderItem(graphics, x, y, stack, true, text, color);\n    }\n\n    @Override\n    public Object getIngredient() {\n        return getStack();\n    }\n\n    @Nullable\n    @Override\n    public StorageTrackerEntry getTrackerEntry() {\n        return entry;\n    }\n\n    @Override\n    public void setTrackerEntry(@Nullable StorageTrackerEntry entry) {\n        this.entry = entry;\n    }\n\n    public static ItemGridStack of(\n        final IStorageCache<ItemStack> cache,\n        @Nullable final IStackList<ItemStack> craftablesList,\n        final IStorageTracker<ItemStack> storageTracker,\n        final StackListResult<ItemStack> delta\n    ) {\n        StackListEntry<ItemStack> craftingEntry = craftablesList == null ? null : cache.getCraftablesList().getEntry(delta.getStack(), IComparer.COMPARE_NBT);\n        return new ItemGridStack(\n            delta.getId(),\n            craftingEntry != null ? craftingEntry.getId() : null,\n            delta.getStack().copy(), // copy is very important as the same stack will be shared between server<->client on single player\n            false,\n            storageTracker.get(delta.getStack())\n        );\n    }\n\n    public static ItemGridStack of(\n        final StackListEntry<ItemStack> entry,\n        final IStorageTracker<ItemStack> storageTracker,\n        @Nullable final IStackList<ItemStack> oppositeList,\n        final boolean craftable\n    ) {\n        StackListEntry<ItemStack> otherEntry = oppositeList == null ? null : oppositeList.getEntry(entry.getStack(), IComparer.COMPARE_NBT);\n        return new ItemGridStack(\n            entry.getId(),\n            otherEntry != null ? otherEntry.getId() : null,\n            entry.getStack().copy(), // copy is very important as the same stack will be shared between server<->client on single player\n            craftable,\n            storageTracker.get(entry.getStack())\n        );\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/view/GridViewImpl.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid.view;\n\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.integration.jei.IngredientTracker;\nimport com.refinedmods.refinedstorage.screen.grid.GridScreen;\nimport com.refinedmods.refinedstorage.screen.grid.filtering.GridFilterParser;\nimport com.refinedmods.refinedstorage.screen.grid.sorting.IGridSorter;\nimport com.refinedmods.refinedstorage.screen.grid.sorting.SortingDirection;\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\n\nimport javax.annotation.Nullable;\nimport java.util.*;\nimport java.util.function.Consumer;\nimport java.util.function.Predicate;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\npublic class GridViewImpl implements IGridView {\n    protected final Map<UUID, IGridStack> map = new HashMap<>();\n    private final GridScreen screen;\n    private final IGridSorter defaultSorter;\n    private final List<IGridSorter> sorters;\n    private boolean canCraft;\n    private boolean active = false;\n    private List<IGridStack> stacks = new ArrayList<>();\n\n    private List<Consumer<IGridStack>> deltaListeners = new ArrayList<>();\n\n    public GridViewImpl(GridScreen screen, IGridSorter defaultSorter, List<IGridSorter> sorters) {\n        this.screen = screen;\n        this.defaultSorter = defaultSorter;\n        this.sorters = sorters;\n    }\n\n    @Override\n    public List<IGridStack> getStacks() {\n        return stacks;\n    }\n\n    @Override\n    public void setStacks(List<? extends IGridStack> stacks) {\n        map.clear();\n\n        for (IGridStack stack : stacks) {\n            map.put(stack.getId(), stack);\n        }\n    }\n\n    @Override\n    public Collection<IGridStack> getAllStacks() {\n        return map.values();\n    }\n\n    @Nullable\n    @Override\n    public IGridStack get(UUID id) {\n        return map.get(id);\n    }\n\n    @Override\n    public void sort() {\n        if (!screen.canSort()) {\n            return;\n        }\n\n        forceSort();\n    }\n\n    @Override\n    public void forceSort() {\n        if (screen.getGrid().isGridActive()) {\n            this.stacks = map.values().stream()\n                    .filter(getActiveFilters())\n                    .sorted(getActiveSort())\n                    .collect(Collectors.toCollection(ArrayList::new));\n            this.active = true;\n        } else {\n            this.stacks = new ArrayList<>();\n            this.active = false;\n        }\n\n        this.screen.updateScrollbar();\n    }\n\n    @Override\n    public void addDeltaListener(Consumer<IGridStack> listener) {\n        deltaListeners.add(listener);\n    }\n\n    @Override\n    public void removed() {\n        deltaListeners.clear();\n        IngredientTracker.invalidate();\n    }\n\n    private Comparator<IGridStack> getActiveSort() {\n        IGrid grid = screen.getGrid();\n        SortingDirection sortingDirection = grid.getSortingDirection() == IGrid.SORTING_DIRECTION_DESCENDING ? SortingDirection.DESCENDING : SortingDirection.ASCENDING;\n        return Stream.concat(Stream.of(defaultSorter), sorters.stream().filter(s -> s.isApplicable(grid)))\n            .map(sorter -> (Comparator<IGridStack>) (o1, o2) -> sorter.compare(o1, o2, sortingDirection))\n            .reduce((l, r) -> r.thenComparing(l))\n            .orElseThrow(IllegalStateException::new);  // There is at least 1 value in the stream (i.e. defaultSorter)\n    }\n\n    private Predicate<IGridStack> getActiveFilters() {\n        IGrid grid = screen.getGrid();\n\n        Predicate<IGridStack> filters = GridFilterParser.getFilters(\n            grid,\n            screen.getSearchFieldText(),\n            (grid.getTabSelected() >= 0 && grid.getTabSelected() < grid.getTabs().size()) ? grid.getTabs().get(grid.getTabSelected()).getFilters() : grid.getFilters()\n        );\n\n        if (screen.getGrid().getViewType() != IGrid.VIEW_TYPE_CRAFTABLES) {\n            return stack -> {\n                // If this is a crafting stack,\n                // and there is a regular matching stack in the view too,\n                // and we aren't in \"view only craftables\" mode,\n                // we don't want the duplicate stacks and we will remove this stack.\n                if (stack.isCraftable() &&\n                    stack.getOtherId() != null &&\n                    map.containsKey(stack.getOtherId())) {\n                    return false;\n                }\n\n                return filters.test(stack);\n            };\n        } else {\n            return filters;\n        }\n    }\n\n    @Override\n    public void postChange(IGridStack stack, int delta) {\n        if (!this.active) {\n            return;\n        }\n        // COMMENT 1 (about this if check in general)\n        // Update the other id reference if needed.\n        // Taking a stack out - and then re-inserting it - gives the new stack a new ID\n        // With that new id, the reference for the crafting stack would be outdated.\n\n        // COMMENT 2 (about map.containsKey(stack.getOtherId()))\n        // This check is needed or the .updateOtherId() call will crash with a NPE in high-update environments.\n        // This is because we might have scenarios where we process \"old\" delta packets from another session when we haven't received any initial update packet from the new session.\n        // (This is because of the executeLater system)\n        // This causes the .updateOtherId() to fail with a NPE because the map is still empty or the IDs mismatch.\n        // We could use !map.isEmpty() here too. But if we have 2 \"old\" delta packets, it would rightfully ignore the first one. But this method mutates the map and would put an entry.\n        // This means that on the second delta packet it would still crash because the map wouldn't be empty anymore.\n        IGridStack craftingStack;\n        if (!stack.isCraftable() &&\n            stack.getOtherId() != null &&\n            map.containsKey(stack.getOtherId())) {\n            craftingStack = map.get(stack.getOtherId());\n\n            craftingStack.updateOtherId(stack.getId());\n            craftingStack.setTrackerEntry(stack.getTrackerEntry());\n        } else {\n            craftingStack = null;\n        }\n\n        Predicate<IGridStack> activeFilters = getActiveFilters();\n        IGridStack existing = map.get(stack.getId());\n        boolean stillExists = true;\n        boolean shouldSort = screen.canSort();\n\n        if (existing == null) {\n            stack.setQuantity(delta);\n\n            map.put(stack.getId(), stack);\n            existing = stack;\n\n            if (craftingStack != null && shouldSort && activeFilters.test(existing)) {\n                stacks.remove(craftingStack);\n            }\n\n            deltaListeners.forEach(consumer -> consumer.accept(stack));\n\n        } else {\n            if (shouldSort) {\n                stacks.remove(existing);\n            }\n            existing.setQuantity(existing.getQuantity() + delta);\n            if (existing.getQuantity() <= 0) {\n                map.remove(existing.getId());\n                stillExists = false;\n\n                if (craftingStack != null && shouldSort && activeFilters.test(existing) && activeFilters.test(craftingStack)) {\n                    addStack(craftingStack);\n                }\n            }\n\n            existing.setTrackerEntry(stack.getTrackerEntry());\n        }\n\n        if (shouldSort) {\n            if (stillExists && activeFilters.test(existing)) {\n                addStack(existing);\n            }\n            this.screen.updateScrollbar();\n        }\n    }\n\n    private void addStack(IGridStack stack) {\n        int insertionPos = Collections.binarySearch(stacks, stack, getActiveSort());\n        if (insertionPos < 0) {\n            insertionPos = -insertionPos - 1;\n        }\n        stacks.add(insertionPos, stack);\n    }\n\n    @Override\n    public void setCanCraft(boolean canCraft) {\n        this.canCraft = canCraft;\n    }\n\n    @Override\n    public boolean canCraft() {\n        return canCraft;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/grid/view/IGridView.java",
    "content": "package com.refinedmods.refinedstorage.screen.grid.view;\n\nimport com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;\n\nimport javax.annotation.Nullable;\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.UUID;\nimport java.util.function.Consumer;\n\npublic interface IGridView {\n    List<IGridStack> getStacks();\n\n    void setStacks(List<? extends IGridStack> stacks);\n\n    @Nullable\n    IGridStack get(UUID id);\n\n    Collection<IGridStack> getAllStacks();\n\n    void postChange(IGridStack stack, int delta);\n\n    void setCanCraft(boolean canCraft);\n\n    boolean canCraft();\n\n    void sort();\n\n    void forceSort();\n\n    void addDeltaListener(Consumer<IGridStack> listener);\n\n    void removed();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/ScrollbarWidget.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget;\n\nimport com.mojang.blaze3d.systems.RenderSystem;\nimport com.refinedmods.refinedstorage.integration.jei.GridRecipeTransferHandler;\nimport com.refinedmods.refinedstorage.integration.jei.JeiIntegration;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.gui.components.events.GuiEventListener;\n\nimport java.util.LinkedList;\nimport java.util.List;\n\npublic class ScrollbarWidget implements GuiEventListener {\n    private static final float SCROLLER_HEIGHT = 15;\n\n    private final int x;\n    private final int y;\n    private final int width;\n    private final int height;\n    private final List<ScrollbarWidgetListener> listeners = new LinkedList<>();\n    private final BaseScreen<?> screen;\n    private boolean enabled = false;\n    private int offset;\n    private int maxOffset;\n    private boolean clicked = false;\n    private boolean small = false;\n    private boolean focused = false;\n\n    public ScrollbarWidget(BaseScreen<?> screen, int x, int y, int width, int height) {\n        this.screen = screen;\n        this.x = x;\n        this.y = y;\n        this.width = width;\n        this.height = height;\n    }\n\n    public ScrollbarWidget(BaseScreen screen, int x, int y, int width, int height, boolean small) {\n        this(screen, x, y, width, height);\n        this.small = small;\n    }\n\n    public void addListener(ScrollbarWidgetListener listener) {\n        listeners.add(listener);\n    }\n\n    public int getWidth() {\n        return width;\n    }\n\n    public int getHeight() {\n        return height;\n    }\n\n    public boolean isEnabled() {\n        return enabled;\n    }\n\n    public void setEnabled(boolean enabled) {\n        this.enabled = enabled;\n    }\n\n    public void render(GuiGraphics graphics) {\n        RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);\n        if (small) {\n            graphics.blit(BaseScreen.ICONS_TEXTURE, screen.getGuiLeft() + x, screen.getGuiTop() + y + (int) Math.min(height - SCROLLER_HEIGHT, (float) offset / (float) maxOffset * (height - SCROLLER_HEIGHT)), isEnabled() ? 218 : 225, 0, 7, (int) SCROLLER_HEIGHT);\n        } else {\n            graphics.blit(BaseScreen.ICONS_TEXTURE, screen.getGuiLeft() + x, screen.getGuiTop() + y + (int) Math.min(height - SCROLLER_HEIGHT, (float) offset / (float) maxOffset * (height - SCROLLER_HEIGHT)), isEnabled() ? 232 : 244, 0, 12, (int) SCROLLER_HEIGHT);\n        }\n    }\n\n    @Override\n    public boolean mouseClicked(double mx, double my, int button) {\n        mx -= screen.getGuiLeft();\n        my -= screen.getGuiTop();\n\n        if (button == 0 && RenderUtils.inBounds(x, y, width, height, mx, my)) {\n            // Prevent accidental scrollbar click after clicking recipe transfer button\n            if (JeiIntegration.isLoaded() && GridRecipeTransferHandler.INSTANCE.hasTransferredRecently()) {\n                return false;\n            }\n\n            updateOffset(my);\n\n            clicked = true;\n\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public void mouseMoved(double mx, double my) {\n        mx -= screen.getGuiLeft();\n        my -= screen.getGuiTop();\n\n        if (clicked && RenderUtils.inBounds(x, y, width, height, mx, my)) {\n            updateOffset(my);\n        }\n    }\n\n    private void updateOffset(double my) {\n        setOffset((int) Math.floor((float) (my - y) / (float) (height - SCROLLER_HEIGHT) * (float) maxOffset));\n    }\n\n    @Override\n    public boolean mouseReleased(double mx, double my, int button) {\n        if (clicked) {\n            clicked = false;\n\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean mouseScrolled(double x, double y, double z, double delta) {\n        if (isEnabled()) {\n            setOffset(offset + Math.max(Math.min(-(int) delta, 1), -1));\n\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public void setFocused(boolean focused) {\n        this.focused = focused;\n    }\n\n    @Override\n    public boolean isFocused() {\n        return focused;\n    }\n\n    public void setMaxOffset(int maxOffset) {\n        this.maxOffset = maxOffset;\n\n        if (offset > maxOffset) {\n            this.offset = Math.max(0, maxOffset);\n        }\n    }\n\n    public int getOffset() {\n        return offset;\n    }\n\n    public void setOffset(int offset) {\n        int oldOffset = this.offset;\n\n        if (offset >= 0 && offset <= maxOffset) {\n            this.offset = offset;\n\n            listeners.forEach(l -> l.onOffsetChanged(oldOffset, offset));\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/ScrollbarWidgetListener.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget;\n\npublic interface ScrollbarWidgetListener {\n    void onOffsetChanged(int oldOffset, int newOffset);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/SearchWidget.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget;\n\nimport com.refinedmods.refinedstorage.RSKeyBindings;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.integration.jei.JeiIntegration;\nimport com.refinedmods.refinedstorage.integration.jei.RSJeiPlugin;\nimport com.refinedmods.refinedstorage.render.RenderSettings;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport net.minecraft.client.gui.Font;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.gui.components.EditBox;\nimport net.minecraft.network.chat.Component;\nimport org.lwjgl.glfw.GLFW;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SearchWidget extends EditBox {\n    private static final List<String> HISTORY = new ArrayList<>();\n\n    private int mode;\n    private int historyIndex = -1;\n\n    public SearchWidget(Font fontRenderer, int x, int y, int width) {\n        super(fontRenderer, x, y, width, fontRenderer.lineHeight, Component.literal(\"\"));\n\n        this.setBordered(false);\n        this.setVisible(true);\n        this.setTextColor(RenderSettings.INSTANCE.getSecondaryColor());\n    }\n\n    public void updateJei() {\n        if (canSyncToJEINow()) {\n            RSJeiPlugin.getRuntime().getIngredientFilter().setFilterText(getValue());\n        }\n    }\n\n    private boolean canSyncToJEINow() {\n        return IGrid.doesSearchBoxModeUseJEI(this.mode) && JeiIntegration.isLoaded();\n    }\n\n    private boolean canSyncFromJEINow() {\n        return (this.mode == IGrid.SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY ||\n            this.mode == IGrid.SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY_AUTOSELECTED)\n            && JeiIntegration.isLoaded();\n    }\n\n    @Override\n    public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) {\n        boolean result = super.mouseClicked(mouseX, mouseY, mouseButton);\n        boolean clickedWidget = mouseX >= this.getX() && mouseX < this.getX() + this.width && mouseY >= this.getY() && mouseY < this.getY() + this.height;\n\n        if (clickedWidget && mouseButton == 1) {\n            // On right click, clear the widget and focus, save history if necessary.\n            if (isFocused()) {\n                saveHistory();\n            }\n            setValue(\"\");\n            setFocused(true);\n        }\n\n        if (!clickedWidget && isFocused()) {\n            // If we are focused, and we click outside the search box, lose focus.\n            saveHistory();\n            setFocused(false);\n        }\n\n        return result;\n    }\n\n    @Override\n    public boolean keyPressed(int keyCode, int scanCode, int modifier) {\n        if (super.keyPressed(keyCode, scanCode, modifier)) {\n            return true;\n        }\n\n        if (isFocused()) {\n            if (keyCode == GLFW.GLFW_KEY_UP) {\n                updateHistory(-1);\n            } else if (keyCode == GLFW.GLFW_KEY_DOWN) {\n                updateHistory(1);\n            } else if (keyCode == GLFW.GLFW_KEY_ENTER || keyCode == GLFW.GLFW_KEY_KP_ENTER) {\n                saveHistory();\n                if (canLoseFocus) {\n                    setFocused(false);\n                }\n            } else if (keyCode == GLFW.GLFW_KEY_ESCAPE) {\n                saveHistory();\n                if (!canLoseFocus) {\n                    // If we can't lose focus,\n                    // and we press escape,\n                    // we unfocus ourselves,\n                    // and close the screen immediately.\n                    setFocused(false);\n                    return false; // Bubble the event up to the screen.\n                } else {\n                    // If we can lose focus,\n                    // and we press escape,\n                    // we unfocus ourselves.\n                    // On the next escape press, the screen will close.\n                    setFocused(false);\n                    return true; // Swallow\n                }\n            }\n        }\n\n        if (BaseScreen.isKeyDown(RSKeyBindings.FOCUS_SEARCH_BAR) && canLoseFocus) {\n            setFocused(!isFocused());\n            saveHistory();\n            return true;\n        }\n\n        return isFocused() && canConsumeInput() && keyCode != GLFW.GLFW_KEY_ESCAPE;\n    }\n\n    private void updateHistory(int delta) {\n        if (HISTORY.isEmpty()) {\n            return;\n        }\n\n        if (historyIndex == -1) {\n            historyIndex = HISTORY.size();\n        }\n\n        historyIndex += delta;\n\n        if (historyIndex < 0) {\n            historyIndex = 0;\n        } else if (historyIndex > HISTORY.size() - 1) {\n            historyIndex = HISTORY.size() - 1;\n\n            if (delta == 1) {\n                setValue(\"\");\n\n                return;\n            }\n        }\n\n        setValue(HISTORY.get(historyIndex));\n    }\n\n    private void saveHistory() {\n        if (!HISTORY.isEmpty() && HISTORY.get(HISTORY.size() - 1).equals(getValue())) {\n            return;\n        }\n\n        if (!getValue().trim().isEmpty()) {\n            HISTORY.add(getValue());\n        }\n    }\n\n    public void setMode(int mode) {\n        this.mode = mode;\n\n        this.setCanLoseFocus(!IGrid.isSearchBoxModeWithAutoselection(mode));\n        this.setFocused(IGrid.isSearchBoxModeWithAutoselection(mode));\n\n        if (canSyncFromJEINow()) {\n            setTextFromJEI();\n        }\n    }\n\n    private void setTextFromJEI() {\n        final String filterText = RSJeiPlugin.getRuntime().getIngredientFilter().getFilterText();\n        if (!getValue().equals(filterText)) {\n            setValue(filterText);\n        }\n    }\n\n    @Override\n    public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {\n        if (canSyncFromJEINow() && RSJeiPlugin.getRuntime().getIngredientListOverlay().hasKeyboardFocus()) {\n            setTextFromJEI();\n        }\n        super.renderWidget(graphics, mouseX, mouseY, partialTicks);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/SmallCheckboxWidget.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget;\n\nimport java.util.function.Consumer;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.gui.components.AbstractButton;\nimport net.minecraft.client.gui.narration.NarratedElementType;\nimport net.minecraft.client.gui.narration.NarrationElementOutput;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.resources.ResourceLocation;\n\npublic class SmallCheckboxWidget extends AbstractButton {\n    private static final ResourceLocation CHECKBOX_SELECTED_HIGHLIGHTED_SPRITE =\n        new ResourceLocation(\"widget/checkbox_selected_highlighted\");\n    private static final ResourceLocation CHECKBOX_SELECTED_SPRITE = new ResourceLocation(\"widget/checkbox_selected\");\n    private static final ResourceLocation CHECKBOX_HIGHLIGHTED_SPRITE =\n        new ResourceLocation(\"widget/checkbox_highlighted\");\n    private static final ResourceLocation CHECKBOX_SPRITE = new ResourceLocation(\"widget/checkbox\");\n\n    private static final int BOX_WIDTH = 13;\n\n    private final Consumer<SmallCheckboxWidget> onPress;\n    private boolean shadow = true;\n    private boolean selected;\n\n    public SmallCheckboxWidget(int x, int y, Component text, boolean isSelected, Consumer<SmallCheckboxWidget> onPress) {\n        super(\n            x,\n            y,\n            Minecraft.getInstance().font.width(text.getString()) + BOX_WIDTH + 4,\n            10,\n            text\n        );\n        this.selected = isSelected;\n        this.onPress = onPress;\n    }\n\n    public void setSelected(boolean value) {\n        this.selected = value;\n    }\n\n    public boolean isSelected() {\n        return selected;\n    }\n\n    public void setShadow(boolean shadow) {\n        this.shadow = shadow;\n    }\n\n    @Override\n    public void onPress() {\n        this.selected = !selected;\n        this.onPress.accept(this);\n    }\n\n    @Override\n    public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {\n        ResourceLocation texture;\n        if (this.selected) {\n            texture = isFocused() ? CHECKBOX_SELECTED_HIGHLIGHTED_SPRITE : CHECKBOX_SELECTED_SPRITE;\n        } else {\n            texture = isFocused() ? CHECKBOX_HIGHLIGHTED_SPRITE : CHECKBOX_SPRITE;\n        }\n\n        int color = 14737632;\n\n        if (!active) {\n            color = 10526880;\n        } else if (packedFGColor != 0) {\n            color = packedFGColor;\n        }\n\n        int i = BOX_WIDTH;\n        int j = this.getX() + i + 4;\n        int k = this.getY() + (this.height - 8) / 2;\n        graphics.blitSprite(texture, this.getX(), this.getY(), i, i);\n        graphics.setColor(1.0F, 1.0F, 1.0F, 1.0F);\n        graphics.drawString(Minecraft.getInstance().font, this.getMessage(), j, k, color, shadow);\n    }\n\n    @Override\n    protected void updateWidgetNarration(NarrationElementOutput output) {\n        output.add(NarratedElementType.TITLE, this.createNarrationMessage());\n        if (this.active) {\n            if (this.isFocused()) {\n                output.add(NarratedElementType.USAGE, Component.translatable(\"narration.checkbox.usage.focused\"));\n            } else {\n                output.add(NarratedElementType.USAGE, Component.translatable(\"narration.checkbox.usage.hovered\"));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/TabListWidget.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget;\n\nimport com.refinedmods.refinedstorage.api.network.grid.IGridTab;\nimport com.refinedmods.refinedstorage.apiimpl.render.ElementDrawers;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.client.gui.Font;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.gui.components.Button;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\n\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.function.Supplier;\n\npublic class TabListWidget<T extends AbstractContainerMenu> {\n    private final BaseScreen<?> screen;\n    private final ElementDrawers<T> drawers;\n    private final Supplier<List<IGridTab>> tabs;\n    private final int tabsPerPage;\n    private final Supplier<Integer> pages;\n    private final Supplier<Integer> page;\n    private final Supplier<Integer> selected;\n    private final List<ITabListListener> listeners = new LinkedList<>();\n    private int tabHovering;\n    private boolean hadTabs;\n    private Button left;\n    private Button right;\n\n    public TabListWidget(BaseScreen<T> screen, ElementDrawers<T> drawers, Supplier<List<IGridTab>> tabs, Supplier<Integer> pages, Supplier<Integer> page, Supplier<Integer> selected, int tabsPerPage) {\n        this.screen = screen;\n        this.drawers = drawers;\n        this.tabs = tabs;\n        this.pages = pages;\n        this.page = page;\n        this.selected = selected;\n        this.tabsPerPage = tabsPerPage;\n    }\n\n    public void init(int width) {\n        this.left = screen.addButton(screen.getGuiLeft(), screen.getGuiTop() - 22, 20, 20, Component.literal(\"<\"), true, pages.get() > 0, btn -> listeners.forEach(t -> t.onPageChanged(page.get() - 1)));\n        this.right = screen.addButton(screen.getGuiLeft() + width - 22, screen.getGuiTop() - 22, 20, 20, Component.literal(\">\"), true, pages.get() > 0, btn -> listeners.forEach(t -> t.onPageChanged(page.get() + 1)));\n    }\n\n    public void addListener(ITabListListener listener) {\n        listeners.add(listener);\n    }\n\n    public void drawForeground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY, boolean visible) {\n        this.tabHovering = -1;\n\n        if (visible) {\n            int j = 0;\n            for (int i = page.get() * tabsPerPage; i < (page.get() * tabsPerPage) + tabsPerPage; ++i) {\n                if (i < tabs.get().size()) {\n                    drawTab(graphics, tabs.get().get(i), true, x, y, i, j);\n\n                    if (RenderUtils.inBounds(x + getXOffset() + ((IGridTab.TAB_WIDTH + 1) * j), y, IGridTab.TAB_WIDTH, IGridTab.TAB_HEIGHT - (i == selected.get() ? 2 : 7), mouseX, mouseY)) {\n                        this.tabHovering = i;\n                    }\n\n                    j++;\n                }\n            }\n        }\n    }\n\n    public void update() {\n        boolean hasTabs = !tabs.get().isEmpty();\n\n        if (this.hadTabs != hasTabs) {\n            this.hadTabs = hasTabs;\n\n            screen.init();\n        }\n\n        if (page.get() > pages.get()) {\n            listeners.forEach(t -> t.onPageChanged(pages.get()));\n        }\n\n        left.visible = pages.get() > 0;\n        right.visible = pages.get() > 0;\n\n        left.active = page.get() > 0;\n        right.active = page.get() < pages.get();\n    }\n\n    public void drawBackground(GuiGraphics graphics, int x, int y) {\n        int j = 0;\n        for (int i = page.get() * tabsPerPage; i < (page.get() * tabsPerPage) + tabsPerPage; ++i) {\n            if (i < tabs.get().size()) {\n                drawTab(graphics, tabs.get().get(i), false, x, y, i, j++);\n            }\n        }\n    }\n\n    public int getHeight() {\n        return !tabs.get().isEmpty() ? IGridTab.TAB_HEIGHT - 4 : 0;\n    }\n\n    private int getXOffset() {\n        if (pages.get() > 0) {\n            return 24;\n        }\n\n        return 0;\n    }\n\n    private void drawTab(GuiGraphics graphics, IGridTab tab, boolean foregroundLayer, int x, int y, int index, int num) {\n        boolean isSelected = index == selected.get();\n\n        if ((foregroundLayer && !isSelected) || (!foregroundLayer && isSelected)) {\n            return;\n        }\n\n        int tx = x + getXOffset() + ((IGridTab.TAB_WIDTH + 1) * num);\n        int ty = y;\n\n        if (!isSelected) {\n            ty += 3;\n        }\n\n        int uvx;\n        int uvy = 225;\n        int tbw = IGridTab.TAB_WIDTH;\n        int otx = tx;\n\n        if (isSelected) {\n            uvx = 227;\n\n            if (num > 0 || getXOffset() != 0) {\n                uvx = 226;\n                uvy = 194;\n                tbw++;\n                tx--;\n            }\n        } else {\n            uvx = 199;\n        }\n\n        graphics.blit(BaseScreen.ICONS_TEXTURE, tx, ty, uvx, uvy, tbw, IGridTab.TAB_HEIGHT);\n\n        tab.drawIcon(graphics, otx + 6, ty + 9 - (!isSelected ? 3 : 0), drawers.getItemDrawer(), drawers.getFluidDrawer());\n    }\n\n    public void drawTooltip(GuiGraphics graphics, Font font, int mouseX, int mouseY) {\n        if (tabHovering >= 0 && tabHovering < tabs.get().size()) {\n            tabs.get().get(tabHovering).drawTooltip(font, graphics, mouseX, mouseY);\n        }\n    }\n\n    public boolean mouseClicked() {\n        if (tabHovering >= 0 && tabHovering < tabs.get().size()) {\n            listeners.forEach(t -> t.onSelectionChanged(tabHovering));\n\n            return true;\n        }\n\n        return false;\n    }\n\n    public interface ITabListListener {\n        void onSelectionChanged(int tab);\n\n        void onPageChanged(int page);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/AccessTypeSideButton.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget.sidebutton;\n\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.util.AccessTypeUtils;\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\n\npublic class AccessTypeSideButton extends SideButton {\n    private final BlockEntitySynchronizationParameter<AccessType, ?> parameter;\n\n    public AccessTypeSideButton(BaseScreen<?> screen, BlockEntitySynchronizationParameter<AccessType, ?> parameter) {\n        super(screen);\n\n        this.parameter = parameter;\n    }\n\n    @Override\n    protected void renderButtonIcon(GuiGraphics graphics, int x, int y) {\n        graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, 16 * parameter.getValue().getId(), 240, 16, 16);\n    }\n\n    @Override\n    protected String getSideButtonTooltip() {\n        return I18n.get(\"sidebutton.refinedstorage.access_type\") + \"\\n\" + ChatFormatting.GRAY + I18n.get(\"sidebutton.refinedstorage.access_type.\" + parameter.getValue().getId());\n    }\n\n    @Override\n    public void onPress() {\n        BlockEntitySynchronizationManager.setParameter(parameter, AccessTypeUtils.getAccessType(parameter.getValue().getId() + 1));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/ConstructorDropSideButton.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget.sidebutton;\n\nimport com.refinedmods.refinedstorage.blockentity.ConstructorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport com.refinedmods.refinedstorage.container.ConstructorContainerMenu;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\n\npublic class ConstructorDropSideButton extends SideButton {\n    public ConstructorDropSideButton(BaseScreen<ConstructorContainerMenu> screen) {\n        super(screen);\n    }\n\n    @Override\n    protected void renderButtonIcon(GuiGraphics graphics, int x, int y) {\n        graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, 64 + (Boolean.TRUE.equals(ConstructorBlockEntity.DROP.getValue()) ? 16 : 0), 16, 16, 16);\n    }\n\n    @Override\n    protected String getSideButtonTooltip() {\n        return I18n.get(\"sidebutton.refinedstorage.constructor.drop\") + \"\\n\" + ChatFormatting.GRAY + I18n.get(Boolean.TRUE.equals(ConstructorBlockEntity.DROP.getValue()) ? \"gui.yes\" : \"gui.no\");\n    }\n\n    @Override\n    public void onPress() {\n        BlockEntitySynchronizationManager.setParameter(ConstructorBlockEntity.DROP, !ConstructorBlockEntity.DROP.getValue());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/CrafterManagerSearchBoxModeSideButton.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget.sidebutton;\n\nimport com.refinedmods.refinedstorage.screen.CrafterManagerScreen;\nimport com.refinedmods.refinedstorage.blockentity.CrafterManagerBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\n\npublic class CrafterManagerSearchBoxModeSideButton extends SearchBoxModeSideButton {\n    public CrafterManagerSearchBoxModeSideButton(CrafterManagerScreen screen) {\n        super(screen);\n    }\n\n    @Override\n    protected int getSearchBoxMode() {\n        return ((CrafterManagerScreen) screen).getCrafterManager().getSearchBoxMode();\n    }\n\n    @Override\n    protected void setSearchBoxMode(int mode) {\n        BlockEntitySynchronizationManager.setParameter(CrafterManagerBlockEntity.SEARCH_BOX_MODE, mode);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/CrafterModeSideButton.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget.sidebutton;\n\nimport com.refinedmods.refinedstorage.blockentity.CrafterBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport com.refinedmods.refinedstorage.container.CrafterContainerMenu;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\n\npublic class CrafterModeSideButton extends SideButton {\n    public CrafterModeSideButton(BaseScreen<CrafterContainerMenu> screen) {\n        super(screen);\n    }\n\n    @Override\n    protected String getSideButtonTooltip() {\n        return I18n.get(\"sidebutton.refinedstorage.crafter_mode\") + \"\\n\" + ChatFormatting.GRAY + I18n.get(\"sidebutton.refinedstorage.crafter_mode.\" + CrafterBlockEntity.MODE.getValue());\n    }\n\n    @Override\n    protected void renderButtonIcon(GuiGraphics graphics, int x, int y) {\n        graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, CrafterBlockEntity.MODE.getValue() * 16, 0, 16, 16);\n    }\n\n    @Override\n    public void onPress() {\n        BlockEntitySynchronizationManager.setParameter(CrafterBlockEntity.MODE, CrafterBlockEntity.MODE.getValue() + 1);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/DestructorPickupSideButton.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget.sidebutton;\n\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.refinedmods.refinedstorage.container.DestructorContainerMenu;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.blockentity.DestructorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\n\npublic class DestructorPickupSideButton extends SideButton {\n    public DestructorPickupSideButton(BaseScreen<DestructorContainerMenu> screen) {\n        super(screen);\n    }\n\n    @Override\n    protected void renderButtonIcon(GuiGraphics graphics, int x, int y) {\n        graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, 64 + (Boolean.TRUE.equals(DestructorBlockEntity.PICKUP.getValue()) ? 0 : 16), 0, 16, 16);\n    }\n\n    @Override\n    protected String getSideButtonTooltip() {\n        return I18n.get(\"sidebutton.refinedstorage.destructor.pickup\") + \"\\n\" + ChatFormatting.GRAY + I18n.get(Boolean.TRUE.equals(DestructorBlockEntity.PICKUP.getValue()) ? \"gui.yes\" : \"gui.no\");\n    }\n\n    @Override\n    public void onPress() {\n        BlockEntitySynchronizationManager.setParameter(DestructorBlockEntity.PICKUP, !DestructorBlockEntity.PICKUP.getValue());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/DetectorModeSideButton.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget.sidebutton;\n\nimport com.refinedmods.refinedstorage.apiimpl.network.node.DetectorNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.DetectorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport com.refinedmods.refinedstorage.container.DetectorContainerMenu;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\n\npublic class DetectorModeSideButton extends SideButton {\n    public DetectorModeSideButton(BaseScreen<DetectorContainerMenu> screen) {\n        super(screen);\n    }\n\n    @Override\n    protected String getSideButtonTooltip() {\n        return I18n.get(\"sidebutton.refinedstorage.detector.mode\") + \"\\n\" + ChatFormatting.GRAY + I18n.get(\"sidebutton.refinedstorage.detector.mode.\" + DetectorBlockEntity.MODE.getValue());\n    }\n\n    @Override\n    protected void renderButtonIcon(GuiGraphics graphics, int x, int y) {\n        graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, DetectorBlockEntity.MODE.getValue() * 16, 176, 16, 16);\n    }\n\n    @Override\n    public void onPress() {\n        int mode = DetectorBlockEntity.MODE.getValue();\n\n        if (mode == DetectorNetworkNode.MODE_EQUAL) {\n            mode = DetectorNetworkNode.MODE_ABOVE;\n        } else if (mode == DetectorNetworkNode.MODE_ABOVE) {\n            mode = DetectorNetworkNode.MODE_UNDER;\n        } else if (mode == DetectorNetworkNode.MODE_UNDER) {\n            mode = DetectorNetworkNode.MODE_EQUAL;\n        }\n\n        BlockEntitySynchronizationManager.setParameter(DetectorBlockEntity.MODE, mode);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/ExactModeSideButton.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget.sidebutton;\n\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\n\npublic class ExactModeSideButton extends SideButton {\n    private static final int MASK = IComparer.COMPARE_NBT;\n\n    private final BlockEntitySynchronizationParameter<Integer, ?> parameter;\n\n    public ExactModeSideButton(BaseScreen<?> screen, BlockEntitySynchronizationParameter<Integer, ?> parameter) {\n        super(screen);\n\n        this.parameter = parameter;\n    }\n\n    @Override\n    protected String getSideButtonTooltip() {\n        String tooltip = I18n.get(\"sidebutton.refinedstorage.exact_mode\") + \"\\n\" + ChatFormatting.GRAY;\n\n        if ((parameter.getValue() & MASK) == MASK) {\n            tooltip += I18n.get(\"sidebutton.refinedstorage.exact_mode.on\");\n        } else {\n            tooltip += I18n.get(\"sidebutton.refinedstorage.exact_mode.off\");\n        }\n\n        return tooltip;\n    }\n\n    @Override\n    protected void renderButtonIcon(GuiGraphics graphics, int x, int y) {\n        int ty = 16 * 12;\n        int tx = (parameter.getValue() & MASK) == MASK ? 0 : 16;\n\n        graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, tx, ty, 16, 16);\n    }\n\n    @Override\n    public void onPress() {\n        BlockEntitySynchronizationManager.setParameter(parameter, parameter.getValue() ^ MASK);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/FilterTypeSideButton.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget.sidebutton;\n\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.screen.FilterScreen;\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\n\npublic class FilterTypeSideButton extends SideButton {\n    private final FilterScreen filterScreen;\n\n    public FilterTypeSideButton(FilterScreen filterScreen) {\n        super(filterScreen);\n\n        this.filterScreen = filterScreen;\n    }\n\n    @Override\n    protected String getSideButtonTooltip() {\n        return I18n.get(\"sidebutton.refinedstorage.type\") + \"\\n\" + ChatFormatting.GRAY + I18n.get(\"sidebutton.refinedstorage.type.\" + filterScreen.getType());\n    }\n\n    @Override\n    protected void renderButtonIcon(GuiGraphics graphics, int x, int y) {\n        graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, 16 * filterScreen.getType(), 128, 16, 16);\n    }\n\n    @Override\n    public void onPress() {\n        filterScreen.setType(filterScreen.getType() == IType.ITEMS ? IType.FLUIDS : IType.ITEMS);\n        filterScreen.sendUpdate();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/GridSearchBoxModeSideButton.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget.sidebutton;\n\nimport com.refinedmods.refinedstorage.screen.grid.GridScreen;\n\npublic class GridSearchBoxModeSideButton extends SearchBoxModeSideButton {\n    public GridSearchBoxModeSideButton(GridScreen screen) {\n        super(screen);\n    }\n\n    @Override\n    protected int getSearchBoxMode() {\n        return ((GridScreen) screen).getGrid().getSearchBoxMode();\n    }\n\n    @Override\n    protected void setSearchBoxMode(int mode) {\n        ((GridScreen) screen).getGrid().onSearchBoxModeChanged(mode);\n        ((GridScreen) screen).getSearchField().setMode(mode);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/GridSizeSideButton.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget.sidebutton;\n\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\n\nimport java.util.function.Consumer;\nimport java.util.function.Supplier;\n\npublic class GridSizeSideButton extends SideButton {\n    private final Supplier<Integer> sizeSupplier;\n    private final Consumer<Integer> listener;\n\n    public GridSizeSideButton(BaseScreen screen, Supplier<Integer> sizeSupplier, Consumer<Integer> listener) {\n        super(screen);\n        this.sizeSupplier = sizeSupplier;\n        this.listener = listener;\n    }\n\n    @Override\n    protected String getSideButtonTooltip() {\n        return I18n.get(\"sidebutton.refinedstorage.grid.size\") + \"\\n\" + ChatFormatting.GRAY + I18n.get(\"sidebutton.refinedstorage.grid.size.\" + this.sizeSupplier.get());\n    }\n\n    @Override\n    protected void renderButtonIcon(GuiGraphics graphics, int x, int y) {\n        int size = this.sizeSupplier.get();\n\n        int tx = 0;\n\n        if (size == IGrid.SIZE_STRETCH) {\n            tx = 48;\n        } else if (size == IGrid.SIZE_SMALL) {\n            tx = 0;\n        } else if (size == IGrid.SIZE_MEDIUM) {\n            tx = 16;\n        } else if (size == IGrid.SIZE_LARGE) {\n            tx = 32;\n        }\n\n        graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, 64 + tx, 64, 16, 16);\n    }\n\n    @Override\n    public void onPress() {\n        int size = this.sizeSupplier.get();\n\n        if (size == IGrid.SIZE_STRETCH) {\n            size = IGrid.SIZE_SMALL;\n        } else if (size == IGrid.SIZE_SMALL) {\n            size = IGrid.SIZE_MEDIUM;\n        } else if (size == IGrid.SIZE_MEDIUM) {\n            size = IGrid.SIZE_LARGE;\n        } else if (size == IGrid.SIZE_LARGE) {\n            size = IGrid.SIZE_STRETCH;\n        }\n\n        this.listener.accept(size);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/GridSortingDirectionSideButton.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget.sidebutton;\n\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\n\npublic class GridSortingDirectionSideButton extends SideButton {\n    private final IGrid grid;\n\n    public GridSortingDirectionSideButton(BaseScreen<GridContainerMenu> screen, IGrid grid) {\n        super(screen);\n\n        this.grid = grid;\n    }\n\n    @Override\n    protected String getSideButtonTooltip() {\n        return I18n.get(\"sidebutton.refinedstorage.grid.sorting.direction\") + \"\\n\" + ChatFormatting.GRAY + I18n.get(\"sidebutton.refinedstorage.grid.sorting.direction.\" + grid.getSortingDirection());\n    }\n\n    @Override\n    protected void renderButtonIcon(GuiGraphics graphics, int x, int y) {\n        graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, grid.getSortingDirection() * 16, 16, 16, 16);\n    }\n\n    @Override\n    public void onPress() {\n        int dir = grid.getSortingDirection();\n\n        if (dir == IGrid.SORTING_DIRECTION_ASCENDING) {\n            dir = IGrid.SORTING_DIRECTION_DESCENDING;\n        } else if (dir == IGrid.SORTING_DIRECTION_DESCENDING) {\n            dir = IGrid.SORTING_DIRECTION_ASCENDING;\n        }\n\n        grid.onSortingDirectionChanged(dir);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/GridSortingTypeSideButton.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget.sidebutton;\n\nimport com.refinedmods.refinedstorage.api.network.grid.GridType;\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\n\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\n\npublic class GridSortingTypeSideButton extends SideButton {\n    private final IGrid grid;\n\n    public GridSortingTypeSideButton(BaseScreen<GridContainerMenu> screen, IGrid grid) {\n        super(screen);\n\n        this.grid = grid;\n    }\n\n    @Override\n    protected String getSideButtonTooltip() {\n        return I18n.get(\"sidebutton.refinedstorage.grid.sorting.type\") + \"\\n\" + ChatFormatting.GRAY +\n            I18n.get(\"sidebutton.refinedstorage.grid.sorting.type.\" + grid.getSortingType());\n    }\n\n    @Override\n    protected void renderButtonIcon(GuiGraphics graphics, int x, int y) {\n        if (grid.getSortingType() == IGrid.SORTING_TYPE_LAST_MODIFIED) {\n            graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, 48, 48, 16, 16);\n        } else {\n            graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, grid.getSortingType() * 16, 32, 16, 16);\n        }\n    }\n\n    @Override\n    public void onPress() {\n        int type = grid.getSortingType();\n\n        if (type == IGrid.SORTING_TYPE_QUANTITY) {\n            type = IGrid.SORTING_TYPE_NAME;\n        } else if (type == IGrid.SORTING_TYPE_NAME) {\n            if (grid.getGridType() == GridType.FLUID) {\n                type = IGrid.SORTING_TYPE_LAST_MODIFIED;\n            } else {\n                type = IGrid.SORTING_TYPE_ID;\n            }\n        } else if (type == IGrid.SORTING_TYPE_ID) {\n            type = IGrid.SORTING_TYPE_LAST_MODIFIED;\n        } else if (type == IGrid.SORTING_TYPE_LAST_MODIFIED) {\n            type = IGrid.SORTING_TYPE_QUANTITY;\n        } else {\n            type = IGrid.SORTING_TYPE_QUANTITY;\n        }\n\n        grid.onSortingTypeChanged(type);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/GridViewTypeSideButton.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget.sidebutton;\n\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.container.GridContainerMenu;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\n\npublic class GridViewTypeSideButton extends SideButton {\n    private final IGrid grid;\n\n    public GridViewTypeSideButton(BaseScreen<GridContainerMenu> screen, IGrid grid) {\n        super(screen);\n\n        this.grid = grid;\n    }\n\n    @Override\n    protected String getSideButtonTooltip() {\n        return I18n.get(\"sidebutton.refinedstorage.grid.view_type\") + \"\\n\" + ChatFormatting.GRAY + I18n.get(\"sidebutton.refinedstorage.grid.view_type.\" + grid.getViewType());\n    }\n\n    @Override\n    protected void renderButtonIcon(GuiGraphics graphics, int x, int y) {\n        graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, (grid.getViewType() - (grid.getViewType() >= 3 ? 3 : 0)) * 16, 112, 16, 16);\n    }\n\n    @Override\n    public void onPress() {\n        int type = grid.getViewType();\n\n        if (type == IGrid.VIEW_TYPE_NORMAL) {\n            type = IGrid.VIEW_TYPE_NON_CRAFTABLES;\n        } else if (type == IGrid.VIEW_TYPE_NON_CRAFTABLES) {\n            type = IGrid.VIEW_TYPE_CRAFTABLES;\n        } else if (type == IGrid.VIEW_TYPE_CRAFTABLES) {\n            type = IGrid.VIEW_TYPE_NORMAL;\n        }\n\n        grid.onViewTypeChanged(type);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/IoModeSideButton.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget.sidebutton;\n\nimport com.refinedmods.refinedstorage.apiimpl.network.node.diskmanipulator.DiskManipulatorNetworkNode;\nimport com.refinedmods.refinedstorage.blockentity.DiskManipulatorBlockEntity;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport com.refinedmods.refinedstorage.container.DiskManipulatorContainerMenu;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\n\npublic class IoModeSideButton extends SideButton {\n    public IoModeSideButton(BaseScreen<DiskManipulatorContainerMenu> screen) {\n        super(screen);\n    }\n\n    @Override\n    protected String getSideButtonTooltip() {\n        return I18n.get(\"sidebutton.refinedstorage.iomode\") + \"\\n\" + ChatFormatting.GRAY + I18n.get(\"sidebutton.refinedstorage.iomode.\" + (DiskManipulatorBlockEntity.IO_MODE.getValue() == DiskManipulatorNetworkNode.IO_MODE_INSERT ? \"insert\" : \"extract\"));\n    }\n\n    @Override\n    protected void renderButtonIcon(GuiGraphics graphics, int x, int y) {\n        graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, DiskManipulatorBlockEntity.IO_MODE.getValue() == DiskManipulatorNetworkNode.IO_MODE_EXTRACT ? 0 : 16, 160, 16, 16);\n    }\n\n    @Override\n    public void onPress() {\n        BlockEntitySynchronizationManager.setParameter(DiskManipulatorBlockEntity.IO_MODE, DiskManipulatorBlockEntity.IO_MODE.getValue() == DiskManipulatorNetworkNode.IO_MODE_INSERT ? DiskManipulatorNetworkNode.IO_MODE_EXTRACT : DiskManipulatorNetworkNode.IO_MODE_INSERT);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/RedstoneModeSideButton.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget.sidebutton;\n\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\n\npublic class RedstoneModeSideButton extends SideButton {\n    private final BlockEntitySynchronizationParameter<Integer, ?> parameter;\n\n    public RedstoneModeSideButton(BaseScreen<?> screen, BlockEntitySynchronizationParameter<Integer, ?> parameter) {\n        super(screen);\n\n        this.parameter = parameter;\n    }\n\n    @Override\n    protected String getSideButtonTooltip() {\n        return I18n.get(\"sidebutton.refinedstorage.redstone_mode\") + \"\\n\" + ChatFormatting.GRAY + I18n.get(\"sidebutton.refinedstorage.redstone_mode.\" + parameter.getValue());\n    }\n\n    @Override\n    protected void renderButtonIcon(GuiGraphics graphics, int x, int y) {\n        graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, parameter.getValue() * 16, 0, 16, 16);\n    }\n\n    @Override\n    public void onPress() {\n        BlockEntitySynchronizationManager.setParameter(parameter, parameter.getValue() + 1);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/SearchBoxModeSideButton.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget.sidebutton;\n\nimport com.refinedmods.refinedstorage.api.network.grid.IGrid;\nimport com.refinedmods.refinedstorage.integration.jei.JeiIntegration;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\n\nimport java.util.Arrays;\nimport java.util.List;\n\npublic abstract class SearchBoxModeSideButton extends SideButton {\n    private static final List<Integer> MODE_ROTATION = Arrays.asList(\n        IGrid.SEARCH_BOX_MODE_NORMAL,\n        IGrid.SEARCH_BOX_MODE_NORMAL_AUTOSELECTED,\n        IGrid.SEARCH_BOX_MODE_JEI_SYNCHRONIZED,\n        IGrid.SEARCH_BOX_MODE_JEI_SYNCHRONIZED_AUTOSELECTED,\n        IGrid.SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY,\n        IGrid.SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY_AUTOSELECTED,\n        IGrid.SEARCH_BOX_MODE_NORMAL\n    );\n\n    protected SearchBoxModeSideButton(BaseScreen<?> screen) {\n        super(screen);\n    }\n\n    private static int nextMode(int oldMode) {\n        return MODE_ROTATION.get(MODE_ROTATION.indexOf(oldMode) + 1);\n    }\n\n    @Override\n    protected String getSideButtonTooltip() {\n        return I18n.get(\"sidebutton.refinedstorage.grid.search_box_mode\") + \"\\n\" + ChatFormatting.GRAY + I18n.get(\"sidebutton.refinedstorage.grid.search_box_mode.\" + getSearchBoxMode());\n    }\n\n    @Override\n    protected void renderButtonIcon(GuiGraphics graphics, int x, int y) {\n        int mode = getSearchBoxMode();\n\n        graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, IGrid.isSearchBoxModeWithAutoselection(mode) ? 16 : 0, 96, 16, 16);\n    }\n\n    @Override\n    public void onPress() {\n        int mode = nextMode(getSearchBoxMode());\n\n        if (IGrid.doesSearchBoxModeUseJEI(mode) && !JeiIntegration.isLoaded()) {\n            mode = IGrid.SEARCH_BOX_MODE_NORMAL;\n        }\n\n        setSearchBoxMode(mode);\n    }\n\n    protected abstract int getSearchBoxMode();\n\n    protected abstract void setSearchBoxMode(int mode);\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/SideButton.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget.sidebutton;\n\nimport com.mojang.blaze3d.systems.RenderSystem;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.util.RenderUtils;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.gui.components.Button;\nimport net.minecraft.network.chat.Component;\nimport org.lwjgl.opengl.GL11;\n\npublic abstract class SideButton extends Button {\n    private static final Button.OnPress NO_ACTION = btn -> {\n    };\n\n    private static final int WIDTH = 18;\n    private static final int HEIGHT = 18;\n\n    protected final BaseScreen<?> screen;\n\n    protected SideButton(BaseScreen<?> screen) {\n        super(Button.builder(Component.empty(), NO_ACTION).pos(-1, -1).size(WIDTH, HEIGHT));\n        this.screen = screen;\n    }\n\n    @Override\n    public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {\n        RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);\n\n        isHovered = RenderUtils.inBounds(getX(), getY(), width, height, mouseX, mouseY);\n\n        graphics.blit(BaseScreen.ICONS_TEXTURE, getX(), getY(), 238, isHovered ? 35 : 16, WIDTH, HEIGHT);\n\n        renderButtonIcon(graphics, getX() + 1, getY() + 1);\n\n        if (isHovered) {\n            RenderSystem.enableBlend();\n            RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);\n            RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 0.5f);\n            graphics.blit(BaseScreen.ICONS_TEXTURE, getX(), getY(), 238, 54, WIDTH, HEIGHT);\n            RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);\n            RenderSystem.disableBlend();\n            screen.renderTooltip(graphics, mouseX, mouseY, getSideButtonTooltip());\n        }\n    }\n\n    protected abstract void renderButtonIcon(GuiGraphics graphics, int x, int y);\n\n    protected abstract String getSideButtonTooltip();\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/TypeSideButton.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget.sidebutton;\n\nimport com.refinedmods.refinedstorage.blockentity.config.IType;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\n\npublic class TypeSideButton extends SideButton {\n    private final BlockEntitySynchronizationParameter<Integer, ?> type;\n\n    public TypeSideButton(BaseScreen<?> screen, BlockEntitySynchronizationParameter<Integer, ?> type) {\n        super(screen);\n\n        this.type = type;\n    }\n\n    @Override\n    protected String getSideButtonTooltip() {\n        return I18n.get(\"sidebutton.refinedstorage.type\") + \"\\n\" + ChatFormatting.GRAY + I18n.get(\"sidebutton.refinedstorage.type.\" + type.getValue());\n    }\n\n    @Override\n    protected void renderButtonIcon(GuiGraphics graphics, int x, int y) {\n        graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, 16 * type.getValue(), 128, 16, 16);\n    }\n\n    @Override\n    public void onPress() {\n        BlockEntitySynchronizationManager.setParameter(type, type.getValue() == IType.ITEMS ? IType.FLUIDS : IType.ITEMS);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/WhitelistBlacklistSideButton.java",
    "content": "package com.refinedmods.refinedstorage.screen.widget.sidebutton;\n\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.refinedmods.refinedstorage.screen.BaseScreen;\nimport com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager;\nimport com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter;\nimport net.minecraft.ChatFormatting;\nimport net.minecraft.client.gui.GuiGraphics;\nimport net.minecraft.client.resources.language.I18n;\n\npublic class WhitelistBlacklistSideButton extends SideButton {\n    private final BlockEntitySynchronizationParameter<Integer, ?> parameter;\n\n    public WhitelistBlacklistSideButton(BaseScreen<?> screen, BlockEntitySynchronizationParameter<Integer, ?> parameter) {\n        super(screen);\n\n        this.parameter = parameter;\n    }\n\n    @Override\n    protected String getSideButtonTooltip() {\n        return I18n.get(\"sidebutton.refinedstorage.mode\") + \"\\n\" + ChatFormatting.GRAY + I18n.get(\"sidebutton.refinedstorage.mode.\" + (parameter.getValue() == IWhitelistBlacklist.WHITELIST ? \"whitelist\" : \"blacklist\"));\n    }\n\n    @Override\n    protected void renderButtonIcon(GuiGraphics graphics, int x, int y) {\n        graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, parameter.getValue() == IWhitelistBlacklist.WHITELIST ? 0 : 16, 64, 16, 16);\n    }\n\n    @Override\n    public void onPress() {\n        BlockEntitySynchronizationManager.setParameter(parameter, parameter.getValue() == IWhitelistBlacklist.WHITELIST ? IWhitelistBlacklist.BLACKLIST : IWhitelistBlacklist.WHITELIST);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/setup/ClientSetup.java",
    "content": "package com.refinedmods.refinedstorage.setup;\n\nimport com.refinedmods.refinedstorage.*;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverType;\nimport com.refinedmods.refinedstorage.container.CrafterContainerMenu;\nimport com.refinedmods.refinedstorage.container.CrafterManagerContainerMenu;\nimport com.refinedmods.refinedstorage.container.slot.CrafterManagerSlot;\nimport com.refinedmods.refinedstorage.item.property.ControllerItemPropertyGetter;\nimport com.refinedmods.refinedstorage.item.property.NetworkItemPropertyGetter;\nimport com.refinedmods.refinedstorage.item.property.SecurityCardItemPropertyGetter;\nimport com.refinedmods.refinedstorage.render.BakedModelOverrideRegistry;\nimport com.refinedmods.refinedstorage.render.blockentity.StorageMonitorBlockEntityRenderer;\nimport com.refinedmods.refinedstorage.render.color.PatternItemColor;\nimport com.refinedmods.refinedstorage.render.model.DiskDriveGeometryLoader;\nimport com.refinedmods.refinedstorage.render.model.DiskManipulatorGeometryLoader;\nimport com.refinedmods.refinedstorage.render.model.PortableGridGeometryLoader;\nimport com.refinedmods.refinedstorage.render.model.baked.CableCoverBakedModel;\nimport com.refinedmods.refinedstorage.render.model.baked.CableCoverItemBakedModel;\nimport com.refinedmods.refinedstorage.render.model.baked.PatternBakedModel;\nimport com.refinedmods.refinedstorage.render.resourcepack.ResourcePackListener;\nimport com.refinedmods.refinedstorage.screen.*;\nimport com.refinedmods.refinedstorage.screen.factory.CrafterManagerScreenFactory;\nimport com.refinedmods.refinedstorage.screen.factory.GridScreenFactory;\nimport com.refinedmods.refinedstorage.util.ColorMap;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.screens.MenuScreens;\nimport net.minecraft.client.gui.screens.Screen;\nimport net.minecraft.client.renderer.blockentity.BlockEntityRenderers;\nimport net.minecraft.client.renderer.item.ItemProperties;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.world.inventory.AbstractContainerMenu;\nimport net.minecraft.world.inventory.Slot;\nimport net.minecraft.world.item.DyeColor;\nimport net.minecraft.world.item.ItemStack;\nimport net.neoforged.bus.api.SubscribeEvent;\nimport net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;\nimport net.neoforged.neoforge.client.event.ModelEvent;\nimport net.neoforged.neoforge.client.event.RegisterColorHandlersEvent;\nimport net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent;\nimport net.neoforged.neoforge.client.event.RegisterMenuScreensEvent;\nimport net.neoforged.neoforge.common.NeoForge;\nimport net.neoforged.neoforge.event.AddReloadListenerEvent;\nimport java.util.Arrays;\nimport java.util.function.BiConsumer;\n\npublic final class ClientSetup {\n    private static final ResourceLocation DISK_RESOURCE = new ResourceLocation(RS.ID + \":block/disks/disk\");\n    private static final ResourceLocation DISK_NEAR_CAPACITY_RESOURCE = new ResourceLocation(RS.ID + \":block/disks/disk_near_capacity\");\n    private static final ResourceLocation DISK_FULL_RESOURCE = new ResourceLocation(RS.ID + \":block/disks/disk_full\");\n    private static final ResourceLocation DISK_DISCONNECTED_RESOURCE = new ResourceLocation(RS.ID + \":block/disks/disk_disconnected\");\n\n    private static final ResourceLocation CONNECTED = new ResourceLocation(RS.ID, \"connected\");\n\n    private static final BakedModelOverrideRegistry BAKED_MODEL_OVERRIDE_REGISTRY = new BakedModelOverrideRegistry();\n\n    private ClientSetup() {\n    }\n\n    @SubscribeEvent\n    public static void onClientSetup(FMLClientSetupEvent e) {\n        NeoForge.EVENT_BUS.register(new KeyInputListener());\n\n        registerBakedModelOverrides();\n        registerPatternRenderHandlers();\n\n        BlockEntityRenderers.register(RSBlockEntities.STORAGE_MONITOR.get(), ctx -> new StorageMonitorBlockEntityRenderer());\n\n        // ItemProperties isn't thread safe\n        e.enqueueWork(() -> {\n            ItemProperties.register(RSItems.SECURITY_CARD.get(), new ResourceLocation(RS.ID, \"active\"), new SecurityCardItemPropertyGetter());\n\n            RSItems.CONTROLLER.values().forEach(controller -> ItemProperties.register(controller.get(), new ResourceLocation(RS.ID, \"energy_type\"), new ControllerItemPropertyGetter()));\n            RSItems.CREATIVE_CONTROLLER.values().forEach(controller -> ItemProperties.register(controller.get(), new ResourceLocation(RS.ID, \"energy_type\"), new ControllerItemPropertyGetter()));\n\n            ItemProperties.register(RSItems.WIRELESS_CRAFTING_MONITOR.get(), CONNECTED, new NetworkItemPropertyGetter());\n            ItemProperties.register(RSItems.CREATIVE_WIRELESS_CRAFTING_MONITOR.get(), CONNECTED, new NetworkItemPropertyGetter());\n\n            ItemProperties.register(RSItems.WIRELESS_GRID.get(), CONNECTED, new NetworkItemPropertyGetter());\n            ItemProperties.register(RSItems.CREATIVE_WIRELESS_GRID.get(), CONNECTED, new NetworkItemPropertyGetter());\n\n            ItemProperties.register(RSItems.WIRELESS_FLUID_GRID.get(), CONNECTED, new NetworkItemPropertyGetter());\n            ItemProperties.register(RSItems.CREATIVE_WIRELESS_FLUID_GRID.get(), CONNECTED, new NetworkItemPropertyGetter());\n        });\n    }\n\n    @SubscribeEvent\n    public static void registerMenuScreens(RegisterMenuScreensEvent e) {\n        e.register(RSContainerMenus.FILTER.get(), FilterScreen::new);\n        e.register(RSContainerMenus.CONTROLLER.get(), ControllerScreen::new);\n        e.register(RSContainerMenus.DISK_DRIVE.get(), DiskDriveScreen::new);\n        e.register(RSContainerMenus.GRID.get(), new GridScreenFactory());\n        e.register(RSContainerMenus.STORAGE_BLOCK.get(), StorageBlockScreen::new);\n        e.register(RSContainerMenus.FLUID_STORAGE_BLOCK.get(), FluidStorageBlockScreen::new);\n        e.register(RSContainerMenus.EXTERNAL_STORAGE.get(), ExternalStorageScreen::new);\n        e.register(RSContainerMenus.IMPORTER.get(), ImporterScreen::new);\n        e.register(RSContainerMenus.EXPORTER.get(), ExporterScreen::new);\n        e.register(RSContainerMenus.NETWORK_TRANSMITTER.get(), NetworkTransmitterScreen::new);\n        e.register(RSContainerMenus.RELAY.get(), RelayScreen::new);\n        e.register(RSContainerMenus.DETECTOR.get(), DetectorScreen::new);\n        e.register(RSContainerMenus.SECURITY_MANAGER.get(), SecurityManagerScreen::new);\n        e.register(RSContainerMenus.INTERFACE.get(), InterfaceScreen::new);\n        e.register(RSContainerMenus.FLUID_INTERFACE.get(), FluidInterfaceScreen::new);\n        e.register(RSContainerMenus.WIRELESS_TRANSMITTER.get(), WirelessTransmitterScreen::new);\n        e.register(RSContainerMenus.STORAGE_MONITOR.get(), StorageMonitorScreen::new);\n        e.register(RSContainerMenus.CONSTRUCTOR.get(), ConstructorScreen::new);\n        e.register(RSContainerMenus.DESTRUCTOR.get(), DestructorScreen::new);\n        e.register(RSContainerMenus.DISK_MANIPULATOR.get(), DiskManipulatorScreen::new);\n        e.register(RSContainerMenus.CRAFTER.get(), CrafterScreen::new);\n        e.register(RSContainerMenus.CRAFTER_MANAGER.get(), new CrafterManagerScreenFactory());\n        e.register(RSContainerMenus.CRAFTING_MONITOR.get(), CraftingMonitorScreen::new);\n        e.register(RSContainerMenus.WIRELESS_CRAFTING_MONITOR.get(), CraftingMonitorScreen::new);\n    }\n\n    private static void registerPatternRenderHandlers() {\n        API.instance().addPatternRenderHandler(pattern -> Screen.hasShiftDown());\n        API.instance().addPatternRenderHandler(pattern -> {\n            AbstractContainerMenu container = Minecraft.getInstance().player.containerMenu;\n\n            if (container instanceof CrafterManagerContainerMenu) {\n                for (Slot slot : container.slots) {\n                    if (slot instanceof CrafterManagerSlot && slot.getItem() == pattern) {\n                        return true;\n                    }\n                }\n            }\n\n            return false;\n        });\n        API.instance().addPatternRenderHandler(pattern -> {\n            AbstractContainerMenu container = Minecraft.getInstance().player.containerMenu;\n\n            if (container instanceof CrafterContainerMenu) {\n                for (int i = 0; i < 9; ++i) {\n                    if (container.getSlot(i).getItem() == pattern) {\n                        return true;\n                    }\n                }\n            }\n\n            return false;\n        });\n    }\n\n    private static void registerBakedModelOverrides() {\n        BAKED_MODEL_OVERRIDE_REGISTRY.add(new ResourceLocation(RS.ID, \"cable\"), (base, registry) -> new CableCoverBakedModel(base));\n        BAKED_MODEL_OVERRIDE_REGISTRY.add(new ResourceLocation(RS.ID, \"exporter\"), (base, registry) -> new CableCoverBakedModel(base));\n        BAKED_MODEL_OVERRIDE_REGISTRY.add(new ResourceLocation(RS.ID, \"importer\"), (base, registry) -> new CableCoverBakedModel(base));\n        BAKED_MODEL_OVERRIDE_REGISTRY.add(new ResourceLocation(RS.ID, \"external_storage\"), (base, registry) -> new CableCoverBakedModel(base));\n        BAKED_MODEL_OVERRIDE_REGISTRY.add(new ResourceLocation(RS.ID, \"cover\"), (base, registry) -> new CableCoverItemBakedModel(ItemStack.EMPTY, CoverType.NORMAL));\n        BAKED_MODEL_OVERRIDE_REGISTRY.add(new ResourceLocation(RS.ID, \"hollow_cover\"), (base, registry) -> new CableCoverItemBakedModel(ItemStack.EMPTY, CoverType.HOLLOW));\n        BAKED_MODEL_OVERRIDE_REGISTRY.add(new ResourceLocation(RS.ID, \"pattern\"), (base, registry) -> new PatternBakedModel(base));\n    }\n\n    @SubscribeEvent\n    public static void onRegisterColorBindings(RegisterColorHandlersEvent.Item e) {\n        e.register(new PatternItemColor(), RSItems.PATTERN.get());\n    }\n\n    @SubscribeEvent\n    public static void onRegisterKeymappings(RegisterKeyMappingsEvent e) {\n        e.register(RSKeyBindings.FOCUS_SEARCH_BAR);\n        e.register(RSKeyBindings.CLEAR_GRID_CRAFTING_MATRIX);\n        e.register(RSKeyBindings.OPEN_WIRELESS_GRID);\n        e.register(RSKeyBindings.OPEN_WIRELESS_FLUID_GRID);\n        e.register(RSKeyBindings.OPEN_WIRELESS_CRAFTING_MONITOR);\n        e.register(RSKeyBindings.OPEN_PORTABLE_GRID);\n    }\n\n    @SubscribeEvent\n    public static void addReloadListener(AddReloadListenerEvent event) {\n        event.addListener(new ResourcePackListener());\n    }\n\n    @SubscribeEvent\n    public static void onRegisterAdditionalModels(ModelEvent.RegisterAdditional e) {\n        e.register(DISK_RESOURCE);\n        e.register(DISK_NEAR_CAPACITY_RESOURCE);\n        e.register(DISK_FULL_RESOURCE);\n        e.register(DISK_DISCONNECTED_RESOURCE);\n\n        e.register(new ResourceLocation(RS.ID + \":block/disk_manipulator/disconnected\"));\n\n        for (DyeColor color : DyeColor.values()) {\n            e.register(new ResourceLocation(RS.ID + \":block/disk_manipulator/\" + color));\n        }\n\n    }\n\n    @SubscribeEvent\n    public static void onModelBake(ModelEvent.ModifyBakingResult e) {\n        for (ResourceLocation id : e.getModels().keySet()) {\n            BakedModelOverrideRegistry.BakedModelOverrideFactory factory = BAKED_MODEL_OVERRIDE_REGISTRY.get(new ResourceLocation(id.getNamespace(), id.getPath()));\n\n            if (factory != null) {\n                e.getModels().put(id, factory.create(e.getModels().get(id), e.getModels()));\n            }\n        }\n    }\n\n    @SubscribeEvent\n    public static void onRegisterModelGeometry(final ModelEvent.RegisterGeometryLoaders e) {\n        e.register(new ResourceLocation(RS.ID, \"disk_drive\"), new DiskDriveGeometryLoader());\n        e.register(new ResourceLocation(RS.ID, \"disk_manipulator\"), new DiskManipulatorGeometryLoader());\n        e.register(new ResourceLocation(RS.ID, \"portable_grid\"), new PortableGridGeometryLoader());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/setup/CommonSetup.java",
    "content": "package com.refinedmods.refinedstorage.setup;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlockEntities;\nimport com.refinedmods.refinedstorage.RSCreativeModeTabItems;\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.RSLootFunctions;\nimport com.refinedmods.refinedstorage.api.network.grid.GridType;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport com.refinedmods.refinedstorage.api.storage.StorageType;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor.ErrorCraftingMonitorElement;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor.FluidCraftingMonitorElement;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor.ItemCraftingMonitorElement;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.ErrorCraftingPreviewElement;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.FluidCraftingPreviewElement;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.ItemCraftingPreviewElement;\nimport com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.CraftingTaskFactory;\nimport com.refinedmods.refinedstorage.apiimpl.network.NetworkListener;\nimport com.refinedmods.refinedstorage.apiimpl.network.NetworkNodeListener;\nimport com.refinedmods.refinedstorage.apiimpl.network.grid.factory.GridBlockGridFactory;\nimport com.refinedmods.refinedstorage.apiimpl.network.grid.factory.PortableGridBlockGridFactory;\nimport com.refinedmods.refinedstorage.apiimpl.network.grid.factory.PortableGridGridFactory;\nimport com.refinedmods.refinedstorage.apiimpl.network.grid.factory.WirelessFluidGridGridFactory;\nimport com.refinedmods.refinedstorage.apiimpl.network.grid.factory.WirelessGridGridFactory;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.CableNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.ConstructorNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.CrafterManagerNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.CrafterNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.CraftingMonitorNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.DestructorNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.DetectorNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.ExporterNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.ExternalStorageNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.FluidInterfaceNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.ImporterNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.InterfaceNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.NetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.NetworkReceiverNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.NetworkTransmitterNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.RelayNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.SecurityManagerNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.StorageMonitorNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.WirelessTransmitterNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.diskdrive.DiskDriveNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.diskmanipulator.DiskManipulatorNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.storage.FluidStorageNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.network.node.storage.StorageNetworkNode;\nimport com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType;\nimport com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType;\nimport com.refinedmods.refinedstorage.apiimpl.storage.disk.factory.FluidStorageDiskFactory;\nimport com.refinedmods.refinedstorage.apiimpl.storage.disk.factory.ItemStorageDiskFactory;\nimport com.refinedmods.refinedstorage.apiimpl.storage.externalstorage.FluidExternalStorageProvider;\nimport com.refinedmods.refinedstorage.apiimpl.storage.externalstorage.ItemExternalStorageProvider;\nimport com.refinedmods.refinedstorage.block.BlockListener;\nimport com.refinedmods.refinedstorage.blockentity.CrafterBlockEntity;\nimport com.refinedmods.refinedstorage.integration.craftingtweaks.CraftingTweaksIntegration;\nimport com.refinedmods.refinedstorage.integration.inventorysorter.InventorySorterIntegration;\n\nimport net.minecraft.core.registries.Registries;\nimport net.minecraft.nbt.CompoundTag;\nimport net.neoforged.bus.api.SubscribeEvent;\nimport net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;\nimport net.neoforged.neoforge.capabilities.Capabilities;\nimport net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent;\nimport net.neoforged.neoforge.common.NeoForge;\nimport net.neoforged.neoforge.network.event.RegisterPayloadHandlerEvent;\nimport net.neoforged.neoforge.network.registration.IPayloadRegistrar;\nimport net.neoforged.neoforge.registries.RegisterEvent;\n\npublic final class CommonSetup {\n    private CommonSetup() {\n    }\n\n    @SubscribeEvent\n    public static void onRegister(final RegisterEvent e) {\n        e.register(Registries.LOOT_FUNCTION_TYPE, helper -> RSLootFunctions.register());\n        e.register(Registries.CREATIVE_MODE_TAB, RSCreativeModeTabItems::register);\n    }\n\n    @SubscribeEvent\n    public static void onCommonSetup(FMLCommonSetupEvent e) {\n        NeoForge.EVENT_BUS.register(new NetworkNodeListener());\n        NeoForge.EVENT_BUS.register(new NetworkListener());\n        NeoForge.EVENT_BUS.register(new BlockListener());\n\n        API.instance().getStorageDiskRegistry().add(ItemStorageDiskFactory.ID, new ItemStorageDiskFactory());\n        API.instance().getStorageDiskRegistry().add(FluidStorageDiskFactory.ID, new FluidStorageDiskFactory());\n\n        API.instance().getNetworkNodeRegistry().add(DiskDriveNetworkNode.ID,\n            (tag, world, pos) -> readAndReturn(tag, new DiskDriveNetworkNode(world, pos)));\n        API.instance().getNetworkNodeRegistry()\n            .add(CableNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new CableNetworkNode(world, pos)));\n        API.instance().getNetworkNodeRegistry().add(GridNetworkNode.ID,\n            (tag, world, pos) -> readAndReturn(tag, new GridNetworkNode(world, pos, GridType.NORMAL)));\n        API.instance().getNetworkNodeRegistry().add(GridNetworkNode.CRAFTING_ID,\n            (tag, world, pos) -> readAndReturn(tag, new GridNetworkNode(world, pos, GridType.CRAFTING)));\n        API.instance().getNetworkNodeRegistry().add(GridNetworkNode.PATTERN_ID,\n            (tag, world, pos) -> readAndReturn(tag, new GridNetworkNode(world, pos, GridType.PATTERN)));\n        API.instance().getNetworkNodeRegistry().add(GridNetworkNode.FLUID_ID,\n            (tag, world, pos) -> readAndReturn(tag, new GridNetworkNode(world, pos, GridType.FLUID)));\n\n        API.instance().getNetworkNodeRegistry().add(StorageNetworkNode.ONE_K_STORAGE_BLOCK_ID,\n            (tag, world, pos) -> readAndReturn(tag, new StorageNetworkNode(world, pos, ItemStorageType.ONE_K)));\n        API.instance().getNetworkNodeRegistry().add(StorageNetworkNode.FOUR_K_STORAGE_BLOCK_ID,\n            (tag, world, pos) -> readAndReturn(tag, new StorageNetworkNode(world, pos, ItemStorageType.FOUR_K)));\n        API.instance().getNetworkNodeRegistry().add(StorageNetworkNode.SIXTEEN_K_STORAGE_BLOCK_ID,\n            (tag, world, pos) -> readAndReturn(tag, new StorageNetworkNode(world, pos, ItemStorageType.SIXTEEN_K)));\n        API.instance().getNetworkNodeRegistry().add(StorageNetworkNode.SIXTY_FOUR_K_STORAGE_BLOCK_ID,\n            (tag, world, pos) -> readAndReturn(tag, new StorageNetworkNode(world, pos, ItemStorageType.SIXTY_FOUR_K)));\n        API.instance().getNetworkNodeRegistry().add(StorageNetworkNode.CREATIVE_STORAGE_BLOCK_ID,\n            (tag, world, pos) -> readAndReturn(tag, new StorageNetworkNode(world, pos, ItemStorageType.CREATIVE)));\n\n        API.instance().getNetworkNodeRegistry().add(FluidStorageNetworkNode.SIXTY_FOUR_K_FLUID_STORAGE_BLOCK_ID,\n            (tag, world, pos) -> readAndReturn(tag,\n                new FluidStorageNetworkNode(world, pos, FluidStorageType.SIXTY_FOUR_K)));\n        API.instance().getNetworkNodeRegistry()\n            .add(FluidStorageNetworkNode.TWO_HUNDRED_FIFTY_SIX_K_FLUID_STORAGE_BLOCK_ID,\n                (tag, world, pos) -> readAndReturn(tag,\n                    new FluidStorageNetworkNode(world, pos, FluidStorageType.TWO_HUNDRED_FIFTY_SIX_K)));\n        API.instance().getNetworkNodeRegistry()\n            .add(FluidStorageNetworkNode.THOUSAND_TWENTY_FOUR_K_FLUID_STORAGE_BLOCK_ID,\n                (tag, world, pos) -> readAndReturn(tag,\n                    new FluidStorageNetworkNode(world, pos, FluidStorageType.THOUSAND_TWENTY_FOUR_K)));\n        API.instance().getNetworkNodeRegistry()\n            .add(FluidStorageNetworkNode.FOUR_THOUSAND_NINETY_SIX_K_FLUID_STORAGE_BLOCK_ID,\n                (tag, world, pos) -> readAndReturn(tag,\n                    new FluidStorageNetworkNode(world, pos, FluidStorageType.FOUR_THOUSAND_NINETY_SIX_K)));\n        API.instance().getNetworkNodeRegistry().add(FluidStorageNetworkNode.CREATIVE_FLUID_STORAGE_BLOCK_ID,\n            (tag, world, pos) -> readAndReturn(tag,\n                new FluidStorageNetworkNode(world, pos, FluidStorageType.CREATIVE)));\n\n        API.instance().getNetworkNodeRegistry().add(ExternalStorageNetworkNode.ID,\n            (tag, world, pos) -> readAndReturn(tag, new ExternalStorageNetworkNode(world, pos)));\n        API.instance().getNetworkNodeRegistry()\n            .add(ImporterNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new ImporterNetworkNode(world, pos)));\n        API.instance().getNetworkNodeRegistry()\n            .add(ExporterNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new ExporterNetworkNode(world, pos)));\n        API.instance().getNetworkNodeRegistry().add(NetworkReceiverNetworkNode.ID,\n            (tag, world, pos) -> readAndReturn(tag, new NetworkReceiverNetworkNode(world, pos)));\n        API.instance().getNetworkNodeRegistry().add(NetworkTransmitterNetworkNode.ID,\n            (tag, world, pos) -> readAndReturn(tag, new NetworkTransmitterNetworkNode(world, pos)));\n        API.instance().getNetworkNodeRegistry()\n            .add(RelayNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new RelayNetworkNode(world, pos)));\n        API.instance().getNetworkNodeRegistry()\n            .add(DetectorNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new DetectorNetworkNode(world, pos)));\n        API.instance().getNetworkNodeRegistry().add(SecurityManagerNetworkNode.ID,\n            (tag, world, pos) -> readAndReturn(tag, new SecurityManagerNetworkNode(world, pos)));\n        API.instance().getNetworkNodeRegistry().add(InterfaceNetworkNode.ID,\n            (tag, world, pos) -> readAndReturn(tag, new InterfaceNetworkNode(world, pos)));\n        API.instance().getNetworkNodeRegistry().add(FluidInterfaceNetworkNode.ID,\n            (tag, world, pos) -> readAndReturn(tag, new FluidInterfaceNetworkNode(world, pos)));\n        API.instance().getNetworkNodeRegistry().add(WirelessTransmitterNetworkNode.ID,\n            (tag, world, pos) -> readAndReturn(tag, new WirelessTransmitterNetworkNode(world, pos)));\n        API.instance().getNetworkNodeRegistry().add(StorageMonitorNetworkNode.ID,\n            (tag, world, pos) -> readAndReturn(tag, new StorageMonitorNetworkNode(world, pos)));\n        API.instance().getNetworkNodeRegistry().add(ConstructorNetworkNode.ID,\n            (tag, world, pos) -> readAndReturn(tag, new ConstructorNetworkNode(world, pos)));\n        API.instance().getNetworkNodeRegistry().add(DestructorNetworkNode.ID,\n            (tag, world, pos) -> readAndReturn(tag, new DestructorNetworkNode(world, pos)));\n        API.instance().getNetworkNodeRegistry().add(DiskManipulatorNetworkNode.ID,\n            (tag, world, pos) -> readAndReturn(tag, new DiskManipulatorNetworkNode(world, pos)));\n        API.instance().getNetworkNodeRegistry()\n            .add(CrafterNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new CrafterNetworkNode(world, pos)));\n        API.instance().getNetworkNodeRegistry().add(CrafterManagerNetworkNode.ID,\n            (tag, world, pos) -> readAndReturn(tag, new CrafterManagerNetworkNode(world, pos)));\n        API.instance().getNetworkNodeRegistry().add(CraftingMonitorNetworkNode.ID,\n            (tag, world, pos) -> readAndReturn(tag, new CraftingMonitorNetworkNode(world, pos)));\n\n        API.instance().getGridManager().add(GridBlockGridFactory.ID, new GridBlockGridFactory());\n        API.instance().getGridManager().add(WirelessGridGridFactory.ID, new WirelessGridGridFactory());\n        API.instance().getGridManager().add(WirelessFluidGridGridFactory.ID, new WirelessFluidGridGridFactory());\n        API.instance().getGridManager().add(PortableGridGridFactory.ID, new PortableGridGridFactory());\n        API.instance().getGridManager().add(PortableGridBlockGridFactory.ID, new PortableGridBlockGridFactory());\n\n        API.instance().addExternalStorageProvider(StorageType.ITEM, new ItemExternalStorageProvider());\n        API.instance().addExternalStorageProvider(StorageType.FLUID, new FluidExternalStorageProvider());\n\n        API.instance().getCraftingPreviewElementRegistry()\n            .add(ItemCraftingPreviewElement.ID, ItemCraftingPreviewElement::read);\n        API.instance().getCraftingPreviewElementRegistry()\n            .add(FluidCraftingPreviewElement.ID, FluidCraftingPreviewElement::read);\n        API.instance().getCraftingPreviewElementRegistry()\n            .add(ErrorCraftingPreviewElement.ID, ErrorCraftingPreviewElement::read);\n\n        API.instance().getCraftingMonitorElementRegistry()\n            .add(ItemCraftingMonitorElement.ID, ItemCraftingMonitorElement::read);\n        API.instance().getCraftingMonitorElementRegistry()\n            .add(FluidCraftingMonitorElement.ID, FluidCraftingMonitorElement::read);\n        API.instance().getCraftingMonitorElementRegistry()\n            .add(ErrorCraftingMonitorElement.ID, ErrorCraftingMonitorElement::read);\n\n        API.instance().getCraftingTaskRegistry().add(CraftingTaskFactory.ID, new CraftingTaskFactory());\n\n        if (CraftingTweaksIntegration.isLoaded()) {\n            CraftingTweaksIntegration.register();\n        }\n\n        if (InventorySorterIntegration.isLoaded()) {\n            InventorySorterIntegration.register();\n        }\n    }\n\n    private static INetworkNode readAndReturn(CompoundTag tag, NetworkNode node) {\n        node.read(tag);\n\n        return node;\n    }\n\n    @SubscribeEvent\n    public static void onRegisterNetworkPackets(final RegisterPayloadHandlerEvent event) {\n        final IPayloadRegistrar registrar = event.registrar(RS.ID);\n        RS.NETWORK_HANDLER.register(registrar);\n    }\n\n    @SubscribeEvent\n    public static void onRegisterCapabilities(final RegisterCapabilitiesEvent e) {\n        e.registerBlockEntity(\n            Capabilities.ItemHandler.BLOCK,\n            RSBlockEntities.CRAFTER.get(),\n            CrafterBlockEntity::getPatterns\n        );\n        e.registerBlockEntity(\n            Capabilities.ItemHandler.BLOCK,\n            RSBlockEntities.DISK_MANIPULATOR.get(),\n            (be, side) -> be.getNode().getDisks()\n        );\n        e.registerBlockEntity(\n            Capabilities.ItemHandler.BLOCK,\n            RSBlockEntities.FLUID_INTERFACE.get(),\n            (be, side) -> be.getNode().getIn()\n        );\n        e.registerBlockEntity(\n            Capabilities.FluidHandler.BLOCK,\n            RSBlockEntities.FLUID_INTERFACE.get(),\n            (be, side) -> be.getNode().getTank()\n        );\n        e.registerBlockEntity(\n            Capabilities.ItemHandler.BLOCK,\n            RSBlockEntities.INTERFACE.get(),\n            (be, side) -> be.getNode().getItems()\n        );\n        e.registerBlockEntity(\n            Capabilities.ItemHandler.BLOCK,\n            RSBlockEntities.DISK_DRIVE.get(),\n            (be, side) -> be.getNode().getDisks()\n        );\n        e.registerBlockEntity(\n            Capabilities.ItemHandler.BLOCK,\n            RSBlockEntities.NETWORK_TRANSMITTER.get(),\n            (be, side) -> be.getNode().getNetworkCard()\n        );\n        e.registerBlockEntity(\n            Capabilities.EnergyStorage.BLOCK,\n            RSBlockEntities.CONTROLLER.get(),\n            (be, side) -> be.getNetwork().getEnergyStorage()\n        );\n        e.registerBlockEntity(\n            Capabilities.ItemHandler.BLOCK,\n            RSBlockEntities.GRID.get(),\n            (be, side) -> be.getInventory()\n        );\n        e.registerBlockEntity(\n            Capabilities.EnergyStorage.BLOCK,\n            RSBlockEntities.PORTABLE_GRID.get(),\n            (be, side) -> be.getEnergyStorage()\n        );\n        RSItems.CONTROLLER.values().forEach(value -> e.registerItem(\n            Capabilities.EnergyStorage.ITEM,\n            (stack, ctx) -> value.get().createEnergyStorage(stack),\n            value.get()\n        ));\n        e.registerItem(\n            Capabilities.EnergyStorage.ITEM,\n            (stack, ctx) -> RSItems.PORTABLE_GRID.get().createEnergyStorage(stack),\n            RSItems.PORTABLE_GRID.get()\n        );\n        e.registerItem(\n            Capabilities.EnergyStorage.ITEM,\n            (stack, ctx) -> RSItems.WIRELESS_GRID.get().createEnergyStorage(stack),\n            RSItems.WIRELESS_GRID.get()\n        );\n        e.registerItem(\n            Capabilities.EnergyStorage.ITEM,\n            (stack, ctx) -> RSItems.WIRELESS_FLUID_GRID.get().createEnergyStorage(stack),\n            RSItems.WIRELESS_FLUID_GRID.get()\n        );\n        e.registerItem(\n            Capabilities.EnergyStorage.ITEM,\n            (stack, ctx) -> RSItems.WIRELESS_CRAFTING_MONITOR.get().createEnergyStorage(stack),\n            RSItems.WIRELESS_CRAFTING_MONITOR.get()\n        );\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/setup/ServerSetup.java",
    "content": "package com.refinedmods.refinedstorage.setup;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.command.disk.CreateDiskCommand;\nimport com.refinedmods.refinedstorage.command.disk.ListDiskCommand;\nimport com.refinedmods.refinedstorage.command.network.GetNetworkCommand;\nimport com.refinedmods.refinedstorage.command.network.ListNetworkCommand;\nimport com.refinedmods.refinedstorage.command.pattern.PatternDumpCommand;\nimport net.minecraft.commands.Commands;\nimport net.neoforged.bus.api.SubscribeEvent;\nimport net.neoforged.neoforge.event.RegisterCommandsEvent;\n\npublic class ServerSetup {\n    @SubscribeEvent\n    public void onRegisterCommands(RegisterCommandsEvent e) {\n        e.getDispatcher().register(Commands.literal(RS.ID)\n            .then(Commands.literal(\"pattern\")\n                .then(PatternDumpCommand.register()))\n            .then(Commands.literal(\"disk\")\n                .then(CreateDiskCommand.register())\n                .then(ListDiskCommand.register()))\n            .then(Commands.literal(\"network\")\n                .then(GetNetworkCommand.register())\n                .then(ListNetworkCommand.register())));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/util/AccessTypeUtils.java",
    "content": "package com.refinedmods.refinedstorage.util;\n\nimport com.refinedmods.refinedstorage.api.storage.AccessType;\nimport net.minecraft.nbt.CompoundTag;\n\npublic final class AccessTypeUtils {\n    private static final String NBT_ACCESS_TYPE = \"AccessType\";\n\n    private AccessTypeUtils() {\n    }\n\n    public static void writeAccessType(CompoundTag tag, AccessType type) {\n        tag.putInt(NBT_ACCESS_TYPE, type.getId());\n    }\n\n    public static AccessType readAccessType(CompoundTag tag) {\n        return tag.contains(NBT_ACCESS_TYPE) ? getAccessType(tag.getInt(NBT_ACCESS_TYPE)) : AccessType.INSERT_EXTRACT;\n    }\n\n    public static AccessType getAccessType(int id) {\n        for (AccessType type : AccessType.values()) {\n            if (type.getId() == id) {\n                return type;\n            }\n        }\n\n        return AccessType.INSERT_EXTRACT;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/util/BlockColorMap.java",
    "content": "package com.refinedmods.refinedstorage.util;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSBlocks;\nimport com.refinedmods.refinedstorage.block.BaseBlock;\nimport com.refinedmods.refinedstorage.block.BlockDirection;\nimport com.refinedmods.refinedstorage.block.NetworkNodeBlock;\n\nimport java.util.List;\nimport java.util.function.Supplier;\n\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.tags.BlockTags;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.DyeColor;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.GameType;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.Block;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.registries.DeferredHolder;\nimport net.neoforged.neoforge.registries.DeferredRegister;\n\npublic class BlockColorMap<T extends Block> extends ColorMap<Block, T> {\n    public BlockColorMap(DeferredRegister<Block> registry) {\n        super(registry);\n    }\n\n    public BlockColorMap(DeferredRegister<Block> registry, List<Runnable> lateRegistration) {\n        super(registry, lateRegistration);\n    }\n\n    public Block[] getBlocks() {\n        return map.values().stream().map(DeferredHolder::get).toArray(Block[]::new);\n    }\n\n    public void registerBlocks(String name, Supplier<T> blockFactory) {\n        for (DyeColor color : DyeColor.values()) {\n            String prefix = color != DEFAULT_COLOR ? color + \"_\" : \"\";\n            DeferredHolder<Block, T> block = registry.register(prefix + name, blockFactory);\n            map.put(color, block);\n            RSBlocks.COLORED_BLOCKS.add(block);\n        }\n        RSBlocks.COLORED_BLOCK_TAGS.put(\n            BlockTags.create(new ResourceLocation(RS.ID, get(DEFAULT_COLOR).getId().getPath())),\n            this\n        );\n    }\n\n    public <S extends BaseBlock> InteractionResult changeBlockColor(BlockState state, ItemStack heldItem, Level level,\n                                                                    BlockPos pos, Player player) {\n        DyeColor color = DyeColor.getColor(heldItem);\n        if (color == null || state.getBlock().equals(map.get(color).get())) {\n            return InteractionResult.PASS;\n        }\n\n        return setBlockState(getNewState((DeferredHolder<Block, S>) map.get(color), state), heldItem, level, pos,\n            player);\n    }\n\n    private <S extends BaseBlock> BlockState getNewState(DeferredHolder<Block, S> block, BlockState state) {\n        BlockState newState = block.get().defaultBlockState();\n\n        if (((NetworkNodeBlock) block.get()).hasConnectedState()) {\n            newState = newState.setValue(NetworkNodeBlock.CONNECTED, state.getValue(NetworkNodeBlock.CONNECTED));\n        }\n        if (block.get().getDirection() != BlockDirection.NONE) {\n            newState = newState.setValue(block.get().getDirection().getProperty(),\n                state.getValue(block.get().getDirection().getProperty()));\n        }\n\n        return newState;\n    }\n\n    public InteractionResult setBlockState(BlockState newState, ItemStack heldItem, Level level, BlockPos pos,\n                                           Player player) {\n        if (!level.isClientSide) {\n            level.setBlockAndUpdate(pos, newState);\n            if (((ServerPlayer) player).gameMode.getGameModeForPlayer() != GameType.CREATIVE) {\n                heldItem.shrink(1);\n            }\n        }\n\n        return InteractionResult.SUCCESS;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/util/BlockUtils.java",
    "content": "package com.refinedmods.refinedstorage.util;\n\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.world.level.block.Block;\nimport net.minecraft.world.level.block.SoundType;\nimport net.minecraft.world.level.block.state.BlockBehaviour;\n\npublic final class BlockUtils {\n    public static final BlockBehaviour.Properties DEFAULT_ROCK_PROPERTIES = BlockBehaviour.Properties.of().strength(0.5F, 6.0F).sound(SoundType.STONE);\n    public static final BlockBehaviour.Properties DEFAULT_GLASS_PROPERTIES = BlockBehaviour.Properties.of().sound(SoundType.GLASS).strength(0.35F);\n\n    private BlockUtils() {\n    }\n\n    // Block#getTranslatedName is client only\n    public static Component getBlockTranslation(Block block) {\n        return Component.translatable(block.getDescriptionId());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/util/CollisionUtils.java",
    "content": "package com.refinedmods.refinedstorage.util;\n\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.world.phys.AABB;\nimport net.minecraft.world.phys.Vec3;\nimport net.minecraft.world.phys.shapes.VoxelShape;\n\npublic final class CollisionUtils {\n    private CollisionUtils() {\n    }\n\n    public static boolean isInBounds(VoxelShape shape, BlockPos pos, Vec3 hit) {\n        AABB aabb = shape.bounds().move(pos);\n\n        return hit.x >= aabb.minX\n            && hit.x <= aabb.maxX\n            && hit.y >= aabb.minY\n            && hit.y <= aabb.maxY\n            && hit.z >= aabb.minZ\n            && hit.z <= aabb.maxZ;\n    }\n\n    public static AABB getBounds(int fromX, int fromY, int fromZ, int toX, int toY, int toZ) {\n        return new AABB((float) fromX / 16F, (float) fromY / 16F, (float) fromZ / 16F, (float) toX / 16F, (float) toY / 16F, (float) toZ / 16F);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/util/ColorMap.java",
    "content": "package com.refinedmods.refinedstorage.util;\n\nimport java.util.Collection;\nimport java.util.EnumMap;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.function.BiConsumer;\n\nimport net.minecraft.world.item.DyeColor;\nimport net.neoforged.neoforge.registries.DeferredHolder;\nimport net.neoforged.neoforge.registries.DeferredRegister;\n\npublic class ColorMap<R, T extends R> {\n    public static final DyeColor DEFAULT_COLOR = DyeColor.LIGHT_BLUE;\n\n    protected final Map<DyeColor, DeferredHolder<R, T>> map = new EnumMap<>(DyeColor.class);\n    private final Map<T, DyeColor> colorByBlock = new HashMap<>();\n    protected final DeferredRegister<R> registry;\n    protected List<Runnable> lateRegistration;\n\n    public ColorMap(DeferredRegister<R> registry) {\n        this.registry = registry;\n    }\n\n    public ColorMap(DeferredRegister<R> registry, List<Runnable> lateRegistration) {\n        this.registry = registry;\n        this.lateRegistration = lateRegistration;\n    }\n\n    public DeferredHolder<R, T> get(DyeColor color) {\n        return map.get(color);\n    }\n\n    public DyeColor getColorFromObject(T object) {\n        if (colorByBlock.isEmpty()) {\n            map.forEach(((dyeColor, registryObject) -> colorByBlock.put(registryObject.get(), dyeColor)));\n        }\n        return colorByBlock.get(object);\n    }\n\n    public Collection<DeferredHolder<R, T>> values() {\n        return map.values();\n    }\n\n    public void put(DyeColor color, DeferredHolder<R, T> object) {\n        map.put(color, object);\n    }\n\n    public void forEach(BiConsumer<DyeColor, DeferredHolder<R, T>> consumer) {\n        map.forEach(consumer);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/util/DirectionUtils.java",
    "content": "package com.refinedmods.refinedstorage.util;\n\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.world.entity.LivingEntity;\n\npublic final class DirectionUtils {\n    private DirectionUtils() {\n    }\n\n    public static Direction getFacingFromEntity(BlockPos clickedBlock, LivingEntity entity) {\n        return Direction.getNearest(\n            (float) (entity.getX() - clickedBlock.getX()),\n            (float) (entity.getY() - clickedBlock.getY()),\n            (float) (entity.getZ() - clickedBlock.getZ())\n        );\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/util/ItemColorMap.java",
    "content": "package com.refinedmods.refinedstorage.util;\n\nimport com.refinedmods.refinedstorage.RS;\nimport com.refinedmods.refinedstorage.RSItems;\nimport com.refinedmods.refinedstorage.block.BaseBlock;\nimport com.refinedmods.refinedstorage.item.blockitem.ColoredBlockItem;\n\nimport java.util.List;\n\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.tags.ItemTags;\nimport net.minecraft.world.item.BlockItem;\nimport net.minecraft.world.item.DyeColor;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.level.block.Block;\nimport net.neoforged.neoforge.registries.DeferredHolder;\nimport net.neoforged.neoforge.registries.DeferredRegister;\n\npublic class ItemColorMap extends ColorMap<Item, ColoredBlockItem> {\n    public ItemColorMap(DeferredRegister<Item> registry) {\n        super(registry);\n    }\n\n    public ItemColorMap(DeferredRegister<Item> registry, List<Runnable> lateRegistration) {\n        super(registry, lateRegistration);\n    }\n\n    public <S extends BaseBlock> void registerItemsFromBlocks(ColorMap<Block, S> blockMap) {\n        DeferredHolder<Block, S> originalBlock = blockMap.get(DEFAULT_COLOR);\n        map.put(DEFAULT_COLOR, registerBlockItemFor(originalBlock, DEFAULT_COLOR, originalBlock));\n        lateRegistration.add(() -> blockMap.forEach((color, block) -> {\n            if (color != DEFAULT_COLOR) {\n                map.put(color, registerBlockItemFor(block, color, originalBlock));\n            }\n        }));\n        RSItems.COLORED_ITEM_TAGS.put(\n            ItemTags.create(new ResourceLocation(RS.ID, blockMap.get(DEFAULT_COLOR).getId().getPath())),\n            this\n        );\n    }\n\n    private <S extends BaseBlock> DeferredHolder<Item, ColoredBlockItem> registerBlockItemFor(\n        DeferredHolder<Block, S> block,\n        DyeColor color,\n        DeferredHolder<Block, S> translationBlock\n    ) {\n        return registry.register(\n            block.getId().getPath(),\n            () -> new ColoredBlockItem(\n                block.get(),\n                new Item.Properties(),\n                color,\n                BlockUtils.getBlockTranslation(translationBlock.get())\n            )\n        );\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/util/ItemStackKey.java",
    "content": "package com.refinedmods.refinedstorage.util;\n\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport net.minecraft.world.item.ItemStack;\n\npublic final class ItemStackKey {\n    private final ItemStack stack;\n\n    public ItemStackKey(ItemStack stack) {\n        this.stack = stack;\n    }\n\n    public ItemStack getStack() {\n        return stack;\n    }\n\n    @Override\n    public boolean equals(Object other) {\n        return other instanceof ItemStackKey && API.instance().getComparer().isEqualNoQuantity(stack, ((ItemStackKey) other).stack);\n    }\n\n    @Override\n    public int hashCode() {\n        return API.instance().getItemStackHashCode(stack);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/util/LevelUtils.java",
    "content": "package com.refinedmods.refinedstorage.util;\n\nimport com.refinedmods.refinedstorage.render.Styles;\n\nimport java.util.Optional;\nimport java.util.UUID;\nimport javax.annotation.Nullable;\n\nimport com.mojang.authlib.GameProfile;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.server.players.GameProfileCache;\nimport net.minecraft.world.Container;\nimport net.minecraft.world.WorldlyContainer;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.level.ClipContext;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.minecraft.world.phys.HitResult;\nimport net.minecraft.world.phys.Vec3;\nimport net.neoforged.neoforge.capabilities.Capabilities;\nimport net.neoforged.neoforge.common.util.FakePlayer;\nimport net.neoforged.neoforge.common.util.FakePlayerFactory;\nimport net.neoforged.neoforge.fluids.capability.IFluidHandler;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport net.neoforged.neoforge.items.wrapper.InvWrapper;\nimport net.neoforged.neoforge.items.wrapper.SidedInvWrapper;\n\npublic final class LevelUtils {\n    private LevelUtils() {\n    }\n\n    public static void updateBlock(@Nullable Level level, BlockPos pos) {\n        if (level != null && level.isLoaded(pos)) {\n            BlockState state = level.getBlockState(pos);\n\n            level.sendBlockUpdated(pos, state, state, 1 | 2);\n        }\n    }\n\n    public static IItemHandler getItemHandler(@Nullable Level level, BlockPos pos, Direction side) {\n        if (level == null) {\n            return null;\n        }\n        IItemHandler handler = level.getCapability(Capabilities.ItemHandler.BLOCK, pos, side);\n        if (handler == null) {\n            if (level instanceof WorldlyContainer) {\n                handler = new SidedInvWrapper((WorldlyContainer) level, side);\n            } else if (level instanceof Container) {\n                handler = new InvWrapper((Container) level);\n            }\n        }\n        return handler;\n    }\n\n    public static IFluidHandler getFluidHandler(@Nullable Level level, BlockPos pos, Direction side) {\n        if (level == null) {\n            return null;\n        }\n        return level.getCapability(Capabilities.FluidHandler.BLOCK, pos, side);\n    }\n\n    public static FakePlayer getFakePlayer(ServerLevel level, @Nullable UUID owner) {\n        if (owner != null) {\n            GameProfileCache profileCache = level.getServer().getProfileCache();\n\n            Optional<GameProfile> profile = profileCache.get(owner);\n\n            if (profile.isPresent()) {\n                return FakePlayerFactory.get(level, profile.get());\n            }\n        }\n\n        return FakePlayerFactory.getMinecraft(level);\n    }\n\n    public static void sendNoPermissionMessage(Player player) {\n        player.sendSystemMessage(\n            Component.translatable(\"misc.refinedstorage.security.no_permission\").setStyle(Styles.RED));\n    }\n\n    public static HitResult rayTracePlayer(Level level, Player player) {\n        double reachDistance = player.getBlockReach();\n\n        Vec3 base = player.getEyePosition(1.0F);\n        Vec3 look = player.getLookAngle();\n        Vec3 target = base.add(look.x * reachDistance, look.y * reachDistance, look.z * reachDistance);\n\n        return level.clip(new ClipContext(base, target, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/util/NetworkUtils.java",
    "content": "package com.refinedmods.refinedstorage.util;\n\nimport com.refinedmods.refinedstorage.api.network.INetwork;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNode;\nimport com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy;\nimport com.refinedmods.refinedstorage.api.network.security.Permission;\nimport com.refinedmods.refinedstorage.api.util.Action;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.world.InteractionResult;\nimport net.minecraft.world.entity.player.Player;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.level.Level;\nimport net.minecraft.world.level.block.entity.BlockEntity;\n\nimport javax.annotation.Nullable;\nimport java.util.function.Consumer;\n\npublic final class NetworkUtils {\n    private NetworkUtils() {\n    }\n\n    @Nullable\n    public static INetworkNode getNodeFromBlockEntity(@Nullable BlockEntity blockEntity) {\n        if (blockEntity instanceof INetworkNodeProxy<?> proxy) {\n            return proxy.getNode();\n        }\n        return null;\n    }\n\n    @Nullable\n    public static INetwork getNetworkFromNode(@Nullable INetworkNode node) {\n        if (node != null) {\n            return node.getNetwork();\n        }\n        return null;\n    }\n\n    public static InteractionResult attemptModify(Level level, BlockPos pos, Player player, Runnable action) {\n        return attempt(level, pos, player, action, Permission.MODIFY);\n    }\n\n    public static InteractionResult attempt(Level level, BlockPos pos, Player player, Runnable action, Permission... permissionsRequired) {\n        if (level.isClientSide) {\n            return InteractionResult.SUCCESS;\n        }\n\n        INetwork network = getNetworkFromNode(getNodeFromBlockEntity(level.getBlockEntity(pos)));\n\n        if (network != null) {\n            for (Permission permission : permissionsRequired) {\n                if (!network.getSecurityManager().hasPermission(permission, player)) {\n                    LevelUtils.sendNoPermissionMessage(player);\n\n                    return InteractionResult.SUCCESS;\n                }\n            }\n        }\n\n        action.run();\n\n        return InteractionResult.SUCCESS;\n    }\n\n    public static void extractBucketFromPlayerInventoryOrNetwork(Player player, INetwork network, Consumer<ItemStack> onBucketFound) {\n        for (int i = 0; i < player.getInventory().getContainerSize(); ++i) {\n            ItemStack slot = player.getInventory().getItem(i);\n\n            if (API.instance().getComparer().isEqualNoQuantity(StackUtils.EMPTY_BUCKET, slot)) {\n                player.getInventory().removeItem(i, 1);\n\n                onBucketFound.accept(StackUtils.EMPTY_BUCKET.copy());\n\n                return;\n            }\n        }\n\n        ItemStack fromNetwork = network.extractItem(StackUtils.EMPTY_BUCKET, 1, Action.PERFORM);\n        if (!fromNetwork.isEmpty()) {\n            onBucketFound.accept(fromNetwork);\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/util/PacketBufferUtils.java",
    "content": "package com.refinedmods.refinedstorage.util;\n\nimport net.minecraft.network.FriendlyByteBuf;\n\npublic final class PacketBufferUtils {\n    private PacketBufferUtils() {\n    }\n\n    // @Volatile: From PacketBuffer#readUtf, this exists because SideOnly\n    public static String readString(FriendlyByteBuf buffer) {\n        return buffer.readUtf(32767);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/util/PlayerUtils.java",
    "content": "package com.refinedmods.refinedstorage.util;\n\nimport net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;\nimport net.minecraft.server.level.ServerPlayer;\nimport net.minecraft.world.entity.player.Inventory;\n\npublic class PlayerUtils {\n    public static void updateHeldItems(ServerPlayer player) {\n        int mainHandSlot = player.getInventory().selected;\n        int offHandSlot = Inventory.SLOT_OFFHAND;\n\n        //See ClientPlayNetHandler#HandleSetSlot for the awful vanilla code that makes this necessary\n        // -2 as that directly sets the inventory slots\n        player.connection.send(new ClientboundContainerSetSlotPacket(-2, player.containerMenu.incrementStateId(), mainHandSlot, player.getInventory().getItem(mainHandSlot)));\n        player.connection.send(new ClientboundContainerSetSlotPacket(-2, player.containerMenu.incrementStateId(), offHandSlot, player.getInventory().getItem(offHandSlot)));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/util/RenderUtils.java",
    "content": "package com.refinedmods.refinedstorage.util;\n\nimport com.google.common.collect.ImmutableMap;\nimport com.refinedmods.refinedstorage.api.util.IComparer;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.render.Styles;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.renderer.RenderType;\nimport net.minecraft.client.renderer.block.model.BakedQuad;\nimport net.minecraft.client.renderer.block.model.ItemTransform;\nimport net.minecraft.client.renderer.block.model.ItemTransforms;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.client.resources.model.BakedModel;\nimport net.minecraft.core.Direction;\nimport net.minecraft.network.chat.Component;\nimport net.minecraft.network.chat.MutableComponent;\nimport net.minecraft.util.Mth;\nimport net.minecraft.util.RandomSource;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.TooltipFlag;\nimport net.minecraft.world.level.block.state.BlockState;\nimport net.neoforged.neoforge.client.model.data.ModelData;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport org.joml.Quaternionf;\nimport org.joml.Vector3f;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\npublic final class RenderUtils {\n    private RenderUtils() {\n    }\n\n    private static Vector3f getRotationVector(Direction direction) {\n        return switch (direction) {\n            case NORTH -> new Vector3f(0, 0, 0);\n            case EAST -> new Vector3f(0, -90, 0);\n            case SOUTH -> new Vector3f(0, 180, 0);\n            case WEST -> new Vector3f(0, 90, 0);\n            case UP -> new Vector3f(90, 0, 180);\n            case DOWN -> new Vector3f(-90, 0, 0);\n        };\n    }\n\n    public static Quaternionf getQuaternion(Direction direction) {\n        Vector3f vec = getRotationVector(direction);\n        return new Quaternionf().rotateXYZ(\n            vec.x() * Mth.DEG_TO_RAD,\n            vec.y() * Mth.DEG_TO_RAD,\n            vec.z() * Mth.DEG_TO_RAD\n        );\n    }\n\n    public static String shorten(String text, int length) {\n        if (text.length() > length) {\n            text = text.substring(0, length) + \"...\";\n        }\n        return text;\n    }\n\n    public static int getOffsetOnScale(int pos, float scale) {\n        float multiplier = (pos / scale);\n\n        return (int) multiplier;\n    }\n\n    public static void addCombinedItemsToTooltip(List<Component> tooltip, boolean displayAmount, List<ItemStack> stacks) {\n        Set<Integer> combinedIndices = new HashSet<>();\n\n        for (int i = 0; i < stacks.size(); ++i) {\n            if (!stacks.get(i).isEmpty() && !combinedIndices.contains(i)) {\n                ItemStack stack = stacks.get(i);\n\n                MutableComponent data = stack.getHoverName().plainCopy();\n\n                int amount = stack.getCount();\n\n                for (int j = i + 1; j < stacks.size(); ++j) {\n                    if (API.instance().getComparer().isEqual(stack, stacks.get(j))) {\n                        amount += stacks.get(j).getCount();\n\n                        combinedIndices.add(j);\n                    }\n                }\n\n                if (displayAmount) {\n                    data = Component.literal(amount + \"x \").append(data);\n                }\n\n                tooltip.add(data.setStyle(Styles.GRAY));\n            }\n        }\n    }\n\n    public static void addCombinedFluidsToTooltip(List<Component> tooltip, boolean displayMb, List<FluidStack> stacks) {\n        Set<Integer> combinedIndices = new HashSet<>();\n\n        for (int i = 0; i < stacks.size(); ++i) {\n            if (!stacks.get(i).isEmpty() && !combinedIndices.contains(i)) {\n                FluidStack stack = stacks.get(i);\n\n                MutableComponent data = stack.getDisplayName().plainCopy();\n\n                int amount = stack.getAmount();\n\n                for (int j = i + 1; j < stacks.size(); ++j) {\n                    if (API.instance().getComparer().isEqual(stack, stacks.get(j), IComparer.COMPARE_NBT)) {\n                        amount += stacks.get(j).getAmount();\n\n                        combinedIndices.add(j);\n                    }\n                }\n\n                if (displayMb) {\n                    data = Component.literal(API.instance().getQuantityFormatter().formatInBucketForm(amount) + \" \").append(data);\n                }\n\n                tooltip.add(data.setStyle(Styles.GRAY));\n            }\n        }\n    }\n\n    // @Volatile: From Screen#getTooltipFromItem\n    public static List<Component> getTooltipFromItem(ItemStack stack) {\n        Minecraft minecraft = Minecraft.getInstance();\n        return stack.getTooltipLines(minecraft.player, minecraft.options.advancedItemTooltips ? TooltipFlag.Default.ADVANCED : TooltipFlag.Default.NORMAL);\n    }\n\n    public static boolean inBounds(int x, int y, int w, int h, double ox, double oy) {\n        return ox >= x && ox <= x + w && oy >= y && oy <= y + h;\n    }\n\n    public static TextureAtlasSprite getSprite(BakedModel coverModel, BlockState coverState, Direction facing, RandomSource rand) {\n        TextureAtlasSprite sprite = null;\n\n        try {\n            for (RenderType layer : coverModel.getRenderTypes(coverState, rand, ModelData.EMPTY)) {\n                for (BakedQuad bakedQuad : coverModel.getQuads(coverState, facing, rand, ModelData.EMPTY, layer)) {\n                    return bakedQuad.getSprite();\n                }\n\n                for (BakedQuad bakedQuad : coverModel.getQuads(coverState, null, rand)) {\n                    if (sprite == null) {\n                        sprite = bakedQuad.getSprite();\n                    }\n\n                    if (bakedQuad.getDirection() == facing) {\n                        return bakedQuad.getSprite();\n                    }\n                }\n            }\n        } catch (Exception e) {\n            // NO OP\n        }\n\n        if (sprite == null) {\n            try {\n                sprite = coverModel.getParticleIcon();\n            } catch (Exception e) {\n                // NO OP\n            }\n        }\n\n        if (sprite == null) {\n            for (BakedQuad quad : Minecraft.getInstance().getModelManager().getMissingModel().getQuads(coverState, facing, rand)) {\n                return quad.getSprite();\n            }\n        }\n\n        return sprite;\n    }\n\n    public static ItemTransforms getDefaultBlockTransforms() {\n        var thirdperson = getTransform(0, 2.5f, 0, 75, 45, 0, 0.375f);\n        return new ItemTransforms(\n            thirdperson,\n            thirdperson,\n            getTransform(0, 0, 0, 0, 225, 0, 0.4f),\n            getTransform(0, 0, 0, 0, 45, 0, 0.4f),\n            ItemTransform.NO_TRANSFORM,\n            getTransform(-3, 1, 0, 30, 225, 0, 0.625f),\n            getTransform(0, 3, 0, 0, 0, 0, 0.25f),\n            getTransform(0, 0, 0, 0, 0, 0, 0.5f),\n            ImmutableMap.of());\n    }\n\n    private static ItemTransform getTransform(float tx, float ty, float tz, float ax, float ay, float az, float s) {\n        return new ItemTransform(\n            new Vector3f(ax, ay, az),\n            new Vector3f(tx / 16, ty / 16, tz / 16),\n            new Vector3f(s, s, s)\n        );\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/util/StackUtils.java",
    "content": "package com.refinedmods.refinedstorage.util;\n\nimport com.refinedmods.refinedstorage.api.storage.StorageType;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;\nimport com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskProvider;\nimport com.refinedmods.refinedstorage.api.storage.tracker.StorageTrackerEntry;\nimport com.refinedmods.refinedstorage.apiimpl.API;\nimport com.refinedmods.refinedstorage.inventory.item.BaseItemHandler;\nimport com.refinedmods.refinedstorage.network.grid.GridStackDelta;\nimport com.refinedmods.refinedstorage.screen.grid.stack.FluidGridStack;\nimport com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack;\n\nimport java.util.UUID;\nimport java.util.function.Function;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.core.registries.BuiltInRegistries;\nimport net.minecraft.nbt.CompoundTag;\nimport net.minecraft.nbt.ListTag;\nimport net.minecraft.nbt.Tag;\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft.server.level.ServerLevel;\nimport net.minecraft.world.Container;\nimport net.minecraft.world.item.Item;\nimport net.minecraft.world.item.ItemStack;\nimport net.minecraft.world.item.Items;\nimport net.neoforged.neoforge.attachment.AttachmentInternals;\nimport net.neoforged.neoforge.capabilities.Capabilities;\nimport net.neoforged.neoforge.fluids.FluidStack;\nimport net.neoforged.neoforge.fluids.FluidType;\nimport net.neoforged.neoforge.fluids.capability.IFluidHandler;\nimport net.neoforged.neoforge.fluids.capability.IFluidHandlerItem;\nimport net.neoforged.neoforge.items.IItemHandler;\nimport net.neoforged.neoforge.items.IItemHandlerModifiable;\nimport net.neoforged.neoforge.items.ItemHandlerHelper;\nimport org.apache.commons.lang3.tuple.Pair;\n\npublic final class StackUtils {\n    public static final ItemStack EMPTY_BUCKET = new ItemStack(Items.BUCKET);\n\n    private static final String NBT_INVENTORY = \"Inventory_%d\";\n    private static final String NBT_SLOT = \"Slot\";\n\n    private static final String NBT_ITEM_ID = \"Id\";\n    private static final String NBT_ITEM_QUANTITY = \"Quantity\";\n    private static final String NBT_ITEM_NBT = \"NBT\";\n\n    private StackUtils() {\n    }\n\n    // @Volatile: from FriendlyByteBuf#writeItem, but allows int item stack counts.\n    public static void writeItemStack(FriendlyByteBuf buf, @Nonnull ItemStack stack) {\n        if (stack.isEmpty()) {\n            buf.writeBoolean(false);\n        } else {\n            buf.writeBoolean(true);\n            Item item = stack.getItem();\n            buf.writeId(BuiltInRegistries.ITEM, item);\n            buf.writeInt(stack.getCount());\n            CompoundTag compoundtag = null;\n            if (item.isDamageable(stack) || item.shouldOverrideMultiplayerNbt()) {\n                compoundtag = stack.getTag();\n            }\n            compoundtag = AttachmentInternals.addAttachmentsToTag(compoundtag, stack, false);\n\n            buf.writeNbt(compoundtag);\n        }\n    }\n\n    // @Volatile: from FriendlyByteBuf#readItem, but allows int item stack counts.\n    public static ItemStack readItemStack(FriendlyByteBuf buf) {\n        if (!buf.readBoolean()) {\n            return ItemStack.EMPTY;\n        } else {\n            Item item = buf.readById(BuiltInRegistries.ITEM);\n            int i = buf.readInt();\n            return AttachmentInternals.reconstructItemStack(item, i, buf.readNbt());\n        }\n    }\n\n    public static void writeItemGridStackDelta(FriendlyByteBuf buf, GridStackDelta<ItemGridStack> delta) {\n        buf.writeInt(delta.change());\n        writeItemGridStack(buf, delta.stack());\n    }\n\n    public static void writeItemGridStack(FriendlyByteBuf buf, ItemGridStack stack) {\n        writeItemStack(buf, stack.getStack());\n\n        buf.writeBoolean(stack.isCraftable());\n        buf.writeUUID(stack.getId());\n\n        buf.writeBoolean(stack.getOtherId() != null);\n        if (stack.getOtherId() != null) {\n            buf.writeUUID(stack.getOtherId());\n        }\n\n        if (stack.getTrackerEntry() == null) {\n            buf.writeBoolean(false);\n        } else {\n            buf.writeBoolean(true);\n\n            buf.writeLong(stack.getTrackerEntry().getTime());\n            buf.writeUtf(stack.getTrackerEntry().getName());\n        }\n    }\n\n    public static GridStackDelta<ItemGridStack> readItemGridStackDelta(FriendlyByteBuf buf) {\n        int delta = buf.readInt();\n        return new GridStackDelta<>(delta, readItemGridStack(buf));\n    }\n\n    public static ItemGridStack readItemGridStack(FriendlyByteBuf buf) {\n        ItemStack stack = readItemStack(buf);\n\n        boolean craftable = buf.readBoolean();\n        UUID id = buf.readUUID();\n\n        UUID otherId = null;\n        if (buf.readBoolean()) {\n            otherId = buf.readUUID();\n        }\n\n        StorageTrackerEntry entry = null;\n        if (buf.readBoolean()) {\n            entry = new StorageTrackerEntry(buf.readLong(), PacketBufferUtils.readString(buf));\n        }\n\n        return new ItemGridStack(id, otherId, stack, craftable, entry);\n    }\n\n    public static void writeFluidGridStackDelta(FriendlyByteBuf buf, GridStackDelta<FluidGridStack> delta) {\n        buf.writeInt(delta.change());\n        writeFluidGridStack(buf, delta.stack());\n    }\n\n    public static void writeFluidGridStack(FriendlyByteBuf buf, FluidGridStack stack) {\n        stack.getStack().writeToPacket(buf);\n\n        buf.writeBoolean(stack.isCraftable());\n        buf.writeUUID(stack.getId());\n\n        buf.writeBoolean(stack.getOtherId() != null);\n        if (stack.getOtherId() != null) {\n            buf.writeUUID(stack.getOtherId());\n        }\n\n        if (stack.getTrackerEntry() == null) {\n            buf.writeBoolean(false);\n        } else {\n            buf.writeBoolean(true);\n\n            buf.writeLong(stack.getTrackerEntry().getTime());\n            buf.writeUtf(stack.getTrackerEntry().getName());\n        }\n    }\n\n    public static GridStackDelta<FluidGridStack> readFluidGridStackDelta(FriendlyByteBuf buf) {\n        int delta = buf.readInt();\n        return new GridStackDelta<>(delta, readFluidGridStack(buf));\n    }\n\n    public static FluidGridStack readFluidGridStack(FriendlyByteBuf buf) {\n        FluidStack stack = FluidStack.readFromPacket(buf);\n        boolean craftable = buf.readBoolean();\n        UUID id = buf.readUUID();\n\n        UUID otherId = null;\n        if (buf.readBoolean()) {\n            otherId = buf.readUUID();\n        }\n\n        StorageTrackerEntry entry = null;\n        if (buf.readBoolean()) {\n            entry = new StorageTrackerEntry(buf.readLong(), PacketBufferUtils.readString(buf));\n        }\n\n        return new FluidGridStack(id, otherId, stack, craftable, entry);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public static void createStorages(ServerLevel level, ItemStack diskStack, int slot,\n                                      IStorageDisk<ItemStack>[] itemDisks, IStorageDisk<FluidStack>[] fluidDisks,\n                                      Function<IStorageDisk<ItemStack>, IStorageDisk> itemDiskWrapper,\n                                      Function<IStorageDisk<FluidStack>, IStorageDisk> fluidDiskWrapper) {\n        if (diskStack.isEmpty()) {\n            itemDisks[slot] = null;\n            fluidDisks[slot] = null;\n        } else {\n            IStorageDisk disk = API.instance().getStorageDiskManager(level).getByStack(diskStack);\n\n            if (disk != null) {\n                StorageType type = ((IStorageDiskProvider) diskStack.getItem()).getType();\n\n                if (type == StorageType.ITEM) {\n                    itemDisks[slot] = itemDiskWrapper.apply(disk);\n                } else if (type == StorageType.FLUID) {\n                    fluidDisks[slot] = fluidDiskWrapper.apply(disk);\n                }\n            } else {\n                itemDisks[slot] = null;\n                fluidDisks[slot] = null;\n            }\n        }\n    }\n\n    public static void writeItems(IItemHandler handler, int id, CompoundTag tag,\n                                  Function<ItemStack, CompoundTag> serializer) {\n        ListTag tagList = new ListTag();\n\n        for (int i = 0; i < handler.getSlots(); i++) {\n            if (!handler.getStackInSlot(i).isEmpty()) {\n                CompoundTag stackTag = serializer.apply(handler.getStackInSlot(i));\n\n                stackTag.putInt(NBT_SLOT, i);\n\n                tagList.add(stackTag);\n            }\n        }\n\n        tag.put(String.format(NBT_INVENTORY, id), tagList);\n    }\n\n    public static void writeItems(IItemHandler handler, int id, CompoundTag tag) {\n        writeItems(handler, id, tag, stack -> stack.save(new CompoundTag()));\n    }\n\n    public static void readItems(IItemHandlerModifiable handler, int id, CompoundTag tag,\n                                 Function<CompoundTag, ItemStack> deserializer) {\n        String name = String.format(NBT_INVENTORY, id);\n\n        if (tag.contains(name)) {\n            ListTag tagList = tag.getList(name, Tag.TAG_COMPOUND);\n\n            for (int i = 0; i < tagList.size(); i++) {\n                int slot = tagList.getCompound(i).getInt(NBT_SLOT);\n\n                if (slot >= 0 && slot < handler.getSlots()) {\n                    handler.setStackInSlot(slot, deserializer.apply(tagList.getCompound(i)));\n                }\n            }\n        }\n    }\n\n    public static void readItems(IItemHandlerModifiable handler, int id, CompoundTag tag) {\n        readItems(handler, id, tag, ItemStack::of);\n    }\n\n    public static void readItems(BaseItemHandler handler, int id, CompoundTag tag) {\n        handler.setReading(true);\n\n        readItems(handler, id, tag, ItemStack::of);\n\n        handler.setReading(false);\n    }\n\n    public static void writeItems(Container inventory, int id, CompoundTag tag) {\n        ListTag tagList = new ListTag();\n\n        for (int i = 0; i < inventory.getContainerSize(); i++) {\n            if (!inventory.getItem(i).isEmpty()) {\n                CompoundTag stackTag = new CompoundTag();\n\n                stackTag.putInt(NBT_SLOT, i);\n\n                inventory.getItem(i).save(stackTag);\n\n                tagList.add(stackTag);\n            }\n        }\n\n        tag.put(String.format(NBT_INVENTORY, id), tagList);\n    }\n\n    public static void readItems(Container inventory, int id, CompoundTag tag) {\n        String name = String.format(NBT_INVENTORY, id);\n\n        if (tag.contains(name)) {\n            ListTag tagList = tag.getList(name, Tag.TAG_COMPOUND);\n\n            for (int i = 0; i < tagList.size(); i++) {\n                int slot = tagList.getCompound(i).getInt(NBT_SLOT);\n\n                ItemStack stack = ItemStack.of(tagList.getCompound(i));\n\n                if (!stack.isEmpty()) {\n                    inventory.setItem(slot, stack);\n                }\n            }\n        }\n    }\n\n    public static FluidStack copy(FluidStack stack, int size) {\n        FluidStack copy = stack.copy();\n        copy.setAmount(size);\n        return copy;\n    }\n\n    public static FluidStack copy(@Nullable FluidStack stack) {\n        return stack == null ? null : stack.copy();\n    }\n\n    public static Pair<ItemStack, FluidStack> getFluid(ItemStack stack, boolean simulate) {\n        if (stack.isEmpty()) {\n            return Pair.of(ItemStack.EMPTY, FluidStack.EMPTY);\n        }\n\n        if (stack.getCount() > 1) {\n            stack = ItemHandlerHelper.copyStackWithSize(stack, 1);\n        }\n\n        IFluidHandlerItem handler = stack.getCapability(Capabilities.FluidHandler.ITEM);\n        if (handler != null) {\n            FluidStack result = handler.drain(FluidType.BUCKET_VOLUME,\n                simulate ? IFluidHandler.FluidAction.SIMULATE : IFluidHandler.FluidAction.EXECUTE);\n\n            return Pair.of(handler.getContainer(), result);\n        }\n\n        return Pair.of(ItemStack.EMPTY, FluidStack.EMPTY);\n    }\n\n    public static CompoundTag serializeStackToNbt(@Nonnull ItemStack stack) {\n        CompoundTag itemTag = new CompoundTag();\n        ResourceLocation key = BuiltInRegistries.ITEM.getKey(stack.getItem());\n        itemTag.putString(NBT_ITEM_ID, key.toString());\n        itemTag.putInt(NBT_ITEM_QUANTITY, stack.getCount());\n        var tag = AttachmentInternals.addAttachmentsToTag(stack.getTag(), stack, true);\n        if (tag != null) {\n            itemTag.put(NBT_ITEM_NBT, tag);\n        }\n        return itemTag;\n    }\n\n    @Nonnull\n    public static ItemStack deserializeStackFromNbt(CompoundTag tag) {\n        return AttachmentInternals.reconstructItemStack(\n            BuiltInRegistries.ITEM.get(new ResourceLocation(tag.getString(NBT_ITEM_ID))),\n            tag.getInt(NBT_ITEM_QUANTITY),\n            tag.contains(NBT_ITEM_NBT) ? tag.getCompound(NBT_ITEM_NBT) : null\n        );\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/refinedmods/refinedstorage/util/TimeUtils.java",
    "content": "package com.refinedmods.refinedstorage.util;\n\nimport net.minecraft.client.resources.language.I18n;\n\npublic final class TimeUtils {\n    private static final long SECOND = 1000;\n    private static final long MINUTE = SECOND * 60;\n    private static final long HOUR = MINUTE * 60;\n    private static final long DAY = HOUR * 24;\n    private static final long WEEK = DAY * 7;\n    private static final long YEAR = DAY * 365;\n\n    private TimeUtils() {\n    }\n\n    public static String getAgo(long ago, String by) {\n        long diff = System.currentTimeMillis() - ago;\n\n        if (diff < SECOND * 10) {\n            return I18n.get(\"misc.refinedstorage.last_modified.just_now\", by);\n        } else if (diff < MINUTE) {\n            return I18n.get(\"misc.refinedstorage.last_modified.second\" + ((diff / SECOND) > 1 ? \"s\" : \"\"), diff / SECOND, by);\n        } else if (diff < HOUR) {\n            return I18n.get(\"misc.refinedstorage.last_modified.minute\" + ((diff / MINUTE) > 1 ? \"s\" : \"\"), diff / MINUTE, by);\n        } else if (diff < DAY) {\n            return I18n.get(\"misc.refinedstorage.last_modified.hour\" + ((diff / HOUR) > 1 ? \"s\" : \"\"), diff / HOUR, by);\n        } else if (diff < WEEK) {\n            return I18n.get(\"misc.refinedstorage.last_modified.day\" + ((diff / DAY) > 1 ? \"s\" : \"\"), diff / DAY, by);\n        } else if (diff < YEAR) {\n            return I18n.get(\"misc.refinedstorage.last_modified.week\" + ((diff / WEEK) > 1 ? \"s\" : \"\"), diff / WEEK, by);\n        }\n\n        return I18n.get(\"misc.refinedstorage.last_modified.year\" + ((diff / YEAR) > 1 ? \"s\" : \"\"), diff / YEAR, by);\n    }\n}\n"
  },
  {
    "path": "src/main/resources/META-INF/accesstransformer.cfg",
    "content": "protected net.minecraft.world.inventory.AbstractContainerMenu lastSlots\nprotected net.minecraft.world.inventory.AbstractContainerMenu containerListeners\nprotected net.minecraft.client.gui.components.EditBox canLoseFocus\npublic net.minecraft.client.gui.components.Checkbox selected\npublic-f net.minecraft.world.inventory.Slot y\npublic net.minecraft.client.gui.GuiGraphics renderTooltipInternal(Lnet/minecraft/client/gui/Font;Ljava/util/List;IILnet/minecraft/client/gui/screens/inventory/tooltip/ClientTooltipPositioner;)V\n"
  },
  {
    "path": "src/main/resources/META-INF/mods.toml",
    "content": "modLoader = \"javafml\"\nloaderVersion = \"[2,)\"\nissueTrackerURL = \"https://github.com/refinedmods/refinedstorage\"\nlicense=\"MIT\"\n[[mods]]\nmodId = \"refinedstorage\"\nversion = \"${version}\"\ndisplayName = \"Refined Storage\"\ndisplayURL = \"https://refinedmods.com/refined-storage\"\nlogoFile = \"logo.png\"\nauthors = \"Refined Mods\"\ndescription = '''\nAn elegant solution to your hoarding problem\n'''"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/1024k_fluid_storage_block.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/1024k_fluid_storage_block\"\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/16k_storage_block.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/16k_storage_block\"\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/1k_storage_block.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/1k_storage_block\"\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/256k_fluid_storage_block.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/256k_fluid_storage_block\"\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/4096k_fluid_storage_block.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/4096k_fluid_storage_block\"\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/4k_storage_block.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/4k_storage_block\"\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/64k_fluid_storage_block.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/64k_fluid_storage_block\"\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/64k_storage_block.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/64k_storage_block\"\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/cable.json",
    "content": "{\n  \"multipart\": [\n    {\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_core\"\n      }\n    },\n    {\n      \"when\": {\n        \"north\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\"\n      }\n    },\n    {\n      \"when\": {\n        \"east\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"y\": 90\n      }\n    },\n    {\n      \"when\": {\n        \"south\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"x\": 180\n      }\n    },\n    {\n      \"when\": {\n        \"west\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"y\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"up\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"x\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"down\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"x\": 90\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/constructor.json",
    "content": "{\n  \"multipart\": [\n    {\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_core\"\n      }\n    },\n    {\n      \"when\": {\n        \"north\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\"\n      }\n    },\n    {\n      \"when\": {\n        \"east\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"y\": 90\n      }\n    },\n    {\n      \"when\": {\n        \"south\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"x\": 180\n      }\n    },\n    {\n      \"when\": {\n        \"west\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"y\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"up\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"x\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"down\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"x\": 90\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"north\",\n        \"connected\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/constructor_connected\"\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"east\",\n        \"connected\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/constructor_connected\",\n        \"y\": 90\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"south\",\n        \"connected\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/constructor_connected\",\n        \"x\": 180\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"west\",\n        \"connected\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/constructor_connected\",\n        \"y\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"up\",\n        \"connected\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/constructor_connected\",\n        \"x\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"down\",\n        \"connected\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/constructor_connected\",\n        \"x\": 90\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"north\",\n        \"connected\": false\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/constructor_disconnected\"\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"east\",\n        \"connected\": false\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/constructor_disconnected\",\n        \"y\": 90\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"south\",\n        \"connected\": false\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/constructor_disconnected\",\n        \"x\": 180\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"west\",\n        \"connected\": false\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/constructor_disconnected\",\n        \"y\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"up\",\n        \"connected\": false\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/constructor_disconnected\",\n        \"x\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"down\",\n        \"connected\": false\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/constructor_disconnected\",\n        \"x\": 90\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/creative_fluid_storage_block.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/creative_fluid_storage_block\"\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/creative_portable_grid.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/portable_grid\"\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/creative_storage_block.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/creative_storage_block\"\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/destructor.json",
    "content": "{\n  \"multipart\": [\n    {\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_core\"\n      }\n    },\n    {\n      \"when\": {\n        \"north\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\"\n      }\n    },\n    {\n      \"when\": {\n        \"east\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"y\": 90\n      }\n    },\n    {\n      \"when\": {\n        \"south\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"x\": 180\n      }\n    },\n    {\n      \"when\": {\n        \"west\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"y\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"up\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"x\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"down\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"x\": 90\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"north\",\n        \"connected\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/destructor_connected\"\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"east\",\n        \"connected\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/destructor_connected\",\n        \"y\": 90\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"south\",\n        \"connected\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/destructor_connected\",\n        \"x\": 180\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"west\",\n        \"connected\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/destructor_connected\",\n        \"y\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"up\",\n        \"connected\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/destructor_connected\",\n        \"x\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"down\",\n        \"connected\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/destructor_connected\",\n        \"x\": 90\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"north\",\n        \"connected\": false\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/destructor_disconnected\"\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"east\",\n        \"connected\": false\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/destructor_disconnected\",\n        \"y\": 90\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"south\",\n        \"connected\": false\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/destructor_disconnected\",\n        \"x\": 180\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"west\",\n        \"connected\": false\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/destructor_disconnected\",\n        \"y\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"up\",\n        \"connected\": false\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/destructor_disconnected\",\n        \"x\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"down\",\n        \"connected\": false\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/destructor_disconnected\",\n        \"x\": 90\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/disk_drive.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/disk_drive\"\n    }\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/exporter.json",
    "content": "{\n  \"multipart\": [\n    {\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_core\"\n      }\n    },\n    {\n      \"when\": {\n        \"north\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\"\n      }\n    },\n    {\n      \"when\": {\n        \"east\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"y\": 90\n      }\n    },\n    {\n      \"when\": {\n        \"south\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"x\": 180\n      }\n    },\n    {\n      \"when\": {\n        \"west\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"y\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"up\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"x\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"down\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"x\": 90\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"north\"\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/exporter\"\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"east\"\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/exporter\",\n        \"y\": 90\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"south\"\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/exporter\",\n        \"x\": 180\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"west\"\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/exporter\",\n        \"y\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"up\"\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/exporter\",\n        \"x\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"down\"\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/exporter\",\n        \"x\": 90\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/external_storage.json",
    "content": "{\n  \"multipart\": [\n    {\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_core\"\n      }\n    },\n    {\n      \"when\": {\n        \"north\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\"\n      }\n    },\n    {\n      \"when\": {\n        \"east\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"y\": 90\n      }\n    },\n    {\n      \"when\": {\n        \"south\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"x\": 180\n      }\n    },\n    {\n      \"when\": {\n        \"west\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"y\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"up\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"x\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"down\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"x\": 90\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"north\"\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/external_storage\"\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"east\"\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/external_storage\",\n        \"y\": 90\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"south\"\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/external_storage\",\n        \"x\": 180\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"west\"\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/external_storage\",\n        \"y\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"up\"\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/external_storage\",\n        \"x\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"down\"\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/external_storage\",\n        \"x\": 90\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/fluid_interface.json",
    "content": "{\n  \"variants\": {\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/fluid_interface_connected\"\n    },\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/fluid_interface_disconnected\"\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/importer.json",
    "content": "{\n  \"multipart\": [\n    {\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_core\"\n      }\n    },\n    {\n      \"when\": {\n        \"north\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\"\n      }\n    },\n    {\n      \"when\": {\n        \"east\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"y\": 90\n      }\n    },\n    {\n      \"when\": {\n        \"south\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"x\": 180\n      }\n    },\n    {\n      \"when\": {\n        \"west\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"y\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"up\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"x\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"down\": true\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/cable_extension\",\n        \"x\": 90\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"north\"\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/importer\"\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"east\"\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/importer\",\n        \"y\": 90\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"south\"\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/importer\",\n        \"x\": 180\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"west\"\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/importer\",\n        \"y\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"up\"\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/importer\",\n        \"x\": 270\n      }\n    },\n    {\n      \"when\": {\n        \"direction\": \"down\"\n      },\n      \"apply\": {\n        \"model\": \"refinedstorage:block/importer\",\n        \"x\": 90\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/interface.json",
    "content": "{\n  \"variants\": {\n    \"connected=true\": {\n      \"model\": \"refinedstorage:block/interface_connected\"\n    },\n    \"connected=false\": {\n      \"model\": \"refinedstorage:block/interface_disconnected\"\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/machine_casing.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/machine_casing\"\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/portable_grid.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/portable_grid\"\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/quartz_enriched_iron_block.json",
    "content": "{\n  \"variants\": {\n    \"\": {\n      \"model\": \"refinedstorage:block/quartz_enriched_iron_block\"\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/blockstates/storage_monitor.json",
    "content": "{\n  \"variants\": {\n    \"direction=north\": {\n      \"model\": \"refinedstorage:block/storage_monitor\",\n      \"y\": 0\n    },\n    \"direction=east\": {\n      \"model\": \"refinedstorage:block/storage_monitor\",\n      \"y\": 90\n    },\n    \"direction=south\": {\n      \"model\": \"refinedstorage:block/storage_monitor\",\n      \"y\": 180\n    },\n    \"direction=west\": {\n      \"model\": \"refinedstorage:block/storage_monitor\",\n      \"y\": 270\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/lang/de_de.json",
    "content": "{\n  \"itemGroup.refinedstorage\": \"Refined Storage\",\n  \"itemGroup.refinedstorage.covers\": \"Refined Storage Fassaden\",\n\n  \"key.refinedstorage.focusSearchBar\": \"Konsolensuchleiste Selektieren\",\n  \"key.refinedstorage.clearGridCraftingMatrix\": \"Werkbank in der Konsole leeren\",\n\n  \"gui.refinedstorage.controller\": \"Kontrollblock\",\n  \"gui.refinedstorage.creative_controller\": \"Kreativ-Kontrollblock\",\n  \"gui.refinedstorage.grid\": \"Konsole\",\n  \"gui.refinedstorage.grid.craft\": \"Herstellen\",\n  \"gui.refinedstorage.crafting_grid\": \"Fertigungskonsole\",\n  \"gui.refinedstorage.pattern_grid\": \"Vorlagenkonsole\",\n  \"gui.refinedstorage.grid.pattern_create\": \"Vorlage herstellen\",\n  \"gui.refinedstorage.fluid_grid\": \"Flüssigkeitskonsole\",\n  \"gui.refinedstorage.portable_grid\": \"Mobile Konsole\",\n  \"gui.refinedstorage.item_amount\": \"Menge an Items\",\n  \"gui.refinedstorage.fluid_amount\": \"Flüssigkeitsmenge in mB\",\n  \"gui.refinedstorage.disk_drive\": \"Laufwerk\",\n  \"gui.refinedstorage.disk_drive.disks\": \"Speicherplatten\",\n  \"gui.refinedstorage.external_storage\": \"Externer Speicher\",\n  \"gui.refinedstorage.importer\": \"Importierer\",\n  \"gui.refinedstorage.exporter\": \"Exportierer\",\n  \"gui.refinedstorage.detector\": \"Detektor\",\n  \"gui.refinedstorage.destructor\": \"Destruktor\",\n  \"gui.refinedstorage.constructor\": \"Konstruktor\",\n  \"gui.refinedstorage.relay\": \"Relais\",\n  \"gui.refinedstorage.interface.import\": \"Importschnittstelle\",\n  \"gui.refinedstorage.interface.export\": \"Exportschnittstelle\",\n  \"gui.refinedstorage.crafting_monitor\": \"Fertigungsmonitor\",\n  \"gui.refinedstorage.wireless_crafting_monitor\": \"Mobile Fertigungskonsole\",\n  \"gui.refinedstorage.crafting_monitor.tooltip.requested\": \"%d angefragt\",\n  \"gui.refinedstorage.crafting_monitor.stored\": \"Gespeichert: %d\",\n  \"gui.refinedstorage.crafting_monitor.missing\": \"Fehlt\",\n  \"gui.refinedstorage.crafting_monitor.processing\": \"Verarbeitung\",\n  \"gui.refinedstorage.crafting_monitor.scheduled\": \"Geplant: %d\",\n  \"gui.refinedstorage.crafting_monitor.crafting\": \"Fertigung: %d\",\n  \"gui.refinedstorage.crafting_monitor.machine_does_not_accept_item\": \"Maschine akzeptiert Item nicht\",\n  \"gui.refinedstorage.crafting_monitor.machine_does_not_accept_fluid\": \"Maschine akzeptiert Flüssigkeit nicht\",\n  \"gui.refinedstorage.crafting_monitor.machine_none\": \"Keine Maschine gefunden\",\n  \"gui.refinedstorage.crafting_monitor.crafter_is_locked\": \"Fertiger ist gesperrt\",\n  \"gui.refinedstorage.wireless_transmitter\": \"Funksender\",\n  \"gui.refinedstorage.wireless_transmitter.distance\": \"%d Blöcke\",\n  \"gui.refinedstorage.crafter\": \"Fertigungseinheit\",\n  \"gui.refinedstorage.filter\": \"Filter\",\n  \"gui.refinedstorage.filter.compare_nbt\": \"NBT\",\n  \"gui.refinedstorage.filter.mod_filter\": \"Mod Filter\",\n  \"gui.refinedstorage.network_transmitter\": \"Netzwerksender\",\n  \"gui.refinedstorage.network_transmitter.distance\": \"%d Blöcke\",\n  \"gui.refinedstorage.network_transmitter.missing_card\": \"Fehlende Netzwerk Karte\",\n  \"gui.refinedstorage.fluid_interface\": \"Flüssigkeitsschnittstelle\",\n  \"gui.refinedstorage.fluid_interface.in\": \"Ein\",\n  \"gui.refinedstorage.fluid_interface.out\": \"Aus\",\n  \"gui.refinedstorage.crafting_preview\": \"Fertigungsvorschau\",\n  \"gui.refinedstorage.crafting_preview.to_craft\": \"Herzustellen: %d\",\n  \"gui.refinedstorage.crafting_preview.available\": \"Verfügbar: %d\",\n  \"gui.refinedstorage.crafting_preview.missing\": \"Fehlt: %d\",\n  \"gui.refinedstorage.crafting_preview.error\": \"Anfrage fehlgeschlagen\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.0\": \"Eine benötigte Resource braucht\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.1\": \"sich selbst.\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.2\": \"Entferne diese Vorlage um sicherzugehen\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.3\": \"dass sie nicht zur Herstellung verwendet wird.\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.4\": \"Fehlerhafte Vorlage:\",\n  \"gui.refinedstorage.crafting_preview.error.too_complex.0\": \"Die Berechnung der Fertigung war zu komplex\",\n  \"gui.refinedstorage.crafting_preview.error.too_complex.1\": \"und wurde angehalten um Serverleistung zu sparen.\",\n  \"gui.refinedstorage.security_manager\": \"Sicherheitsmanager\",\n  \"gui.refinedstorage.security_manager.configure\": \"Konfiguriere\",\n  \"gui.refinedstorage.security_manager.permission.0\": \"Einfügen\",\n  \"gui.refinedstorage.security_manager.permission.0.tooltip\": \"Items in das Netzwerk einfügen\",\n  \"gui.refinedstorage.security_manager.permission.1\": \"Extrahieren\",\n  \"gui.refinedstorage.security_manager.permission.1.tooltip\": \"Items aus dem Netz herausholen\",\n  \"gui.refinedstorage.security_manager.permission.2\": \"Automatisches Herstellen\",\n  \"gui.refinedstorage.security_manager.permission.2.tooltip\": \"Fertigungsprozesse starten, abbrechen und überwachen\",\n  \"gui.refinedstorage.security_manager.permission.3\": \"Modifizieren\",\n  \"gui.refinedstorage.security_manager.permission.3.tooltip\": \"Auf Block GUIs zugreifen\",\n  \"gui.refinedstorage.security_manager.permission.4\": \"Bauen\",\n  \"gui.refinedstorage.security_manager.permission.4.tooltip\": \"Geräte zum Netzwerk hinzufügen oder entfernen\",\n  \"gui.refinedstorage.security_manager.permission.5\": \"Sicherheit\",\n  \"gui.refinedstorage.security_manager.permission.5.tooltip\": \"Sicherheitseinstellungen ändern\",\n  \"gui.refinedstorage.storage_monitor\": \"Lagermonitor\",\n  \"gui.refinedstorage.crafter_manager\": \"Vorlagenmanager\",\n\n  \"misc.refinedstorage.energy_stored\": \"%d / %d FE\",\n  \"misc.refinedstorage.energy_usage\": \"Verbrauch: %d FE/t\",\n  \"misc.refinedstorage.energy_usage_minimal\": \"%d FE/t\",\n\n  \"misc.refinedstorage.storage.stored\": \"Belegt: %s\",\n  \"misc.refinedstorage.storage.stored_capacity\": \"Belegt: %s / %s\",\n  \"misc.refinedstorage.storage.stored_minimal\": \"%s\",\n  \"misc.refinedstorage.storage.stored_capacity_minimal\": \"%s / %s\",\n  \"misc.refinedstorage.storage.full\": \"%d%% belegt\",\n\n  \"misc.refinedstorage.network_item.tooltip\": \"Verbungen mit %d, %d, %d.\",\n  \"misc.refinedstorage.network_item.out_of_range\": \"Kein Funksender in Reichweite\",\n  \"misc.refinedstorage.network_item.not_found\": \"Kontrollblock nicht gefunden.\",\n\n  \"misc.refinedstorage.network_card.tooltip\": \"Verbunden mit %d, %d, %d in %s.\",\n\n  \"misc.refinedstorage.pattern.inputs\": \"Ausgangsmaterialien\",\n  \"misc.refinedstorage.pattern.outputs\": \"Ergebnis\",\n  \"misc.refinedstorage.pattern.invalid\": \"Ungültige Vorlage\",\n\n  \"misc.refinedstorage.security.no_permission\": \"Du hast keine Berechtigung dafür.\",\n\n  \"misc.refinedstorage.start\": \"Start\",\n  \"misc.refinedstorage.clear\": \"Löschen\",\n  \"misc.refinedstorage.set\": \"Setzen\",\n  \"misc.refinedstorage.cancel_all\": \"Alles Anhalten\",\n  \"misc.refinedstorage.priority\": \"Priorität\",\n  \"misc.refinedstorage.processing\": \"Verarbeitung\",\n\n  \"misc.refinedstorage.total\": \"%s insgesamt\",\n\n  \"misc.refinedstorage.last_modified.just_now\": \"Zuletzt geändert: Gerade eben von %s\",\n  \"misc.refinedstorage.last_modified.second\": \"Zuletzt geändert: Vor %d Sekunde von %s\",\n  \"misc.refinedstorage.last_modified.seconds\": \"Zuletzt geändert: Vor %d Sekunden von %s\",\n  \"misc.refinedstorage.last_modified.minute\": \"Zuletzt geändert: Vor %d Minute von %s\",\n  \"misc.refinedstorage.last_modified.minutes\": \"Zuletzt geändert: Vor %d Minuten von %s\",\n  \"misc.refinedstorage.last_modified.hour\": \"Zuletzt geändert: Vor %d Stunde von %s\",\n  \"misc.refinedstorage.last_modified.hours\": \"Zuletzt geändert: Vor %d Stunden von %s\",\n  \"misc.refinedstorage.last_modified.day\": \"Zuletzt geändert: Vor %d Tag von %s\",\n  \"misc.refinedstorage.last_modified.days\": \"Zuletzt geändert: Vor %d Tagen von %s\",\n  \"misc.refinedstorage.last_modified.week\": \"Zuletzt geändert: Vor %d Woche von %s\",\n  \"misc.refinedstorage.last_modified.weeks\": \"Zuletzt geändert: Vor %d Wochen von %s\",\n  \"misc.refinedstorage.last_modified.year\": \"Zuletzt geändert: Vor %d Jahr von %s\",\n  \"misc.refinedstorage.last_modified.years\": \"Zuletzt geändert: Vor %d Jahren von %s\",\n\n  \"sidebutton.refinedstorage.redstone_mode\": \"Redstone Modus\",\n  \"sidebutton.refinedstorage.redstone_mode.0\": \"Ignoriere Redstone Signal\",\n  \"sidebutton.refinedstorage.redstone_mode.1\": \"Nur mit Redstone Signal\",\n  \"sidebutton.refinedstorage.redstone_mode.2\": \"Nur ohne Redstone Signal\",\n\n  \"sidebutton.refinedstorage.crafter_mode\": \"Redstone Modus\",\n  \"sidebutton.refinedstorage.crafter_mode.0\": \"Ignoriere Redstone Signal\",\n  \"sidebutton.refinedstorage.crafter_mode.1\": \"Redstone Signal schaltet Autofertigung frei\",\n  \"sidebutton.refinedstorage.crafter_mode.2\": \"Redstone Signal sperrt Autofertigung\",\n  \"sidebutton.refinedstorage.crafter_mode.3\": \"Redstone Impuls fügt nächstes Rezept ein\",\n\n  \"sidebutton.refinedstorage.grid.view_type\": \"Anzeige\",\n  \"sidebutton.refinedstorage.grid.view_type.0\": \"Normal\",\n  \"sidebutton.refinedstorage.grid.view_type.1\": \"Keine Vorlagen\",\n  \"sidebutton.refinedstorage.grid.view_type.2\": \"Nur Vorlagen\",\n  \"sidebutton.refinedstorage.grid.sorting.direction\": \"Sortierung\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.0\": \"Aufsteigend\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.1\": \"Absteigend\",\n  \"sidebutton.refinedstorage.grid.sorting.type\": \"Sortieren Nach\",\n  \"sidebutton.refinedstorage.grid.sorting.type.0\": \"Menge\",\n  \"sidebutton.refinedstorage.grid.sorting.type.1\": \"Name\",\n  \"sidebutton.refinedstorage.grid.sorting.type.2\": \"ID\",\n  \"sidebutton.refinedstorage.grid.sorting.type.3\": \"InventoryTweaks\",\n  \"sidebutton.refinedstorage.grid.sorting.type.4\": \"Zuletzt Geändert\",\n  \"sidebutton.refinedstorage.grid.search_box_mode\": \"Suchleistenmodus\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.0\": \"Normal\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.1\": \"Normal (Autoselektiert)\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.2\": \"JEI synchronisiert\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.3\": \"JEI synchronisiert (Autoselektiert)\",\n  \"sidebutton.refinedstorage.grid.size\": \"Größe\",\n  \"sidebutton.refinedstorage.grid.size.0\": \"Auto\",\n  \"sidebutton.refinedstorage.grid.size.1\": \"Klein\",\n  \"sidebutton.refinedstorage.grid.size.2\": \"Mittel\",\n  \"sidebutton.refinedstorage.grid.size.3\": \"Groß\",\n\n  \"sidebutton.refinedstorage.mode\": \"Modus\",\n  \"sidebutton.refinedstorage.mode.whitelist\": \"Whitelist\",\n  \"sidebutton.refinedstorage.mode.blacklist\": \"Blacklist\",\n\n  \"sidebutton.refinedstorage.iomode\": \"IO Modus\",\n  \"sidebutton.refinedstorage.iomode.insert\": \"In Netzwerk importieren\",\n  \"sidebutton.refinedstorage.iomode.extract\": \"Aus Netzwerk exportieren\",\n\n  \"sidebutton.refinedstorage.type\": \"Typ\",\n  \"sidebutton.refinedstorage.type.0\": \"Items\",\n  \"sidebutton.refinedstorage.type.1\": \"Flüssigkeiten\",\n\n  \"sidebutton.refinedstorage.detector.mode\": \"Modus\",\n  \"sidebutton.refinedstorage.detector.mode.0\": \"Signal Wenn Weniger\",\n  \"sidebutton.refinedstorage.detector.mode.1\": \"Signal Wenn Gleich\",\n  \"sidebutton.refinedstorage.detector.mode.2\": \"Signal Wenn Mehr\",\n\n  \"sidebutton.refinedstorage.constructor.drop\": \"Blöcke fallen lassen anstatt zu platzieren\",\n\n  \"sidebutton.refinedstorage.destructor.pickup\": \"Items einsammeln anstatt abzubauen\",\n\n  \"sidebutton.refinedstorage.access_type\": \"Zugriffsmodus\",\n  \"sidebutton.refinedstorage.access_type.0\": \"Importieren und Exportieren\",\n  \"sidebutton.refinedstorage.access_type.1\": \"Nur Importieren\",\n  \"sidebutton.refinedstorage.access_type.2\": \"Nur Exportieren\",\n\n  \"block.refinedstorage.controller\": \"Kontrollblock\",\n  \"block.refinedstorage.controller.creative_controller\": \"Kreativ-Kontrollblock\",\n  \"block.refinedstorage.cable\": \"Kabel\",\n  \"block.refinedstorage.grid\": \"Konsole\",\n  \"block.refinedstorage.crafting_grid\": \"Fertigungskonsole\",\n  \"block.refinedstorage.pattern_grid\": \"Vorlagenkonsole\",\n  \"block.refinedstorage.fluid_grid\": \"Flüssigkeitskonsole\",\n  \"block.refinedstorage.disk_drive\": \"Laufwerk\",\n  \"block.refinedstorage.disk_manipulator\": \"Speichermanipulator\",\n  \"block.refinedstorage.external_storage\": \"Externer Speicher\",\n  \"block.refinedstorage.importer\": \"Importierer\",\n  \"block.refinedstorage.exporter\": \"Exportierer\",\n  \"block.refinedstorage.detector\": \"Detektor\",\n  \"block.refinedstorage.machine_casing\": \"Gehäuse\",\n  \"block.refinedstorage.destructor\": \"Destruktor\",\n  \"block.refinedstorage.constructor\": \"Konstruktor\",\n  \"block.refinedstorage.1k_storage_block\": \"1k Speicherblock\",\n  \"block.refinedstorage.4k_storage_block\": \"4k Speicherblock\",\n  \"block.refinedstorage.16k_storage_block\": \"16k Speicherblock\",\n  \"block.refinedstorage.64k_storage_block\": \"64k Speicherblock\",\n  \"block.refinedstorage.creative_storage_block\": \"Kreativ-Speicherblock\",\n  \"block.refinedstorage.relay\": \"Relais\",\n  \"block.refinedstorage.interface\": \"Schnittstelle\",\n  \"block.refinedstorage.crafting_monitor\": \"Fertigungsmonitor\",\n  \"block.refinedstorage.wireless_transmitter\": \"Funksender\",\n  \"block.refinedstorage.wireless_transmitter.tooltip\": \"Muss an %s platziert werden.\",\n  \"block.refinedstorage.crafter\": \"Fertiger\",\n  \"block.refinedstorage.network_receiver\": \"Netzwerkempfänger\",\n  \"block.refinedstorage.network_transmitter\": \"Netzwerksender\",\n  \"block.refinedstorage.fluid_interface\": \"Flüssigkeitsschnittstelle\",\n  \"block.refinedstorage.64k_fluid_storage_block\": \"64k Flüssigspeicherblock\",\n  \"block.refinedstorage.256k_fluid_storage_block\": \"256k Flüssigspeicherblock\",\n  \"block.refinedstorage.1024k_fluid_storage_block\": \"1024k Flüssigspeicherblock\",\n  \"block.refinedstorage.4096k_fluid_storage_block\": \"4096k Flüssigspeicherblock\",\n  \"block.refinedstorage.creative_fluid_storage_block\": \"Kreativ-Flüssigspeicherblock\",\n  \"block.refinedstorage.security_manager\": \"Sicherheitsmanager\",\n  \"block.refinedstorage.quartz_enriched_iron_block\": \"Quarzangereicherter Eisenblock\",\n  \"block.refinedstorage.storage_monitor\": \"Speichermonitor\",\n  \"block.refinedstorage.portable_grid\": \"Mobile Konsole\",\n  \"block.refinedstorage.creative_portable_grid\": \"Mobile Kreativ-Konsole\",\n  \"block.refinedstorage.portable_grid.tooltip\": \"Schleiche um das in der Welt zu platzieren\",\n  \"block.refinedstorage.crafter_manager\": \"Fertigungsmanager\",\n\n  \"item.refinedstorage.1k_storage_disk\": \"1k Speicherzelle\",\n  \"item.refinedstorage.4k_storage_disk\": \"4k Speicherzelle\",\n  \"item.refinedstorage.16k_storage_disk\": \"16k Speicherzelle\",\n  \"item.refinedstorage.64k_storage_disk\": \"64k Speicherzelle\",\n  \"item.refinedstorage.creative_storage_disk\": \"Kreativ-Speicherzelle\",\n  \"item.refinedstorage.64k_fluid_storage_disk\": \"64k Flüssigspeicherzelle\",\n  \"item.refinedstorage.256k_fluid_storage_disk\": \"256k Flüssigspeicherzelle\",\n  \"item.refinedstorage.1024k_fluid_storage_disk\": \"1024k Flüssigspeicherzelle\",\n  \"item.refinedstorage.4096k_fluid_storage_disk\": \"4096k Flüssigspeicherzelle\",\n  \"item.refinedstorage.creative_fluid_storage_disk\": \"Kreativ-Flüssigspeicherzelle\",\n  \"item.refinedstorage.wireless_grid\": \"Mobile Konsole\",\n  \"item.refinedstorage.creative_wireless_grid\": \"Mobile Kreativkonsole\",\n  \"item.refinedstorage.wireless_fluid_grid\": \"Mobile Flüssigkeitskonsole\",\n  \"item.refinedstorage.creative_wireless_fluid_grid\": \"Mobile Kreative-Flüssigkeitskonsole\",\n  \"item.refinedstorage.wireless_crafting_monitor\": \"Mobile Fertigungskonsole\",\n  \"item.refinedstorage.creative_wireless_crafting_monitor\": \"Mobile Kreativ-Fertigungskonsole\",\n  \"item.refinedstorage.quartz_enriched_iron\": \"Quarzangereichertes Eisen\",\n  \"item.refinedstorage.construction_core\": \"Konstruktionskern\",\n  \"item.refinedstorage.destruction_core\": \"Destruktionskern\",\n  \"item.refinedstorage.silicon\": \"Silizium\",\n  \"item.refinedstorage.raw_basic_processor\": \"Basisrohprozessor\",\n  \"item.refinedstorage.raw_improved_processor\": \"Verbesserter Rohprozessor\",\n  \"item.refinedstorage.raw_advanced_processor\": \"Fortschrittlicher Rohprozessor\",\n  \"item.refinedstorage.basic_processor\": \"Basisprozessor\",\n  \"item.refinedstorage.improved_processor\": \"Verbesserter Prozessor\",\n  \"item.refinedstorage.advanced_processor\": \"Fortschrittlicher Prozessor\",\n  \"item.refinedstorage.1k_storage_part\": \"1k Speicherkern\",\n  \"item.refinedstorage.4k_storage_part\": \"4k Speicherkern\",\n  \"item.refinedstorage.16k_storage_part\": \"16k Speicherkern\",\n  \"item.refinedstorage.64k_storage_part\": \"64k Speicherkern\",\n  \"item.refinedstorage.64k_fluid_storage_part\": \"64k Flüssigspeicherkern\",\n  \"item.refinedstorage.256k_fluid_storage_part\": \"256k Flüssigspeicherkern\",\n  \"item.refinedstorage.1024k_fluid_storage_part\": \"1024k Flüssigspeicherkern\",\n  \"item.refinedstorage.4096k_fluid_storage_part\": \"4096k Flüssigspeicherkern\",\n  \"item.refinedstorage.pattern\": \"Vorlage\",\n  \"item.refinedstorage.upgrade\": \"Upgrade\",\n  \"item.refinedstorage.range_upgrade\": \"Reichweitenupgrade\",\n  \"item.refinedstorage.speed_upgrade\": \"Geschwindigkeitsupgrade\",\n  \"item.refinedstorage.crafting_upgrade\": \"Fertigungsupgrade\",\n  \"item.refinedstorage.stack_upgrade\": \"Stapelupgrade\",\n  \"item.refinedstorage.silk_touch_upgrade\": \"Behutsamkeitsupgrade\",\n  \"item.refinedstorage.fortune_1_upgrade\": \"Glücksupgrade\",\n  \"item.refinedstorage.fortune_2_upgrade\": \"Glücksupgrade\",\n  \"item.refinedstorage.fortune_3_upgrade\": \"Glücksupgrade\",\n  \"item.refinedstorage.storage_housing\": \"Speichergehäuse\",\n  \"item.refinedstorage.filter\": \"Filter\",\n  \"item.refinedstorage.network_card\": \"Netzwerkkarte\",\n  \"item.refinedstorage.wrench\": \"Schraubenschlüssel\",\n  \"item.refinedstorage.security_card\": \"Sicherheitskarte\",\n  \"item.refinedstorage.security_card.owner\": \"Besitzer: %s\",\n  \"item.refinedstorage.processor_binding\": \"Prozessor Rohmaterial\",\n  \"commands.refinedstorage.disk.create.error.disk_not_found\": \"Speicherzelle %s konnte nicht gefunden werden.\",\n  \"commands.refinedstorage.disk.create.success\": \"Speicherzelle %s erfolgreich an %s gegeben.\",\n  \"advancements.refinedstorage.controlling.description\": \"Stelle einen Kontrollblock her\",\n  \"advancements.refinedstorage.connecting\": \"Verbinden\",\n  \"advancements.refinedstorage.connecting.description\": \"Platziere zwei Geräte nebeneinander oder verwende ein Kabel um sie zu verbinden\",\n  \"advancements.refinedstorage.conditional_connecting\": \"Bedingte Verbindung\",\n  \"advancements.refinedstorage.conditional_connecting.description\": \"Stelle ein Relais her, um eine Verbindung per Redstone zu steuern\",\n  \"advancements.refinedstorage.drives\": \"Laufwerke\",\n  \"advancements.refinedstorage.drives.description\": \"Stelle ein Laufwerk her um Speicherzellen zu lagern\",\n  \"advancements.refinedstorage.manipulating_disks\": \"Speichermanipulation\",\n  \"advancements.refinedstorage.manipulating_disks.description\": \"Benutze einen Speichermanipulator, um Speicherzellen einfach zu bearbeiten\",\n  \"advancements.refinedstorage.storing_items\": \"Items Speichern\",\n  \"advancements.refinedstorage.storing_items.description\": \"Stelle eine Speicherzelle her und lege sie in ein Laufwerk\",\n  \"advancements.refinedstorage.viewing_items\": \"Items Betrachten\",\n  \"advancements.refinedstorage.viewing_items.description\": \"Stelle eine Konsole her, um mit deinem Speicher zu interagieren\",\n  \"advancements.refinedstorage.portable_storage\": \"Tragbarer Speicher\",\n  \"advancements.refinedstorage.portable_storage.description\": \"Stelle einen Tragbaren Speicher her, um Items außerhalb eines Netzwerks zu speichern\",\n  \"advancements.refinedstorage.upgrading_your_grid\": \"Konsolenupgrade\",\n  \"advancements.refinedstorage.upgrading_your_grid.description\": \"Erweitere eine Konsole zu einer Fertigungskonsole um eine Werkbank in der Konsole zu erhalten\",\n  \"advancements.refinedstorage.storing_fluids\": \"Flüssigkeiten Speichern\",\n  \"advancements.refinedstorage.storing_fluids.description\": \"Stelle eine Flüssigspeicherzelle her und lege sie in ein Laufwerk\",\n  \"advancements.refinedstorage.viewing_fluids\": \"Flüssigkeiten Betrachten\",\n  \"advancements.refinedstorage.viewing_fluids.description\": \"Stelle eine Flüssigkeitskonsole her, um mit Flüssigkeiten in deinem Speicher zu interagieren\",\n  \"advancements.refinedstorage.better_than_a_barrel\": \"Besser als ein Fass\",\n  \"advancements.refinedstorage.better_than_a_barrel.description\": \"Stelle einen Speichermonitor her, um mit Items in deinem Speicher abzulegen oder herauszunehmen\",\n  \"advancements.refinedstorage.autocrafting\": \"Automatische Fertigung\",\n  \"advancements.refinedstorage.autocrafting.description\": \"Stelle eine Fertigungseinheit her\",\n  \"advancements.refinedstorage.pattern_creation\": \"Vorlagen\",\n  \"advancements.refinedstorage.pattern_creation.description\": \"Stelle eine Vorlage mit einer Vorlagenkonsole her\",\n  \"advancements.refinedstorage.monitoring\": \"Überwachung\",\n  \"advancements.refinedstorage.monitoring.description\": \"Überprüfe den Fortschritt deiner automatischen Fertigung mit einem Fertigungsmonitor\",\n  \"advancements.refinedstorage.managing_patterns\": \"Vorlagen Ordnen\",\n  \"advancements.refinedstorage.managing_patterns.description\": \"Stelle einen Vorlagenmanager her, um deine Vorlagen zu sortieren\",\n  \"advancements.refinedstorage.importing\": \"Importieren\",\n  \"advancements.refinedstorage.importing.description\": \"Importiere Items oder Flüssigkeiten mit einem Importierer\",\n  \"advancements.refinedstorage.destruction\": \"Zerstörung\",\n  \"advancements.refinedstorage.destruction.description\": \"Benutze einen Destruktor, um Blöcke oder Flüssigkeiten in den Speicher zu importieren\",\n  \"advancements.refinedstorage.exporting\": \"Exportieren\",\n  \"advancements.refinedstorage.exporting.description\": \"Exportiere Items oder Flüssigkeiten mit einem Exportierer\",\n  \"advancements.refinedstorage.construction\": \"Konstruktion\",\n  \"advancements.refinedstorage.construction.description\": \"Benutze einen Konstruktor, um Blöcke oder Flüssigkeitne aus dem Speicher zu exportieren\",\n  \"advancements.refinedstorage.security\": \"Sicherheit\",\n  \"advancements.refinedstorage.security.description\": \"Sichere dein Netzwerk mit einem Sicherheitsmanager und einer Sicherheitskarte\",\n  \"advancements.refinedstorage.wireless\": \"Drahtlos\",\n  \"advancements.refinedstorage.wireless.description\": \"Übertrage ein Netzwerksignal mit einem Funksender\",\n  \"advancements.refinedstorage.wireless_items\": \"Drahtlose Items\",\n  \"advancements.refinedstorage.wireless_items.description\": \"Interagiere mit deinen Items über eine mobile Konsole\",\n  \"advancements.refinedstorage.wireless_fluids\": \"Drahtlose Flüssigkeit\",\n  \"advancements.refinedstorage.wireless_fluids.description\": \"Interagiere mit deinem Flüssigkeitsspeicher über eine mobile Flüssigkeitskonsole\",\n  \"advancements.refinedstorage.wireless_monitoring\": \"Drahtlose Überwachung\",\n  \"advancements.refinedstorage.wireless_monitoring.description\": \"Überprüfe drahtlos den Fertigungsfortschritt über einen mobilen Fertigungsmonitor\",\n  \"advancements.refinedstorage.no_cables_required\": \"Kabellos\",\n  \"advancements.refinedstorage.no_cables_required.description\": \"Füge neue Geräte deinem Netzwerk hinzu, indem du einen Netzwerkempfänger, einen Netzwerksender und eine Netzwerkkarte benutzt\",\n  \"advancements.refinedstorage.upgrading\": \"Upgrades\",\n  \"advancements.refinedstorage.upgrading.description\": \"Stelle ein beliebiges Upgrade her\",\n  \"advancements.refinedstorage.crafting_on_demand\": \"Fertigung auf Befehl\",\n  \"advancements.refinedstorage.crafting_on_demand.description\": \"Benutze ein Fertigungsupgrade in einer Schnittstelle, einem Exportierer oder einem Konstruktor um Items nach Bedarf herzustellen\",\n  \"advancements.refinedstorage.detecting\": \"Erfassung\",\n  \"advancements.refinedstorage.detecting.description\": \"Benutze einen Detektor um Items oder Flüssigkeiten in einem Netzwerk zu erfassen\",\n  \"advancements.refinedstorage.interface_to_the_world\": \"Schnittstelle zur Welt\",\n  \"advancements.refinedstorage.interface_to_the_world.description\": \"Benutze ein Interface, um gleichzeitig Items zu exportieren und zu importieren\",\n  \"advancements.refinedstorage.storing_externally\": \"Speicher auslagern\",\n  \"advancements.refinedstorage.storing_externally.description\": \"Benutze einen externen Speicher um externe Itemquellen wie zum Beispiel Kisten anzubinden\"\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/lang/en_us.json",
    "content": "{\n  \"itemGroup.refinedstorage\": \"Refined Storage\",\n  \"itemGroup.refinedstorage.covers\": \"Refined Storage Covers\",\n\n  \"key.refinedstorage.focusSearchBar\": \"Focus Grid Search Bar\",\n  \"key.refinedstorage.clearGridCraftingMatrix\": \"Clear Grid Crafting Matrix\",\n  \"key.refinedstorage.openWirelessGrid\": \"Open Wireless Grid\",\n  \"key.refinedstorage.openWirelessFluidGrid\": \"Open Wireless Fluid Grid\",\n  \"key.refinedstorage.openPortableGrid\": \"Open Portable Grid\",\n  \"key.refinedstorage.openWirelessCraftingMonitor\": \"Open Wireless Crafting Monitor\",\n\n  \"gui.refinedstorage.controller\": \"Controller\",\n  \"gui.refinedstorage.creative_controller\": \"Creative Controller\",\n  \"gui.refinedstorage.grid\": \"Grid\",\n  \"gui.refinedstorage.grid.craft\": \"Craft\",\n  \"gui.refinedstorage.crafting_grid\": \"Crafting Grid\",\n  \"gui.refinedstorage.pattern_grid\": \"Pattern Grid\",\n  \"gui.refinedstorage.grid.pattern_create\": \"Create\",\n  \"gui.refinedstorage.fluid_grid\": \"Fluid Grid\",\n  \"gui.refinedstorage.portable_grid\": \"Portable Grid\",\n  \"gui.refinedstorage.item_amount\": \"Item amount\",\n  \"gui.refinedstorage.fluid_amount\": \"Fluid amount in mB\",\n  \"gui.refinedstorage.disk_drive\": \"Disk Drive\",\n  \"gui.refinedstorage.disk_drive.disks\": \"Disks\",\n  \"gui.refinedstorage.disk_manipulator\": \"Disk Manipulator\",\n  \"gui.refinedstorage.disk_manipulator.in\": \"In\",\n  \"gui.refinedstorage.disk_manipulator.out\": \"Out\",\n  \"gui.refinedstorage.external_storage\": \"External Storage\",\n  \"gui.refinedstorage.importer\": \"Importer\",\n  \"gui.refinedstorage.exporter\": \"Exporter\",\n  \"gui.refinedstorage.detector\": \"Detector\",\n  \"gui.refinedstorage.destructor\": \"Destructor\",\n  \"gui.refinedstorage.constructor\": \"Constructor\",\n  \"gui.refinedstorage.relay\": \"Relay\",\n  \"gui.refinedstorage.interface.import\": \"Interface Import\",\n  \"gui.refinedstorage.interface.export\": \"Interface Export\",\n  \"gui.refinedstorage.crafting_monitor\": \"Crafting Monitor\",\n  \"gui.refinedstorage.wireless_crafting_monitor\": \"Wireless Crafting Monitor\",\n  \"gui.refinedstorage.crafting_monitor.tooltip.requested\": \"%d requested\",\n  \"gui.refinedstorage.crafting_monitor.stored\": \"Stored: %d\",\n  \"gui.refinedstorage.crafting_monitor.missing\": \"Missing: %d\",\n  \"gui.refinedstorage.crafting_monitor.processing\": \"Processing: %d\",\n  \"gui.refinedstorage.crafting_monitor.scheduled\": \"Scheduled: %d\",\n  \"gui.refinedstorage.crafting_monitor.crafting\": \"Crafting: %d\",\n  \"gui.refinedstorage.crafting_monitor.machine_does_not_accept_item\": \"Machine doesn't accept item\",\n  \"gui.refinedstorage.crafting_monitor.machine_does_not_accept_fluid\": \"Machine doesn't accept fluid\",\n  \"gui.refinedstorage.crafting_monitor.machine_none\": \"No machine found\",\n  \"gui.refinedstorage.crafting_monitor.crafter_is_locked\": \"Crafter is locked\",\n  \"gui.refinedstorage.wireless_transmitter\": \"Wireless Transmitter\",\n  \"gui.refinedstorage.wireless_transmitter.distance\": \"%d block(s)\",\n  \"gui.refinedstorage.crafter\": \"Crafter\",\n  \"gui.refinedstorage.filter\": \"Filter\",\n  \"gui.refinedstorage.filter.compare_nbt\": \"NBT\",\n  \"gui.refinedstorage.filter.mod_filter\": \"Mod filter\",\n  \"gui.refinedstorage.network_transmitter\": \"Network Transmitter\",\n  \"gui.refinedstorage.network_transmitter.distance\": \"%d block(s)\",\n  \"gui.refinedstorage.network_transmitter.missing_card\": \"Missing Network Card\",\n  \"gui.refinedstorage.fluid_interface\": \"Fluid Interface\",\n  \"gui.refinedstorage.fluid_interface.in\": \"In\",\n  \"gui.refinedstorage.fluid_interface.out\": \"Out\",\n  \"gui.refinedstorage.crafting_preview\": \"Crafting Preview\",\n  \"gui.refinedstorage.crafting_preview.to_craft\": \"To craft: %d\",\n  \"gui.refinedstorage.crafting_preview.available\": \"Available: %d\",\n  \"gui.refinedstorage.crafting_preview.missing\": \"Missing: %d\",\n  \"gui.refinedstorage.crafting_preview.error\": \"Request failed\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.0\": \"One of the crafting ingredients ended up needing\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.1\": \"itself.\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.2\": \"You need to remove the pattern or make sure\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.3\": \"the pattern is not used during crafting.\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.4\": \"Offending pattern:\",\n  \"gui.refinedstorage.crafting_preview.error.too_complex.0\": \"The crafting task calculation was too complex\",\n  \"gui.refinedstorage.crafting_preview.error.too_complex.1\": \"and was stopped to avoid server strain.\",\n  \"gui.refinedstorage.security_manager\": \"Security Manager\",\n  \"gui.refinedstorage.security_manager.configure\": \"Configure\",\n  \"gui.refinedstorage.security_manager.permission.0\": \"Insert\",\n  \"gui.refinedstorage.security_manager.permission.0.tooltip\": \"Inserting items or fluids to the network\",\n  \"gui.refinedstorage.security_manager.permission.1\": \"Extract\",\n  \"gui.refinedstorage.security_manager.permission.1.tooltip\": \"Extracting items or fluids from the network\",\n  \"gui.refinedstorage.security_manager.permission.2\": \"Autocrafting\",\n  \"gui.refinedstorage.security_manager.permission.2.tooltip\": \"Starting, cancelling and viewing crafting tasks\",\n  \"gui.refinedstorage.security_manager.permission.3\": \"Modify\",\n  \"gui.refinedstorage.security_manager.permission.3.tooltip\": \"Opening blocks\",\n  \"gui.refinedstorage.security_manager.permission.4\": \"Build\",\n  \"gui.refinedstorage.security_manager.permission.4.tooltip\": \"Adding or removing devices to or from the network\",\n  \"gui.refinedstorage.security_manager.permission.5\": \"Security\",\n  \"gui.refinedstorage.security_manager.permission.5.tooltip\": \"Ability to change security options\",\n  \"gui.refinedstorage.storage_monitor\": \"Storage Monitor\",\n  \"gui.refinedstorage.crafter_manager\": \"Crafter Manager\",\n  \"gui.refinedstorage.alternatives\": \"Alternatives\",\n  \"gui.refinedstorage.alternatives.apply\": \"Apply\",\n  \"gui.refinedstorage.jei.transfer.autocrafting_available\": \"Autocrafting available\",\n  \"gui.refinedstorage.jei.transfer.request_autocrafting\": \"CTRL + CLICK to request autocrafting\",\n  \"gui.refinedstorage.jei.transfer.request_autocrafting_mac\": \"CMD + CLICK to request autocrafting\",\n  \"misc.refinedstorage.energy_stored\": \"%d / %d FE\",\n  \"misc.refinedstorage.energy_usage\": \"Usage: %d FE/t\",\n  \"misc.refinedstorage.energy_usage_minimal\": \"%d FE/t\",\n  \"misc.refinedstorage.storage.stored\": \"Stored: %s\",\n  \"misc.refinedstorage.storage.stored_capacity\": \"Stored: %s / %s\",\n  \"misc.refinedstorage.storage.stored_minimal\": \"%s\",\n  \"misc.refinedstorage.storage.stored_capacity_minimal\": \"%s / %s\",\n  \"misc.refinedstorage.storage.full\": \"%d%% full\",\n  \"misc.refinedstorage.network_item.tooltip\": \"Linked to %d, %d, %d.\",\n  \"misc.refinedstorage.network_item.out_of_range\": \"There is no Wireless Transmitter in range.\",\n  \"misc.refinedstorage.network_item.not_found\": \"Network not found.\",\n  \"misc.refinedstorage.network_item.shortcut_not_found\": \"There isn't any %s in your inventory.\",\n  \"misc.refinedstorage.network_item.shortcut_duplicate\": \"There is more than one %s in your inventory.\",\n  \"misc.refinedstorage.network_item.out_of_energy\": \"The %s is out of energy.\",\n\n  \"misc.refinedstorage.network_card.tooltip\": \"Linked to %d, %d, %d in %s.\",\n\n  \"misc.refinedstorage.pattern.inputs\": \"Inputs\",\n  \"misc.refinedstorage.pattern.outputs\": \"Outputs\",\n  \"misc.refinedstorage.pattern.invalid\": \"Invalid pattern\",\n  \"misc.refinedstorage.pattern.exact\": \"Uses exact mode\",\n  \"misc.refinedstorage.pattern.allowed_item_tag\": \"Uses items from %s for %s\",\n  \"misc.refinedstorage.pattern.allowed_fluid_tag\": \"Uses fluids from %s for %s\",\n\n  \"misc.refinedstorage.pattern.error.processing_no_outputs\": \"Processing pattern has no outputs\",\n  \"misc.refinedstorage.pattern.error.no_output\": \"Recipe has no output\",\n  \"misc.refinedstorage.pattern.error.recipe_does_not_exist\": \"Recipe doesn't exist\",\n  \"misc.refinedstorage.pattern.error.tag_no_longer_applicable\": \"Tag %s is no longer applicable for %s\",\n  \"misc.refinedstorage.security.no_permission\": \"You have no permission to perform that action.\",\n  \"misc.refinedstorage.start\": \"Start\",\n  \"misc.refinedstorage.clear\": \"Clear\",\n  \"misc.refinedstorage.set\": \"Set\",\n  \"misc.refinedstorage.cancel_all\": \"Cancel All\",\n  \"misc.refinedstorage.priority\": \"Priority\",\n  \"misc.refinedstorage.exact\": \"Exact\",\n  \"misc.refinedstorage.processing\": \"Processing\",\n  \"misc.refinedstorage.fluidmode\": \"Fluids\",\n  \"misc.refinedstorage.total\": \"%s total\",\n  \"misc.refinedstorage.last_modified.just_now\": \"Last modified just now by %s\",\n  \"misc.refinedstorage.last_modified.second\": \"Last modified %d second ago by %s\",\n  \"misc.refinedstorage.last_modified.seconds\": \"Last modified %d seconds ago by %s\",\n  \"misc.refinedstorage.last_modified.minute\": \"Last modified %d minute ago by %s\",\n  \"misc.refinedstorage.last_modified.minutes\": \"Last modified %d minutes ago by %s\",\n  \"misc.refinedstorage.last_modified.hour\": \"Last modified %d hour ago by %s\",\n  \"misc.refinedstorage.last_modified.hours\": \"Last modified %d hours ago by %s\",\n  \"misc.refinedstorage.last_modified.day\": \"Last modified %d day ago by %s\",\n  \"misc.refinedstorage.last_modified.days\": \"Last modified %d days ago by %s\",\n  \"misc.refinedstorage.last_modified.week\": \"Last modified %d week ago by %s\",\n  \"misc.refinedstorage.last_modified.weeks\": \"Last modified %d weeks ago by %s\",\n  \"misc.refinedstorage.last_modified.year\": \"Last modified %d year ago by %s\",\n  \"misc.refinedstorage.last_modified.years\": \"Last modified %d years ago by %s\",\n\n  \"sidebutton.refinedstorage.exact_mode\": \"Exact mode\",\n  \"sidebutton.refinedstorage.exact_mode.on\": \"On\",\n  \"sidebutton.refinedstorage.exact_mode.off\": \"Off\",\n\n  \"sidebutton.refinedstorage.redstone_mode\": \"Redstone mode\",\n  \"sidebutton.refinedstorage.redstone_mode.0\": \"Ignore redstone signal\",\n  \"sidebutton.refinedstorage.redstone_mode.1\": \"Only work with redstone signal\",\n  \"sidebutton.refinedstorage.redstone_mode.2\": \"Only work without redstone signal\",\n\n  \"sidebutton.refinedstorage.crafter_mode\": \"Crafter mode\",\n  \"sidebutton.refinedstorage.crafter_mode.0\": \"Ignore redstone signal\",\n  \"sidebutton.refinedstorage.crafter_mode.1\": \"Redstone signal unlocks autocrafting\",\n  \"sidebutton.refinedstorage.crafter_mode.2\": \"Redstone signal locks autocrafting\",\n  \"sidebutton.refinedstorage.crafter_mode.3\": \"Redstone pulse inserts next set\",\n\n  \"sidebutton.refinedstorage.grid.view_type\": \"Display\",\n  \"sidebutton.refinedstorage.grid.view_type.0\": \"Normal\",\n  \"sidebutton.refinedstorage.grid.view_type.1\": \"No craftables\",\n  \"sidebutton.refinedstorage.grid.view_type.2\": \"Only craftables\",\n  \"sidebutton.refinedstorage.grid.sorting.direction\": \"Sorting direction\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.0\": \"Ascending\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.1\": \"Descending\",\n  \"sidebutton.refinedstorage.grid.sorting.type\": \"Sorting type\",\n  \"sidebutton.refinedstorage.grid.sorting.type.0\": \"Quantity\",\n  \"sidebutton.refinedstorage.grid.sorting.type.1\": \"Name\",\n  \"sidebutton.refinedstorage.grid.sorting.type.2\": \"ID\",\n  \"sidebutton.refinedstorage.grid.sorting.type.3\": \"InventoryTweaks\",\n  \"sidebutton.refinedstorage.grid.sorting.type.4\": \"Last modified\",\n  \"sidebutton.refinedstorage.grid.search_box_mode\": \"Search box mode\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.0\": \"Normal\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.1\": \"Normal (autoselected)\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.2\": \"JEI synchronized\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.3\": \"JEI synchronized (autoselected)\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.4\": \"JEI synchronized (two-way)\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.5\": \"JEI synchronized (two-way autoselected)\",\n  \"sidebutton.refinedstorage.grid.size\": \"Size\",\n  \"sidebutton.refinedstorage.grid.size.0\": \"Stretch\",\n  \"sidebutton.refinedstorage.grid.size.1\": \"Small\",\n  \"sidebutton.refinedstorage.grid.size.2\": \"Medium\",\n  \"sidebutton.refinedstorage.grid.size.3\": \"Large\",\n\n  \"sidebutton.refinedstorage.mode\": \"Mode\",\n  \"sidebutton.refinedstorage.mode.whitelist\": \"Whitelist\",\n  \"sidebutton.refinedstorage.mode.blacklist\": \"Blacklist\",\n\n  \"sidebutton.refinedstorage.iomode\": \"IO mode\",\n  \"sidebutton.refinedstorage.iomode.insert\": \"Insert into network\",\n  \"sidebutton.refinedstorage.iomode.extract\": \"Extract from network\",\n\n  \"sidebutton.refinedstorage.type\": \"Type\",\n  \"sidebutton.refinedstorage.type.0\": \"Items\",\n  \"sidebutton.refinedstorage.type.1\": \"Fluids\",\n\n  \"sidebutton.refinedstorage.detector.mode\": \"Mode\",\n  \"sidebutton.refinedstorage.detector.mode.0\": \"Emit signal when under the amount\",\n  \"sidebutton.refinedstorage.detector.mode.1\": \"Emit signal when on the amount\",\n  \"sidebutton.refinedstorage.detector.mode.2\": \"Emit signal when above the amount\",\n  \"sidebutton.refinedstorage.constructor.drop\": \"Drop blocks instead of placing\",\n  \"sidebutton.refinedstorage.destructor.pickup\": \"Pickup items instead of breaking\",\n  \"sidebutton.refinedstorage.access_type\": \"Access type\",\n  \"sidebutton.refinedstorage.access_type.0\": \"Insert and extract\",\n  \"sidebutton.refinedstorage.access_type.1\": \"Insert only\",\n  \"sidebutton.refinedstorage.access_type.2\": \"Extract only\",\n  \"block.refinedstorage.controller\": \"Controller\",\n  \"block.refinedstorage.creative_controller\": \"Creative Controller\",\n  \"block.refinedstorage.cable\": \"Cable\",\n  \"block.refinedstorage.grid\": \"Grid\",\n  \"block.refinedstorage.crafting_grid\": \"Crafting Grid\",\n  \"block.refinedstorage.pattern_grid\": \"Pattern Grid\",\n  \"block.refinedstorage.fluid_grid\": \"Fluid Grid\",\n  \"block.refinedstorage.disk_drive\": \"Disk Drive\",\n  \"block.refinedstorage.disk_manipulator\": \"Disk Manipulator\",\n  \"block.refinedstorage.external_storage\": \"External Storage\",\n  \"block.refinedstorage.importer\": \"Importer\",\n  \"block.refinedstorage.exporter\": \"Exporter\",\n  \"block.refinedstorage.detector\": \"Detector\",\n  \"block.refinedstorage.machine_casing\": \"Machine Casing\",\n  \"block.refinedstorage.destructor\": \"Destructor\",\n  \"block.refinedstorage.constructor\": \"Constructor\",\n  \"block.refinedstorage.1k_storage_block\": \"1k Storage Block\",\n  \"block.refinedstorage.4k_storage_block\": \"4k Storage Block\",\n  \"block.refinedstorage.16k_storage_block\": \"16k Storage Block\",\n  \"block.refinedstorage.64k_storage_block\": \"64k Storage Block\",\n  \"block.refinedstorage.creative_storage_block\": \"Creative Storage Block\",\n  \"block.refinedstorage.relay\": \"Relay\",\n  \"block.refinedstorage.interface\": \"Interface\",\n  \"block.refinedstorage.crafting_monitor\": \"Crafting Monitor\",\n  \"block.refinedstorage.wireless_transmitter\": \"Wireless Transmitter\",\n  \"block.refinedstorage.crafter\": \"Crafter\",\n  \"block.refinedstorage.network_receiver\": \"Network Receiver\",\n  \"block.refinedstorage.network_transmitter\": \"Network Transmitter\",\n  \"block.refinedstorage.fluid_interface\": \"Fluid Interface\",\n  \"block.refinedstorage.64k_fluid_storage_block\": \"64k Fluid Storage Block\",\n  \"block.refinedstorage.256k_fluid_storage_block\": \"256k Fluid Storage Block\",\n  \"block.refinedstorage.1024k_fluid_storage_block\": \"1024k Fluid Storage Block\",\n  \"block.refinedstorage.4096k_fluid_storage_block\": \"4096k Fluid Storage Block\",\n  \"block.refinedstorage.creative_fluid_storage_block\": \"Creative Fluid Storage Block\",\n  \"block.refinedstorage.security_manager\": \"Security Manager\",\n  \"block.refinedstorage.quartz_enriched_iron_block\": \"Block of Quartz Enriched Iron\",\n  \"block.refinedstorage.storage_monitor\": \"Storage Monitor\",\n  \"block.refinedstorage.portable_grid\": \"Portable Grid\",\n  \"block.refinedstorage.creative_portable_grid\": \"Creative Portable Grid\",\n  \"block.refinedstorage.portable_grid.tooltip\": \"Sneak to place in the world.\",\n  \"block.refinedstorage.crafter_manager\": \"Crafter Manager\",\n  \"item.refinedstorage.1k_storage_disk\": \"1k Storage Disk\",\n  \"item.refinedstorage.4k_storage_disk\": \"4k Storage Disk\",\n  \"item.refinedstorage.16k_storage_disk\": \"16k Storage Disk\",\n  \"item.refinedstorage.64k_storage_disk\": \"64k Storage Disk\",\n  \"item.refinedstorage.creative_storage_disk\": \"Creative Storage Disk\",\n  \"item.refinedstorage.64k_fluid_storage_disk\": \"64k Fluid Storage Disk\",\n  \"item.refinedstorage.256k_fluid_storage_disk\": \"256k Fluid Storage Disk\",\n  \"item.refinedstorage.1024k_fluid_storage_disk\": \"1024k Fluid Storage Disk\",\n  \"item.refinedstorage.4096k_fluid_storage_disk\": \"4096k Fluid Storage Disk\",\n  \"item.refinedstorage.creative_fluid_storage_disk\": \"Creative Fluid Storage Disk\",\n  \"item.refinedstorage.wireless_grid\": \"Wireless Grid\",\n  \"item.refinedstorage.creative_wireless_grid\": \"Creative Wireless Grid\",\n  \"item.refinedstorage.wireless_fluid_grid\": \"Wireless Fluid Grid\",\n  \"item.refinedstorage.creative_wireless_fluid_grid\": \"Creative Wireless Fluid Grid\",\n  \"item.refinedstorage.wireless_crafting_monitor\": \"Wireless Crafting Monitor\",\n  \"item.refinedstorage.creative_wireless_crafting_monitor\": \"Creative Wireless Crafting Monitor\",\n  \"item.refinedstorage.quartz_enriched_iron\": \"Quartz Enriched Iron\",\n  \"item.refinedstorage.construction_core\": \"Construction Core\",\n  \"item.refinedstorage.destruction_core\": \"Destruction Core\",\n  \"item.refinedstorage.silicon\": \"Silicon\",\n  \"item.refinedstorage.raw_basic_processor\": \"Raw Basic Processor\",\n  \"item.refinedstorage.raw_improved_processor\": \"Raw Improved Processor\",\n  \"item.refinedstorage.raw_advanced_processor\": \"Raw Advanced Processor\",\n  \"item.refinedstorage.basic_processor\": \"Basic Processor\",\n  \"item.refinedstorage.improved_processor\": \"Improved Processor\",\n  \"item.refinedstorage.advanced_processor\": \"Advanced Processor\",\n  \"item.refinedstorage.1k_storage_part\": \"1k Storage Part\",\n  \"item.refinedstorage.4k_storage_part\": \"4k Storage Part\",\n  \"item.refinedstorage.16k_storage_part\": \"16k Storage Part\",\n  \"item.refinedstorage.64k_storage_part\": \"64k Storage Part\",\n  \"item.refinedstorage.64k_fluid_storage_part\": \"64k Fluid Storage Part\",\n  \"item.refinedstorage.256k_fluid_storage_part\": \"256k Fluid Storage Part\",\n  \"item.refinedstorage.1024k_fluid_storage_part\": \"1024k Fluid Storage Part\",\n  \"item.refinedstorage.4096k_fluid_storage_part\": \"4096k Fluid Storage Part\",\n  \"item.refinedstorage.pattern\": \"Pattern\",\n  \"item.refinedstorage.upgrade\": \"Upgrade\",\n  \"item.refinedstorage.range_upgrade\": \"Range Upgrade\",\n  \"item.refinedstorage.speed_upgrade\": \"Speed Upgrade\",\n  \"item.refinedstorage.crafting_upgrade\": \"Crafting Upgrade\",\n  \"item.refinedstorage.stack_upgrade\": \"Stack Upgrade\",\n  \"item.refinedstorage.silk_touch_upgrade\": \"Silk Touch Upgrade\",\n  \"item.refinedstorage.fortune_1_upgrade\": \"Fortune Upgrade\",\n  \"item.refinedstorage.fortune_2_upgrade\": \"Fortune Upgrade\",\n  \"item.refinedstorage.fortune_3_upgrade\": \"Fortune Upgrade\",\n  \"item.refinedstorage.regulator_upgrade\": \"Regulator Upgrade\",\n  \"item.refinedstorage.storage_housing\": \"Storage Housing\",\n  \"item.refinedstorage.filter\": \"Filter\",\n  \"item.refinedstorage.network_card\": \"Network Card\",\n  \"item.refinedstorage.wrench\": \"Wrench\",\n  \"item.refinedstorage.security_card\": \"Security Card\",\n  \"item.refinedstorage.security_card.owner\": \"Bound to: %s\",\n  \"item.refinedstorage.processor_binding\": \"Processor Binding\",\n  \"item.refinedstorage.cover\": \"Cover\",\n  \"item.refinedstorage.hollow_cover\": \"Hollow Cover\",\n  \"commands.refinedstorage.disk.create.error.disk_not_found\": \"Disk %s was not found.\",\n  \"commands.refinedstorage.disk.create.success\": \"Successfully gave disk %s to %s.\",\n  \"commands.refinedstorage.network.list.pos\": \"Network at X: %d, Y: %d, Z: %d\",\n  \"commands.refinedstorage.network.list.tick_times\": \"Mean tick time: %s ms. Mean TPS: %s\",\n  \"commands.refinedstorage.network.list.autocrafting_tasks\": \"%s tasks\",\n  \"commands.refinedstorage.network.list.nodes\": \"%s nodes\",\n  \"commands.refinedstorage.network.list.energy_usage\": \"Energy usage: %s\",\n  \"commands.refinedstorage.network.get.error.not_found\": \"Network not found.\",\n  \"commands.refinedstorage.network.autocrafting.get.error.not_found\": \"Task not found.\",\n  \"commands.refinedstorage.network.autocrafting.cancel.single\": \"Cancelled %d task.\",\n  \"commands.refinedstorage.network.autocrafting.cancel.multiple\": \"Cancelled %d tasks.\",\n  \"advancements.refinedstorage.controlling.description\": \"Craft a Controller\",\n  \"advancements.refinedstorage.connecting\": \"Connecting\",\n  \"advancements.refinedstorage.connecting.description\": \"You can place all the devices next to each other to connect them up, or, use Cable\",\n  \"advancements.refinedstorage.conditional_connecting\": \"Conditional connecting\",\n  \"advancements.refinedstorage.conditional_connecting.description\": \"Craft a Relay to control if a network signal can pass with redstone\",\n  \"advancements.refinedstorage.drives\": \"Drives\",\n  \"advancements.refinedstorage.drives.description\": \"Craft a Disk Drive to be able to store your disks\",\n  \"advancements.refinedstorage.manipulating_disks\": \"Manipulating disks\",\n  \"advancements.refinedstorage.manipulating_disks.description\": \"Use a Disk Manipulator to easily modify contents of disks\",\n  \"advancements.refinedstorage.storing_items\": \"Storing items\",\n  \"advancements.refinedstorage.storing_items.description\": \"Craft a Storage Disk and put it in your Disk Drive\",\n  \"advancements.refinedstorage.viewing_items\": \"Viewing items\",\n  \"advancements.refinedstorage.viewing_items.description\": \"Craft a Grid to interact with your item storage\",\n  \"advancements.refinedstorage.portable_storage\": \"Portable storage\",\n  \"advancements.refinedstorage.portable_storage.description\": \"Craft a Portable Grid to access items and fluids in disks without being in a network\",\n  \"advancements.refinedstorage.upgrading_your_grid\": \"Upgrading your Grid\",\n  \"advancements.refinedstorage.upgrading_your_grid.description\": \"Upgrade your Grid to a Crafting Grid to get crafting abilities in your Grid\",\n  \"advancements.refinedstorage.storing_fluids\": \"Storing fluids\",\n  \"advancements.refinedstorage.storing_fluids.description\": \"Craft a Fluid Storage Disk and put it in your Disk Drive\",\n  \"advancements.refinedstorage.viewing_fluids\": \"Viewing fluids\",\n  \"advancements.refinedstorage.viewing_fluids.description\": \"Craft a Fluid Grid to interact with your fluid storage\",\n  \"advancements.refinedstorage.better_than_a_barrel\": \"Better than a barrel\",\n  \"advancements.refinedstorage.better_than_a_barrel.description\": \"Craft a Storage Monitor to view, insert or extract items of a network\",\n  \"advancements.refinedstorage.autocrafting\": \"Autocrafting\",\n  \"advancements.refinedstorage.autocrafting.description\": \"Craft a Crafter\",\n  \"advancements.refinedstorage.pattern_creation\": \"Pattern creation\",\n  \"advancements.refinedstorage.pattern_creation.description\": \"Create patterns with a Pattern Grid and a Pattern\",\n  \"advancements.refinedstorage.monitoring\": \"Monitoring\",\n  \"advancements.refinedstorage.monitoring.description\": \"Check the status of your crafting tasks with a Crafting Monitor\",\n  \"advancements.refinedstorage.managing_patterns\": \"Managing patterns\",\n  \"advancements.refinedstorage.managing_patterns.description\": \"Craft a Crafter Manager to manage your patterns in a better way\",\n  \"advancements.refinedstorage.importing\": \"Importing\",\n  \"advancements.refinedstorage.importing.description\": \"Get items or fluids into the storage network with an Importer\",\n  \"advancements.refinedstorage.destruction\": \"Destruction\",\n  \"advancements.refinedstorage.destruction.description\": \"Get blocks or fluids into the storage network with a Destructor\",\n  \"advancements.refinedstorage.exporting\": \"Exporting\",\n  \"advancements.refinedstorage.exporting.description\": \"Get items or fluids out of the storage network with an Exporter\",\n  \"advancements.refinedstorage.construction\": \"Construction\",\n  \"advancements.refinedstorage.construction.description\": \"Get blocks or fluids out of the storage network with a Constructor\",\n  \"advancements.refinedstorage.security\": \"Security\",\n  \"advancements.refinedstorage.security.description\": \"Secure your network with a Security Manager and a Security Card\",\n  \"advancements.refinedstorage.wireless\": \"Wireless\",\n  \"advancements.refinedstorage.wireless.description\": \"Transmit a network signal with a Wireless Transmitter\",\n  \"advancements.refinedstorage.wireless_items\": \"Wireless items\",\n  \"advancements.refinedstorage.wireless_items.description\": \"Interact with your item storage wirelessly with a Wireless Grid\",\n  \"advancements.refinedstorage.wireless_fluids\": \"Wireless fluids\",\n  \"advancements.refinedstorage.wireless_fluids.description\": \"Interact with your fluid storage wirelessly with a Wireless Fluid Grid\",\n  \"advancements.refinedstorage.wireless_monitoring\": \"Wireless monitoring\",\n  \"advancements.refinedstorage.wireless_monitoring.description\": \"Check the status of your crafting tasks wirelessly with a Wireless Crafting Monitor\",\n  \"advancements.refinedstorage.no_cables_required\": \"No cables required\",\n  \"advancements.refinedstorage.no_cables_required.description\": \"Add extra components to your network without using cables by using a Network Transmitter, Network Receiver and Network Card\",\n  \"advancements.refinedstorage.upgrading\": \"Upgrading\",\n  \"advancements.refinedstorage.upgrading.description\": \"Craft an Upgrade to improve various devices\",\n  \"advancements.refinedstorage.crafting_on_demand\": \"Crafting on demand\",\n  \"advancements.refinedstorage.crafting_on_demand.description\": \"Use a Crafting Upgrade in a Interface, Exporter or Constructor to craft items and blocks on demand\",\n  \"advancements.refinedstorage.detecting\": \"Detecting\",\n  \"advancements.refinedstorage.detecting.description\": \"Detect items or fluids in the network with the Detector\",\n  \"advancements.refinedstorage.interface_to_the_world\": \"Interface to the world\",\n  \"advancements.refinedstorage.interface_to_the_world.description\": \"Export and import items at the same time with an Interface\",\n  \"advancements.refinedstorage.storing_externally\": \"Storing externally\",\n  \"advancements.refinedstorage.storing_externally.description\": \"Use an External Storage to provide the network with storage from an external block like a chest\"\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/lang/es_es.json",
    "content": "﻿{\n  \"itemGroup.refinedstorage\": \"Refined Storage\",\n\n  \"key.refinedstorage.focusSearchBar\": \"Panel de búsqueda centrada\",\n  \"key.refinedstorage.clearGridCraftingMatrix\": \"Limpiar matriz del panel de fabricación\",\n\n  \"gui.refinedstorage.controller\": \"Controlador\",\n  \"gui.refinedstorage.creative_controller\": \"Controlador creativo\",\n  \"gui.refinedstorage.grid\": \"Panel\",\n  \"gui.refinedstorage.grid.craft\": \"Fabricar\",\n  \"gui.refinedstorage.crafting_grid\": \"Panel de fabricación\",\n  \"gui.refinedstorage.pattern_grid\": \"Panel de patrones\",\n  \"gui.refinedstorage.grid.pattern_create\": \"Crear patrón\",\n  \"gui.refinedstorage.fluid_grid\": \"Panel de fluidos\",\n  \"gui.refinedstorage.portable_grid\": \"Panel portátil\",\n  \"gui.refinedstorage.disk_drive\": \"Deposito\",\n  \"gui.refinedstorage.disk_drive.disks\": \"Depósitos\",\n  \"gui.refinedstorage.external_storage\": \"Almacén externo\",\n  \"gui.refinedstorage.importer\": \"Importador\",\n  \"gui.refinedstorage.exporter\": \"Exportador\",\n  \"gui.refinedstorage.detector\": \"Detector\",\n  \"gui.refinedstorage.destructor\": \"Destructor\",\n  \"gui.refinedstorage.constructor\": \"Constructor\",\n  \"gui.refinedstorage.relay\": \"Relé\",\n  \"gui.refinedstorage.interface.import\": \"Interfaz de entrada\",\n  \"gui.refinedstorage.interface.export\": \"Interfaz de salida\",\n  \"gui.refinedstorage.crafting_monitor\": \"Monitor de fabricación\",\n  \"gui.refinedstorage.wireless_crafting_monitor\": \"Monitor remoto de fabricación\",\n  \"gui.refinedstorage.crafting_monitor.machine_none\": \"Maquina no hallada\",\n  \"gui.refinedstorage.wireless_transmitter\": \"Emisor inalámbrico\",\n  \"gui.refinedstorage.wireless_transmitter.distance\": \"%d bloque(s)\",\n  \"gui.refinedstorage.crafter\": \"Fabricador\",\n  \"gui.refinedstorage.filter\": \"Filtro\",\n  \"gui.refinedstorage.filter.compare_nbt\": \"NBT\",\n  \"gui.refinedstorage.filter.mod_filter\": \"Filtro de mods\",\n  \"gui.refinedstorage.network_transmitter\": \"Emisor de red\",\n  \"gui.refinedstorage.network_transmitter.distance\": \"%d bloque(s)\",\n  \"gui.refinedstorage.network_transmitter.missing_card\": \"Falta tarjeta de red\",\n  \"gui.refinedstorage.fluid_interface\": \"Interfaz de fluidos\",\n  \"gui.refinedstorage.fluid_interface.in\": \"Entrada\",\n  \"gui.refinedstorage.fluid_interface.out\": \"Salida\",\n  \"gui.refinedstorage.crafting_preview\": \"Avance de fabricación\",\n  \"gui.refinedstorage.crafting_preview.to_craft\": \"Para fabricar: %d\",\n  \"gui.refinedstorage.crafting_preview.available\": \"Disponible: %d\",\n  \"gui.refinedstorage.crafting_preview.missing\": \"Falta: %d\",\n  \"gui.refinedstorage.crafting_preview.error\": \"No puede fabricar\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.0\": \"Uno de los objetos de creación termino faltando\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.1\": \"sí mismo.\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.2\": \"Necesita remover el patrón o revisarlo\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.3\": \"el patrón no se usa para la fabricación.\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.4\": \"Patrón ofensivo:\",\n  \"gui.refinedstorage.security_manager\": \"Centro de seguridad\",\n  \"gui.refinedstorage.security_manager.configure\": \"Configurar\",\n  \"gui.refinedstorage.security_manager.permission.0\": \"Insertar\",\n  \"gui.refinedstorage.security_manager.permission.0.tooltip\": \"Insertar objetos a la red\",\n  \"gui.refinedstorage.security_manager.permission.1\": \"Extraer\",\n  \"gui.refinedstorage.security_manager.permission.1.tooltip\": \"Extraer objetos de la red\",\n  \"gui.refinedstorage.security_manager.permission.2\": \"Autofabricar\",\n  \"gui.refinedstorage.security_manager.permission.2.tooltip\": \"Comenzar, cancelar y ver tareas de fabricación\",\n  \"gui.refinedstorage.security_manager.permission.3\": \"Modificar\",\n  \"gui.refinedstorage.security_manager.permission.3.tooltip\": \"Abrir interfaz de bloque\",\n  \"gui.refinedstorage.security_manager.permission.4\": \"Construir\",\n  \"gui.refinedstorage.security_manager.permission.4.tooltip\": \"Añadir o remover disposotivos de o desde la red\",\n  \"gui.refinedstorage.security_manager.permission.5\": \"Seguridad\",\n  \"gui.refinedstorage.security_manager.permission.5.tooltip\": \"Abilidad de cambiar opciones de seguridad\",\n  \"gui.refinedstorage.storage_monitor\": \"Monitor de almacén\",\n\n  \"misc.refinedstorage.energy_stored\": \"%d / %d FE\",\n  \"misc.refinedstorage.energy_usage\": \"Uso: %d FE/t\",\n  \"misc.refinedstorage.energy_usage_minimal\": \"%d FE/t\",\n\n  \"misc.refinedstorage.storage.stored\": \"Guardado: %s\",\n  \"misc.refinedstorage.storage.stored_capacity\": \"Capacidad: %s / %s\",\n  \"misc.refinedstorage.storage.stored_minimal\": \"%s\",\n  \"misc.refinedstorage.storage.stored_capacity_minimal\": \"%s / %s\",\n  \"misc.refinedstorage.storage.full\": \"%d%% lleno\",\n\n  \"misc.refinedstorage.network_item.tooltip\": \"Enlazado a %d, %d, %d.\",\n  \"misc.refinedstorage.network_item.out_of_range\": \"No hay emisor de red en rango.\",\n  \"misc.refinedstorage.network_item.not_found\": \"No se encontró un controlador.\",\n\n  \"misc.refinedstorage.network_card.tooltip\": \"Enlazado a %d, %d, %d en %s.\",\n\n  \"misc.refinedstorage.pattern.inputs\": \"Entradas\",\n  \"misc.refinedstorage.pattern.outputs\": \"Salidas\",\n  \"misc.refinedstorage.pattern.invalid\": \"patrón invalido\",\n\n  \"misc.refinedstorage.security.no_permission\": \"No tienes permiso de realizar esa acción.\",\n\n  \"misc.refinedstorage.start\": \"Empezar\",\n  \"misc.refinedstorage.clear\": \"Limpiar\",\n  \"misc.refinedstorage.set\": \"Poner\",\n  \"misc.refinedstorage.cancel_all\": \"Cancelar todo\",\n  \"misc.refinedstorage.priority\": \"Prioridad\",\n  \"misc.refinedstorage.processing\": \"Procesándose\",\n  \"misc.refinedstorage.total\": \"%s total\",\n\n  \"misc.refinedstorage.last_modified.just_now\": \"Último cambio justo ahora por %s\",\n  \"misc.refinedstorage.last_modified.second\": \"Último cambio %d hace un segundo por %s\",\n  \"misc.refinedstorage.last_modified.seconds\": \"Último cambio %d hace unos segundos por %s\",\n  \"misc.refinedstorage.last_modified.minute\": \"Último cambio %d hace un minuto por %s\",\n  \"misc.refinedstorage.last_modified.minutes\": \"Último cambio %d hace unos minutos por %s\",\n  \"misc.refinedstorage.last_modified.hour\": \"Último cambio %d hace una hora por %s\",\n  \"misc.refinedstorage.last_modified.hours\": \"Último cambio %d hace unas horas por %s\",\n  \"misc.refinedstorage.last_modified.day\": \"Último cambio %d hace una día por %s\",\n  \"misc.refinedstorage.last_modified.days\": \"Último cambio %d hace unos días por %s\",\n  \"misc.refinedstorage.last_modified.week\": \"Último cambio %d hace una semana por %s\",\n  \"misc.refinedstorage.last_modified.weeks\": \"Último cambio %d hace semanas por %s\",\n  \"misc.refinedstorage.last_modified.year\": \"Último cambio %d hace un año por %s\",\n  \"misc.refinedstorage.last_modified.years\": \"Último cambio %d hace años por %s\",\n\n  \"sidebutton.refinedstorage.redstone_mode\": \"Modo de señal\",\n  \"sidebutton.refinedstorage.redstone_mode.0\": \"Ignorar señal de redstone\",\n  \"sidebutton.refinedstorage.redstone_mode.1\": \"Trabajar solo con señal de redstone\",\n  \"sidebutton.refinedstorage.redstone_mode.2\": \"Trabajar solo sin señal de redstone\",\n\n  \"sidebutton.refinedstorage.grid.view_type\": \"Pantalla\",\n  \"sidebutton.refinedstorage.grid.view_type.0\": \"Normal\",\n  \"sidebutton.refinedstorage.grid.view_type.1\": \"No fabricable\",\n  \"sidebutton.refinedstorage.grid.view_type.2\": \"Solo fabricable\",\n  \"sidebutton.refinedstorage.grid.sorting.direction\": \"Dirección de orden\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.0\": \"Ascendente\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.1\": \"Descendente\",\n  \"sidebutton.refinedstorage.grid.sorting.type\": \"Tipo de orden\",\n  \"sidebutton.refinedstorage.grid.sorting.type.0\": \"Cantidad\",\n  \"sidebutton.refinedstorage.grid.sorting.type.1\": \"Nombre\",\n  \"sidebutton.refinedstorage.grid.sorting.type.2\": \"ID\",\n  \"sidebutton.refinedstorage.grid.sorting.type.3\": \"InventoryTweaks\",\n  \"sidebutton.refinedstorage.grid.sorting.type.4\": \"Último cambio\",\n  \"sidebutton.refinedstorage.grid.search_box_mode\": \"Modo de caja de búsqueda\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.0\": \"Normal\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.1\": \"Normal (autoselección)\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.2\": \"Sincronizado con JEI\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.3\": \"Sincronizado con JEI (autoselección)\",\n  \"sidebutton.refinedstorage.grid.size\": \"Tamaño\",\n  \"sidebutton.refinedstorage.grid.size.0\": \"Tramo\",\n  \"sidebutton.refinedstorage.grid.size.1\": \"Pequeño\",\n  \"sidebutton.refinedstorage.grid.size.2\": \"Mediano\",\n  \"sidebutton.refinedstorage.grid.size.3\": \"Largo\",\n\n  \"sidebutton.refinedstorage.mode\": \"Modo\",\n  \"sidebutton.refinedstorage.mode.whitelist\": \"Permitido\",\n  \"sidebutton.refinedstorage.mode.blacklist\": \"No permitido\",\n\n  \"sidebutton.refinedstorage.iomode\": \"Modo de E/S\",\n  \"sidebutton.refinedstorage.iomode.insert\": \"Insertar a la red\",\n  \"sidebutton.refinedstorage.iomode.extract\": \"Extraer de la red\",\n\n  \"sidebutton.refinedstorage.type\": \"Tipo\",\n  \"sidebutton.refinedstorage.type.0\": \"Objetos\",\n  \"sidebutton.refinedstorage.type.1\": \"Fluidos\",\n\n  \"sidebutton.refinedstorage.detector.mode\": \"Modo\",\n  \"sidebutton.refinedstorage.detector.mode.0\": \"Emitir señal si hay menos de lo indicado\",\n  \"sidebutton.refinedstorage.detector.mode.1\": \"Emitir señal si la cantidad se alcanza\",\n  \"sidebutton.refinedstorage.detector.mode.2\": \"Emitir señal si esta más de lo indicado\",\n\n  \"sidebutton.refinedstorage.constructor.drop\": \"Soltar bloques en lugar de colocar\",\n\n  \"sidebutton.refinedstorage.destructor.pickup\": \"Recoger objetos en lugar de romper\",\n\n  \"sidebutton.refinedstorage.access_type\": \"Tipo de acceso\",\n  \"sidebutton.refinedstorage.access_type.0\": \"Insertar y extraer\",\n  \"sidebutton.refinedstorage.access_type.1\": \"Solo insertar\",\n  \"sidebutton.refinedstorage.access_type.2\": \"Solo extraer\",\n\n  \"block.refinedstorage.controller\": \"Controlador\",\n  \"block.refinedstorage.creative_controller\": \"Controlador creativo\",\n  \"block.refinedstorage.cable\": \"Cable\",\n  \"block.refinedstorage.grid\": \"Panel\",\n  \"block.refinedstorage.crafting_grid\": \"Panel de fabricación\",\n  \"block.refinedstorage.pattern_grid\": \"Panel de patrones\",\n  \"block.refinedstorage.fluid_grid\": \"Panel de fluidos\",\n  \"block.refinedstorage.disk_drive\": \"Almacén de discos\",\n  \"block.refinedstorage.disk_manipulator\": \"Manipulador de discos\",\n  \"block.refinedstorage.external_storage\": \"Almacén externo\",\n  \"block.refinedstorage.importer\": \"Importador\",\n  \"block.refinedstorage.exporter\": \"Exportador\",\n  \"block.refinedstorage.detector\": \"Detector\",\n  \"block.refinedstorage.machine_casing\": \"Estructura de maquina\",\n  \"block.refinedstorage.destructor\": \"Destructor\",\n  \"block.refinedstorage.constructor\": \"Constructor\",\n  \"block.refinedstorage.1k_storage_block\": \"Bloque de memoria de 1k\",\n  \"block.refinedstorage.4k_storage_block\": \"Bloque de memoria de 4k\",\n  \"block.refinedstorage.16k_storage_block\": \"Bloque de memoria de 16k\",\n  \"block.refinedstorage.64k_storage_block\": \"Bloque de memoria de 64k\",\n  \"block.refinedstorage.creative_storage_block\": \"Bloque de memoria creativo\",\n  \"block.refinedstorage.relay\": \"Relé\",\n  \"block.refinedstorage.interface\": \"Interfaz\",\n  \"block.refinedstorage.crafting_monitor\": \"Monitor de fabricación\",\n  \"block.refinedstorage.wireless_transmitter\": \"Transmisor inalámbrico\",\n  \"block.refinedstorage.wireless_transmitter.tooltip\": \"Necesita ser puesto en %s.\",\n  \"block.refinedstorage.crafter\": \"Fabricador\",\n  \"block.refinedstorage.network_receiver\": \"Receptor de red\",\n  \"block.refinedstorage.network_transmitter\": \"Transmisor de red\",\n  \"block.refinedstorage.fluid_interface\": \"Interfaz de fluidos\",\n  \"block.refinedstorage.64k_fluid_storage_block\": \"Bloque de memoria de fluidos de 64k\",\n  \"block.refinedstorage.256k_fluid_storage_block\": \"Bloque de memoria de fluidos de 256k\",\n  \"block.refinedstorage.1024k_fluid_storage_block\": \"Bloque de memoria de fluidos de 1024k\",\n  \"block.refinedstorage.4096k_fluid_storage_block\": \"Bloque de memoria de fluidos de 4096k\",\n  \"block.refinedstorage.creative_fluid_storage_block\": \"Bloque de memoria de fluidos creativo\",\n  \"block.refinedstorage.security_manager\": \"Centro de seguridad\",\n  \"block.refinedstorage.quartz_enriched_iron_block\": \"Bloque de hierro enriquecido con cuarzo\",\n  \"block.refinedstorage.storage_monitor\": \"Monitor de almacén\",\n  \"block.refinedstorage.portable_grid\": \"Panel portátil\",\n  \"block.refinedstorage.creative_portable_grid\": \"Panel portátil creativo\",\n  \"block.refinedstorage.portable_grid.tooltip\": \"Agáchate para colocarlo.\",\n\n  \"item.refinedstorage.1k_storage_disk\": \"Disco duro de 1k\",\n  \"item.refinedstorage.4k_storage_disk\": \"Disco duro de 4k\",\n  \"item.refinedstorage.16k_storage_disk\": \"Disco duro de 16k\",\n  \"item.refinedstorage.64k_storage_disk\": \"Disco duro de 64k\",\n  \"item.refinedstorage.creative_storage_disk\": \"Disco duro creativo\",\n  \"item.refinedstorage.64k_fluid_storage_disk\": \"Disco duro de fluidos de 64k\",\n  \"item.refinedstorage.256k_fluid_storage_disk\": \"Disco duro de fluidos de 256k\",\n  \"item.refinedstorage.1024k_fluid_storage_disk\": \"Disco duro de fluidos de 1024k\",\n  \"item.refinedstorage.4096k_fluid_storage_disk\": \"Disco duro de fluidos de 4096k\",\n  \"item.refinedstorage.creative_fluid_storage_disk\": \"Disco duro de fluidos creativo\",\n  \"item.refinedstorage.wireless_grid\": \"Panel inalámbrico\",\n  \"item.refinedstorage.creative_wireless_grid\": \"Panel inalámbrico creativo\",\n  \"item.refinedstorage.wireless_fluid_grid\": \"Panel de fluidos inalámbrico\",\n  \"item.refinedstorage.creative_wireless_fluid_grid\": \"Panel de fluidos inalámbrico creativo\",\n  \"item.refinedstorage.wireless_crafting_monitor\": \"Monitor de fabricación inalámbrico\",\n  \"item.refinedstorage.creative_wireless_crafting_monitor\": \"Monitor de fabricación inalámbrico creativo\",\n  \"item.refinedstorage.quartz_enriched_iron\": \"Hierro enriquecido con cuarzo\",\n  \"item.refinedstorage.construction_core\": \"Núcleo de construcción\",\n  \"item.refinedstorage.destruction_core\": \"Núcleo de destrucción\",\n  \"item.refinedstorage.silicon\": \"Silicio\",\n  \"item.refinedstorage.basic_processor\": \"Procesador básico\",\n  \"item.refinedstorage.improved_processor\": \"Procesador mejorado\",\n  \"item.refinedstorage.advanced_processor\": \"Procesador avanzado\",\n  \"item.refinedstorage.1k_storage_part\": \"Parte de memoria de 1k\",\n  \"item.refinedstorage.4k_storage_part\": \"Parte de memoria de 4k\",\n  \"item.refinedstorage.16k_storage_part\": \"Parte de memoria de 16k\",\n  \"item.refinedstorage.64k_storage_part\": \"Parte de memoria de 64k\",\n  \"item.refinedstorage.64k_fluid_storage_part\": \"Parte de memoria de fluidos de 64k\",\n  \"item.refinedstorage.256k_fluid_storage_part\": \"Parte de memoria de fluidos de 256k\",\n  \"item.refinedstorage.1024k_fluid_storage_part\": \"Parte de memoria de fluidos de 1024k\",\n  \"item.refinedstorage.4096k_fluid_storage_part\": \"Parte de memoria de fluidos de 4096k\",\n  \"item.refinedstorage.pattern\": \"Patrón\",\n  \"item.refinedstorage.upgrade\": \"Mejora\",\n  \"item.refinedstorage.range_upgrade\": \"Mejora de rango\",\n  \"item.refinedstorage.speed_upgrade\": \"Mejora de rapidez\",\n  \"item.refinedstorage.crafting_upgrade\": \"Mejora de fabricación\",\n  \"item.refinedstorage.stack_upgrade\": \"Mejora de apilación\",\n  \"item.refinedstorage.silk_touch_upgrade\": \"Mejora de toque de seda\",\n  \"item.refinedstorage.fortune_1_upgrade\": \"Mejora de fortuna\",\n  \"item.refinedstorage.fortune_2_upgrade\": \"Mejora de fortuna\",\n  \"item.refinedstorage.fortune_3_upgrade\": \"Mejora de fortuna\",\n  \"item.refinedstorage.storage_housing\": \"Carcasa\",\n  \"item.refinedstorage.filter\": \"Filtro\",\n  \"item.refinedstorage.network_card\": \"Tarjeta de red\",\n  \"item.refinedstorage.wrench\": \"Llave inglesa\",\n  \"item.refinedstorage.security_card\": \"Tarjeta de seguridad\",\n  \"item.refinedstorage.security_card.owner\": \"Designado a: %s\",\n\n  \"advancements.refinedstorage.controlling.description\": \"Haz un controlador\",\n  \"advancements.refinedstorage.connecting\": \"conectándose\",\n  \"advancements.refinedstorage.connecting.description\": \"Puedes poner todos los dispositivos juntos para conectarlos, o, usa cable\",\n  \"advancements.refinedstorage.conditional_connecting\": \"Conexión condicional\",\n  \"advancements.refinedstorage.conditional_connecting.description\": \"Haz un relé para controlar si señal de red pasa con redstone\",\n  \"advancements.refinedstorage.drives\": \"Almacén\",\n  \"advancements.refinedstorage.drives.description\": \"Haz un almacén de discos para almacenar tus discos\",\n  \"advancements.refinedstorage.manipulating_disks\": \"Manipulando discos\",\n  \"advancements.refinedstorage.manipulating_disks.description\": \"Use un manipulador de discos para modificar los datos en discos\",\n  \"advancements.refinedstorage.storing_items\": \"Almacenando objetos\",\n  \"advancements.refinedstorage.storing_items.description\": \"Haz un disco duro y colocalo en el almacén\",\n  \"advancements.refinedstorage.viewing_items\": \"Viendo objetos\",\n  \"advancements.refinedstorage.viewing_items.description\": \"Haz un panel para interactuar con tus objetos almacenados\",\n  \"advancements.refinedstorage.portable_storage\": \"Almacén portátil\",\n  \"advancements.refinedstorage.upgrading_your_grid\": \"Mejorando el panel\",\n  \"advancements.refinedstorage.upgrading_your_grid.description\": \"Mejora tu panel a uno de panel de fabricación para fabricar y ver objetos\",\n  \"advancements.refinedstorage.storing_fluids\": \"Guardando fluidos\",\n  \"advancements.refinedstorage.storing_fluids.description\": \"Haz un disco duro de fluidos y colocalo en el almacén de discos\",\n  \"advancements.refinedstorage.viewing_fluids\": \"Viendo flujo\",\n  \"advancements.refinedstorage.viewing_fluids.description\": \"Haz un panel de fluidos para interactuar con tu almacén de fluidos\",\n  \"advancements.refinedstorage.better_than_a_barrel\": \"Mejor que un barril\",\n  \"advancements.refinedstorage.better_than_a_barrel.description\": \"Haz un monitor de almacén para ver, insertar o extraer objetos de la red\",\n  \"advancements.refinedstorage.autocrafting\": \"Autofabricación\",\n  \"advancements.refinedstorage.autocrafting.description\": \"Fabrica un fabricador\",\n  \"advancements.refinedstorage.pattern_creation\": \"Creación de patrones\",\n  \"advancements.refinedstorage.pattern_creation.description\": \"Crea patrones usando un panel de patrones y un patrón\",\n  \"advancements.refinedstorage.monitoring\": \"Monitoreo\",\n  \"advancements.refinedstorage.monitoring.description\": \"Verifica el estado de las tareas de fabricación con un monitor de fabricación\",\n  \"advancements.refinedstorage.importing\": \"Importando\",\n  \"advancements.refinedstorage.importing.description\": \"Inserta objetos o fluidos a la red con un importador\",\n  \"advancements.refinedstorage.destruction\": \"Destrucción\",\n  \"advancements.refinedstorage.destruction.description\": \"Inserta bloques o fluidos a la red con un destructor\",\n  \"advancements.refinedstorage.exporting\": \"Exportando\",\n  \"advancements.refinedstorage.exporting.description\": \"Saca objetos o fluidos de la red con un exportador\",\n  \"advancements.refinedstorage.construction\": \"Construcción\",\n  \"advancements.refinedstorage.construction.description\": \"Saca bloques o fluidos de la red con un constructor\",\n  \"advancements.refinedstorage.security\": \"Seguridad\",\n  \"advancements.refinedstorage.security.description\": \"Asegura tu red con un centro de seguridad y una tarjeta de seguridad\",\n  \"advancements.refinedstorage.wireless\": \"Wi-FI\",\n  \"advancements.refinedstorage.wireless.description\": \"Transmite la señal de tu red con un transmisor de red\",\n  \"advancements.refinedstorage.wireless_items\": \"Objetos inalámbrico\",\n  \"advancements.refinedstorage.wireless_items.description\": \"Interactua con tus objetos guardados inalámbricamente con tu panel inalámbrico\",\n  \"advancements.refinedstorage.wireless_fluids\": \"fluidos inalámbricos\",\n  \"advancements.refinedstorage.wireless_fluids.description\": \"Interactua con tus fluidos guardados inalámbricamente con tu panel de fluidos inalámbrico\",\n  \"advancements.refinedstorage.wireless_monitoring\": \"Ojos en la red\",\n  \"advancements.refinedstorage.wireless_monitoring.description\": \"Verifica el estado de las tareas de fabricación inalámbricamente con el monitor de fabricación inalámbrico\",\n  \"advancements.refinedstorage.no_cables_required\": \"¿para qué cables?\",\n  \"advancements.refinedstorage.no_cables_required.description\": \"Añade más componentes a la red sin usar cables, solo usando un transmisor de red, receptor de red y una tarjeta de red\",\n  \"advancements.refinedstorage.upgrading\": \"Mejorando\",\n  \"advancements.refinedstorage.upgrading.description\": \"Haz una mejora\",\n  \"advancements.refinedstorage.better_range\": \"Mas rango\",\n  \"advancements.refinedstorage.better_range.description\": \"Mejora el rango de tu transmisor inalámbrico con mejoras de rango - adicionalmente, amplifica el rango de tu transmisor inalámbrico en tu mundo\",\n  \"advancements.refinedstorage.crafting_on_demand\": \"Pedido a domicilio\",\n  \"advancements.refinedstorage.crafting_on_demand.description\": \"Usa la mejora de fabricación en una interfaz, exportador o constructor para fabricar objetos y bloques en demanda\",\n  \"advancements.refinedstorage.detecting\": \"Detectando\",\n  \"advancements.refinedstorage.detecting.description\": \"Detecta objetos o fluidos en la red con el detector\",\n  \"advancements.refinedstorage.interface_to_the_world\": \"Interfaz al mundo\",\n  \"advancements.refinedstorage.storing_externally\": \"Almacén externo\",\n  \"advancements.refinedstorage.storing_externally.description\": \"Usa un almacén externo para que la red tenga almacenamiento desde un bloque externo como un cofre\"\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/lang/fr_fr.json",
    "content": "{\n  \"itemGroup.refinedstorage\": \"Refined Storage\",\n  \"key.refinedstorage.focusSearchBar\": \"Barre de recherche de la grille\",\n\n  \"gui.refinedstorage.controller\": \"Contrôleur\",\n  \"gui.refinedstorage.creative_controller\": \"Contrôleur\",\n  \"gui.refinedstorage.grid\": \"Grille\",\n  \"gui.refinedstorage.grid.craft\": \"Craft\",\n  \"gui.refinedstorage.crafting_grid\": \"Grille pour les crafts\",\n  \"gui.refinedstorage.pattern_grid\": \"Grille de modèle\",\n  \"gui.refinedstorage.grid.pattern_create\": \"Créer des modèles\",\n  \"gui.refinedstorage.fluid_grid\": \"Grille des fluides\",\n  \"gui.refinedstorage.portable_grid\": \"Grille portable\",\n  \"gui.refinedstorage.disk_drive\": \"Lecteur de disques\",\n  \"gui.refinedstorage.disk_drive.disks\": \"Disques\",\n  \"gui.refinedstorage.external_storage\": \"Stockage externe\",\n  \"gui.refinedstorage.importer\": \"Importeur\",\n  \"gui.refinedstorage.exporter\": \"Exporteur\",\n  \"gui.refinedstorage.detector\": \"Detecteur\",\n  \"gui.refinedstorage.destructor\": \"Destructeur\",\n  \"gui.refinedstorage.constructor\": \"Constructeur\",\n  \"gui.refinedstorage.relay\": \"Relais\",\n  \"gui.refinedstorage.interface.import\": \"Interface d'import\",\n  \"gui.refinedstorage.interface.export\": \"Interface d'export\",\n  \"gui.refinedstorage.crafting_monitor\": \"Moniteur de craft\",\n  \"gui.refinedstorage.wireless_crafting_monitor\": \"Moniteur de craft sans-fil\",\n  \"gui.refinedstorage.crafting_monitor.machine_none\": \"Pas de machine disponible\",\n  \"gui.refinedstorage.wireless_transmitter\": \"Emetteur sans-fil\",\n  \"gui.refinedstorage.wireless_transmitter.distance\": \"%d bloc(s)\",\n  \"gui.refinedstorage.crafter\": \"Crafteur\",\n  \"gui.refinedstorage.filter\": \"Filtre\",\n  \"gui.refinedstorage.filter.compare_nbt\": \"NBT\",\n  \"gui.refinedstorage.filter.mod_filter\": \"Filtre de mod\",\n  \"gui.refinedstorage.network_transmitter\": \"Emetteur réseau\",\n  \"gui.refinedstorage.network_transmitter.distance\": \"%d bloc(s)\",\n  \"gui.refinedstorage.network_transmitter.missing_card\": \"Carte réseau manquante\",\n  \"gui.refinedstorage.fluid_interface\": \"Interface de fluides\",\n  \"gui.refinedstorage.fluid_interface.in\": \"Entrée\",\n  \"gui.refinedstorage.fluid_interface.out\": \"Sortie\",\n  \"gui.refinedstorage.crafting_preview\": \"Aperçu de craft\",\n  \"gui.refinedstorage.crafting_preview.to_craft\": \"A craft: %d\",\n  \"gui.refinedstorage.crafting_preview.available\": \"Disponible: %d\",\n  \"gui.refinedstorage.crafting_preview.missing\": \"Manquant: %d\",\n  \"gui.refinedstorage.crafting_preview.circular\": \"Dépendance circulaire!\",\n  \"gui.refinedstorage.crafting_preview.loop\": \"Boucle de traitement...\",\n  \"gui.refinedstorage.security_manager\": \"Poste de sécurité\",\n  \"gui.refinedstorage.security_manager.configure\": \"Configure\",\n  \"gui.refinedstorage.security_manager.permission.0\": \"Insère\",\n  \"gui.refinedstorage.security_manager.permission.0.tooltip\": \"Insertion d'items dans le réseau\",\n  \"gui.refinedstorage.security_manager.permission.1\": \"Extrait\",\n  \"gui.refinedstorage.security_manager.permission.1.tooltip\": \"Extraction d'items du réseau\",\n  \"gui.refinedstorage.security_manager.permission.2\": \"Autocraft\",\n  \"gui.refinedstorage.security_manager.permission.2.tooltip\": \"Lance, annule et voit les taches de crafts\",\n  \"gui.refinedstorage.security_manager.permission.3\": \"Modifie\",\n  \"gui.refinedstorage.security_manager.permission.3.tooltip\": \"Ouvre l'interface des blocks\",\n  \"gui.refinedstorage.security_manager.permission.4\": \"Construit\",\n  \"gui.refinedstorage.security_manager.permission.4.tooltip\": \"Ajoute ou enlève des appareils sur le réseau\",\n  \"gui.refinedstorage.security_manager.permission.5\": \"Securité\",\n  \"gui.refinedstorage.security_manager.permission.5.tooltip\": \"Capable de modifier les options de sécurité\",\n  \"gui.refinedstorage.storage_monitor\": \"Storage moniteur\",\n\n  \"misc.refinedstorage.energy_stored\": \"%d / %d FE\",\n  \"misc.refinedstorage.energy_usage\": \"Usage: %d FE/t\",\n  \"misc.refinedstorage.energy_usage_minimal\": \"%d FE/t\",\n\n  \"misc.refinedstorage.storage.stored\": \"Stored: %s\",\n  \"misc.refinedstorage.storage.stored_capacity\": \"Stored: %s / %s\",\n  \"misc.refinedstorage.storage.stored_minimal\": \"%s\",\n  \"misc.refinedstorage.storage.stored_capacity_minimal\": \"%s / %s\",\n  \"misc.refinedstorage.storage.full\": \"%d%% plein\",\n\n  \"misc.refinedstorage.network_item.tooltip\": \"Linked to %d, %d, %d.\",\n  \"misc.refinedstorage.network_item.out_of_range\": \"Pas d'émetteur sans-fil à portée.\",\n  \"misc.refinedstorage.network_item.not_found\": \"Controlleur introuvable.\",\n\n  \"misc.refinedstorage.network_card.tooltip\": \"Linked to %d, %d, %d in %s.\",\n\n  \"misc.refinedstorage.pattern.inputs\": \"Entrée\",\n  \"misc.refinedstorage.pattern.outputs\": \"Sortie\",\n  \"misc.refinedstorage.pattern.invalid\": \"Modèle invalide\",\n\n  \"misc.refinedstorage.security.no_permission\": \"Vous n'avez pas l'autorisation de faire cette action.\",\n\n  \"misc.refinedstorage.start\": \"Commencer\",\n  \"misc.refinedstorage.clear\": \"Vider\",\n  \"misc.refinedstorage.set\": \"Fixer\",\n  \"misc.refinedstorage.cancel_all\": \"Tout annuler\",\n  \"misc.refinedstorage.priority\": \"Priorité\",\n  \"misc.refinedstorage.processing\": \"En traitement\",\n\n  \"sidebutton.refinedstorage.redstone_mode\": \"Mode redstone\",\n  \"sidebutton.refinedstorage.redstone_mode.0\": \"Ignore le signal de redstone\",\n  \"sidebutton.refinedstorage.redstone_mode.1\": \"Actif seulement avec signal de redstone\",\n  \"sidebutton.refinedstorage.redstone_mode.2\": \"Actif seulement sans signal de redstone\",\n\n  \"sidebutton.refinedstorage.grid.view_type\": \"Affiche\",\n  \"sidebutton.refinedstorage.grid.view_type.0\": \"Normal\",\n  \"sidebutton.refinedstorage.grid.view_type.1\": \"Pas de craftables\",\n  \"sidebutton.refinedstorage.grid.view_type.2\": \"Seulement les craftables\",\n  \"sidebutton.refinedstorage.grid.sorting.direction\": \"Ordre de tri\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.0\": \"Croissant\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.1\": \"Décroissant\",\n  \"sidebutton.refinedstorage.grid.sorting.type\": \"Type de tri\",\n  \"sidebutton.refinedstorage.grid.sorting.type.0\": \"Quantité\",\n  \"sidebutton.refinedstorage.grid.sorting.type.1\": \"Nom\",\n  \"sidebutton.refinedstorage.grid.sorting.type.2\": \"ID\",\n  \"sidebutton.refinedstorage.grid.search_box_mode\": \"Mode de la barre de recherche\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.0\": \"Normal\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.1\": \"Normal (sélection auto)\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.2\": \"Synchronisé JEI\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.3\": \"Synchronisé JEI (sélection auto)\",\n  \"sidebutton.refinedstorage.grid.size\": \"Taille\",\n  \"sidebutton.refinedstorage.grid.size.0\": \"Etendu\",\n  \"sidebutton.refinedstorage.grid.size.1\": \"Petit\",\n  \"sidebutton.refinedstorage.grid.size.2\": \"Moyen\",\n  \"sidebutton.refinedstorage.grid.size.3\": \"Grand\",\n\n  \"sidebutton.refinedstorage.mode\": \"Mode\",\n  \"sidebutton.refinedstorage.mode.whitelist\": \"Liste blanche\",\n  \"sidebutton.refinedstorage.mode.blacklist\": \"Liste noire\",\n\n  \"sidebutton.refinedstorage.iomode\": \"IO mode\",\n  \"sidebutton.refinedstorage.iomode.insert\": \"Insère dans le réseau\",\n  \"guidebutton.refinedstorage.iomode.extract\": \"Extrait du réseau\",\n\n  \"sidebutton.refinedstorage.type\": \"Type\",\n  \"sidebutton.refinedstorage.type.0\": \"Items\",\n  \"sidebutton.refinedstorage.type.1\": \"Fluides\",\n\n  \"sidebutton.refinedstorage.detector.mode\": \"Mode\",\n  \"sidebutton.refinedstorage.detector.mode.0\": \"Emet un signal quand la quantité est inférieure\",\n  \"sidebutton.refinedstorage.detector.mode.1\": \"Emet un signal quand la quantité est égale\",\n  \"sidebutton.refinedstorage.detector.mode.2\": \"Emet un signal quand la quantité est supérieure\",\n\n  \"sidebutton.refinedstorage.constructor.drop\": \"Laisse tomber les blocs au lieu de les placer\",\n\n  \"sidebutton.refinedstorage.destructor.pickup\": \"Ramasse les items au lieu de les casser\",\n\n  \"sidebutton.refinedstorage.access_type\": \"Type d'accès\",\n  \"sidebutton.refinedstorage.access_type.0\": \"Insère and extrait\",\n  \"sidebutton.refinedstorage.access_type.1\": \"Insère seulement\",\n  \"sidebutton.refinedstorage.access_type.2\": \"Extrait seulement\",\n\n  \"block.refinedstorage.controller\": \"Controlleur\",\n  \"block.refinedstorage.creative_controller\": \"Controlleur créatif\",\n  \"block.refinedstorage.cable\": \"Cable\",\n  \"block.refinedstorage.grid\": \"Grille\",\n  \"block.refinedstorage.crafting_grid\": \"Grille de craft\",\n  \"block.refinedstorage.pattern_grid\": \"Grille de modèle\",\n  \"block.refinedstorage.fluid_grid\": \"Grille de fluide\",\n  \"block.refinedstorage.disk_drive\": \"Lecteur de disque\",\n  \"block.refinedstorage.disk_manipulator\": \"Manipulateur de disque\",\n  \"block.refinedstorage.external_storage\": \"Stockage externe\",\n  \"block.refinedstorage.importer\": \"Importeur\",\n  \"block.refinedstorage.exporter\": \"Exporteur\",\n  \"block.refinedstorage.detector\": \"Detecteur\",\n  \"block.refinedstorage.machine_casing\": \"Boitier de machine\",\n  \"block.refinedstorage.destructor\": \"Destructeur\",\n  \"block.refinedstorage.constructor\": \"Constructeur\",\n  \"block.refinedstorage.1k_storage_block\": \"Bloc de stockage 1k\",\n  \"block.refinedstorage.4k_storage_block\": \"Bloc de stockage 4k\",\n  \"block.refinedstorage.16k_storage_block\": \"Bloc de stockage 16k\",\n  \"block.refinedstorage.64k_storage_block\": \"Bloc de stockage 64k\",\n  \"block.refinedstorage.creative_storage_block\": \"Bloc de stockage créatif\",\n  \"block.refinedstorage.relay\": \"Relais\",\n  \"block.refinedstorage.interface\": \"Interface\",\n  \"block.refinedstorage.crafting_monitor\": \"Moniteur de craft\",\n  \"block.refinedstorage.wireless_transmitter\": \"Emetteur sans fil\",\n  \"block.refinedstorage.wireless_transmitter.tooltip\": \"A besoin d'être placé sur %s.\",\n  \"block.refinedstorage.crafter\": \"Crafteur\",\n  \"block.refinedstorage.network_receiver\": \"Récepteur réseau\",\n  \"block.refinedstorage.network_transmitter\": \"Transmetteur réseau\",\n  \"block.refinedstorage.fluid_interface\": \"Interface de fluides\",\n  \"block.refinedstorage.64k_fluid_storage_block\": \"Bloc de stockage de fluides de 64k\",\n  \"block.refinedstorage.256k_fluid_storage_block\": \"Bloc de stockage de fluides de 256k\",\n  \"block.refinedstorage.1024k_fluid_storage_block\": \"Bloc de stockage de fluides de 1024k\",\n  \"block.refinedstorage.4096k_fluid_storage_block\": \"Bloc de stockage de fluides de 4096k\",\n  \"block.refinedstorage.creative_fluid_storage_block\": \"Bloc de stockage de fluides créatif\",\n  \"block.refinedstorage.security_manager\": \"Poste de sécurité\",\n  \"block.refinedstorage.quartz_enriched_iron_block\": \"Bloc de quartz enrichi au fer\",\n  \"block.refinedstorage.storage_monitor\": \"Moniteur de stockage\",\n  \"block.refinedstorage.portable_grid\": \"Grille portative\",\n  \"block.refinedstorage.creative_portable_grid\": \"Grille portative créatif\",\n  \"block.refinedstorage.portable_grid.tooltip\": \"S'accroupir pour placer dans le monde.\",\n\n  \"item.refinedstorage.1k_storage_disk\": \"Disque de stockage 1k\",\n  \"item.refinedstorage.4k_storage_disk\": \"Disque de stockage 4k\",\n  \"item.refinedstorage.16k_storage_disk\": \"Disque de stockage 16k\",\n  \"item.refinedstorage.64k_storage_disk\": \"Disque de stockage 64k\",\n  \"item.refinedstorage.creative_storage_disk\": \"Disque de stockage créatif\",\n  \"item.refinedstorage.64k_fluid_storage_disk\": \"Disque de stockage de fluides 64k\",\n  \"item.refinedstorage.256k_fluid_storage_disk\": \"Disque de stockage de fluides 256k\",\n  \"item.refinedstorage.1024k_fluid_storage_disk\": \"Disque de stockage de fluides 1024k\",\n  \"item.refinedstorage.4096k_fluid_storage_disk\": \"Disque de stockage de fluides 4096k\",\n  \"item.refinedstorage.creative_fluid_storage_disk\": \"Disque de stockage de fluides créatif\",\n  \"item.refinedstorage.wireless_grid\": \"Grille sans fil\",\n  \"item.refinedstorage.creative_wireless_grid\": \"Grille sans fil créative\",\n  \"item.refinedstorage.wireless_fluid_grid\": \"Grille de liquide sans fil\",\n  \"item.refinedstorage.creative_wireless_fluid_grid\": \"Grille liquide sans fil créative\",\n  \"item.refinedstorage.wireless_crafting_monitor\": \"Moniteur de craft sans fil\",\n  \"item.refinedstorage.creative_wireless_crafting_monitor\": \"Moniteur de craft sans fil créatif\",\n  \"item.refinedstorage.quartz_enriched_iron\": \"Quartz enrichi au fer\",\n  \"item.refinedstorage.construction_core\": \"Coeur de construction\",\n  \"item.refinedstorage.destruction_core\": \"Coeur de destruction\",\n  \"item.refinedstorage.silicon\": \"Silicone\",\n  \"item.refinedstorage.basic_processor\": \"Processeur basique\",\n  \"item.refinedstorage.improved_processor\": \"Processeur amélioré\",\n  \"item.refinedstorage.advanced_processor\": \"Processeur avancé\",\n  \"item.refinedstorage.1k_storage_part\": \"Pièce de stockage 1k\",\n  \"item.refinedstorage.4k_storage_part\": \"Pièce de stockage 4k\",\n  \"item.refinedstorage.16k_storage_part\": \"Pièce de stockage 16k\",\n  \"item.refinedstorage.64k_storage_part\": \"Pièce de stockage 64k\",\n  \"item.refinedstorage.64k_fluid_storage_part\": \"Pièce de stockage de fluides 64k\",\n  \"item.refinedstorage.256k_fluid_storage_part\": \"Pièce de stockage de fluides 256k\",\n  \"item.refinedstorage.1024k_fluid_storage_part\": \"Pièce de stockage de fluides 1024k\",\n  \"item.refinedstorage.4096k_fluid_storage_part\": \"Pièce de stockage de fluides 4096k\",\n  \"item.refinedstorage.pattern\": \"Modèle\",\n  \"item.refinedstorage.upgrade\": \"Amélioration\",\n  \"item.refinedstorage.range_upgrade\": \"Amélioration de portée\",\n  \"item.refinedstorage.speed_upgrade\": \"Amélioration de vitesse\",\n  \"item.refinedstorage.crafting_upgrade\": \"Amélioration de craft\",\n  \"item.refinedstorage.stack_upgrade\": \"Amélioration de stack\",\n  \"item.refinedstorage.silk_touch_upgrade\": \"Amélioration touché de soie\",\n  \"item.refinedstorage.fortune_1_upgrade\": \"Amélioration de fortune\",\n  \"item.refinedstorage.fortune_2_upgrade\": \"Amélioration de fortune\",\n  \"item.refinedstorage.fortune_3_upgrade\": \"Amélioration de fortune\",\n  \"item.refinedstorage.storage_housing\": \"Boitier de stockage\",\n  \"item.refinedstorage.filter\": \"Filtre\",\n  \"item.refinedstorage.network_card\": \"Carte réseau\",\n  \"item.refinedstorage.wrench\": \"Clé\",\n  \"item.refinedstorage.security_card\": \"Carte de sécurité\",\n  \"item.refinedstorage.security_card.owner\": \"Bound to: %s\",\n\n  \"advancements.refinedstorage.controlling.description\": \"Craft d'un controlleur\",\n  \"advancements.refinedstorage.connecting\": \"En cours de connexion\",\n  \"advancements.refinedstorage.connecting.description\": \"Vous pouvez placer chaque appareil côte à côte pour les connecter ensemble, ou utiliser un cable.\",\n  \"advancements.refinedstorage.conditional_connecting\": \"Connexion conditionnelle\",\n  \"advancements.refinedstorage.conditional_connecting.description\": \"Crafter un relais pour controller si le signal du réseau peut passer avec un signal de redstone\",\n  \"advancements.refinedstorage.drives\": \"Lecteur de disques\",\n  \"advancements.refinedstorage.drives.description\": \"Crafter un lecteur de disques pour pouvoir stocker vos disques\",\n  \"advancements.refinedstorage.manipulating_disks\": \"Disque manipulateur\",\n  \"advancements.refinedstorage.manipulating_disks.description\": \"Utiliser un disque manipulateur pour modifier facilement le contenu des disques\",\n  \"advancements.refinedstorage.storing_items\": \"Stocker les items\",\n  \"advancements.refinedstorage.storing_items.description\": \"Crafter un disque et le mettre dans un lecteur\",\n  \"advancements.refinedstorage.viewing_items\": \"Voir les items\",\n  \"advancements.refinedstorage.viewing_items.description\": \"Crafter une grille pour intéragir avec votre stockage d'item\",\n  \"advancements.refinedstorage.portable_storage\": \"Stockage portatif\",\n  \"advancements.refinedstorage.upgrading_your_grid\": \"Améliorer votre grille\",\n  \"advancements.refinedstorage.upgrading_your_grid.description\": \"Améliorer votre grille vers une grille de craft pour pouvoir crafter dans votre grille\",\n  \"advancements.refinedstorage.storing_fluids\": \"Stocker des fluides\",\n  \"advancements.refinedstorage.storing_fluids.description\": \"Crafte un disque de fluide et le mettre dans un lecteur\",\n  \"advancements.refinedstorage.viewing_fluids\": \"Voir les fluides\",\n  \"advancements.refinedstorage.viewing_fluids.description\": \"Crafter une grille pour intéragir avec votre stockage de fluides\",\n  \"advancements.refinedstorage.better_than_a_barrel\": \"Mieux qu'un barril\",\n  \"advancements.refinedstorage.better_than_a_barrel.description\": \"Crafter un moniteur de stockage pour voir, insérer ou extraire des items de votre réseau\",\n  \"advancements.refinedstorage.autocrafting\": \"Autocrafter\",\n  \"advancements.refinedstorage.autocrafting.description\": \"Crafter un crafteur\",\n  \"advancements.refinedstorage.pattern_creation\": \"Création de modèle\",\n  \"advancements.refinedstorage.pattern_creation.description\": \"Créer des modèles avec la grille de modèle et un modèle\",\n  \"advancements.refinedstorage.monitoring\": \"Controller\",\n  \"advancements.refinedstorage.monitoring.description\": \"Vérifier le statut de vos tâches de crafts avec le moniteur de crafts\",\n  \"advancements.refinedstorage.importing\": \"Importer\",\n  \"advancements.refinedstorage.importing.description\": \"Amener des items ou fluides dans le réseau de stockage avec un importeur\",\n  \"advancements.refinedstorage.destruction\": \"Destruction\",\n  \"advancements.refinedstorage.destruction.description\": \"Amener des blocs ou fluides dans le réseau de stockage avec un destructeur\",\n  \"advancements.refinedstorage.exporting\": \"Exporter\",\n  \"advancements.refinedstorage.exporting.description\": \"Sortir des items ou fluides du réseau de stockage avec un exporteur\",\n  \"advancements.refinedstorage.construction\": \"Construction\",\n  \"advancements.refinedstorage.construction.description\": \"Sortir des blocs ou fluides du réseau de stockage avec un constructeur\",\n  \"advancements.refinedstorage.security\": \"Sécurité\",\n  \"advancements.refinedstorage.security.description\": \"Securisez votre réseau avec un poste de sécurité et une carte de sécurité\",\n  \"advancements.refinedstorage.wireless\": \"Sans fil\",\n  \"advancements.refinedstorage.wireless.description\": \"Transmettez un signal réseau avec un émetteur sans fil\",\n  \"advancements.refinedstorage.wireless_items\": \"Items sans fil\",\n  \"advancements.refinedstorage.wireless_items.description\": \"Interagissez avec votre stockage d'items a distance avec votre grille sans fil\",\n  \"advancements.refinedstorage.wireless_fluids\": \"Fluides sans fils\",\n  \"advancements.refinedstorage.wireless_fluids.description\": \"Interagissez avec votre stockage de fluide à distance avec une grille de fluides sans fil\",\n  \"advancements.refinedstorage.wireless_monitoring\": \"Controller\",\n  \"advancements.refinedstorage.wireless_monitoring.description\": \"Controller le statut de vos taches de craft à distance avec un moniteur de crafts sans fil\",\n  \"advancements.refinedstorage.no_cables_required\": \"Aucun cable demandé\",\n  \"advancements.refinedstorage.no_cables_required.description\": \"Ajoutez des composants supplémentaires à votre réseau sans utiliser un emetteur réseau, un recepteur réseau ou une carte réseau\",\n  \"advancements.refinedstorage.upgrading\": \"Amélioration\",\n  \"advancements.refinedstorage.upgrading.description\": \"Craftez une amélioration\",\n  \"advancements.refinedstorage.crafting_on_demand\": \"Crafter à la demande\",\n  \"advancements.refinedstorage.crafting_on_demand.description\": \"Utilisez une amélioration de craft dans une interface, un exporteur ou un constructeur pour crafter des items ou blocs à la demande\",\n  \"advancements.refinedstorage.detecting\": \"Detection\",\n  \"advancements.refinedstorage.detecting.description\": \"Detectez les items ou fluides dans le réseau avec un détecteur\",\n  \"advancements.refinedstorage.interface_to_the_world\": \"Interface vers le monde\",\n  \"advancements.refinedstorage.storing_externally\": \"Stocker éternellement\",\n  \"advancements.refinedstorage.storing_externally.description\": \"Utilisez un stockage externe pour fournir au réseau un stockage à partir d'un bloc externe comme un coffre\"\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/lang/hu_hu.json",
    "content": "{\n  \"itemGroup.refinedstorage\": \"Refined Storage\",\n  \"itemGroup.refinedstorage.covers\": \"Refined Storage Fedők\",\n\n  \"key.refinedstorage.focusSearchBar\": \"Kereső Mező Rács Fókuszálása\",\n  \"key.refinedstorage.clearGridCraftingMatrix\": \"Barkácsoló Mátrix Rács Ürítése\",\n  \"key.refinedstorage.openWirelessGrid\": \"Vezeték Nélküli Rács Megnyitása\",\n  \"key.refinedstorage.openWirelessFluidGrid\": \"Vezeték Nélküli Folyadékrács Megnyitása\",\n  \"key.refinedstorage.openPortableGrid\": \"Hordozható Rács Megnyitása\",\n  \"key.refinedstorage.openWirelessCraftingMonitor\": \"Vezeték Nélküli Barkácsoló Monitor Megnyitása\",\n\n  \"gui.refinedstorage.controller\": \"Vezérlő\",\n  \"gui.refinedstorage.creative_controller\": \"Kreatív Vezérlő\",\n  \"gui.refinedstorage.grid\": \"Rács\",\n  \"gui.refinedstorage.grid.craft\": \"Barkácsolás\",\n  \"gui.refinedstorage.crafting_grid\": \"Barkácsoló Rács\",\n  \"gui.refinedstorage.pattern_grid\": \"Sablon Rács\",\n  \"gui.refinedstorage.grid.pattern_create\": \"Létrehoz\",\n  \"gui.refinedstorage.fluid_grid\": \"Folyadék Rács\",\n  \"gui.refinedstorage.portable_grid\": \"Hordozható Rács\",\n  \"gui.refinedstorage.item_amount\": \"Tárgy Mennyiség\",\n  \"gui.refinedstorage.fluid_amount\": \"Folyadék Mennyiség mB-ben\",\n  \"gui.refinedstorage.disk_drive\": \"Lemez Meghajtó\",\n  \"gui.refinedstorage.disk_drive.disks\": \"Lemezek\",\n  \"gui.refinedstorage.disk_manipulator\": \"Lemez Kezelő\",\n  \"gui.refinedstorage.disk_manipulator.in\": \"Be\",\n  \"gui.refinedstorage.disk_manipulator.out\": \"Ki\",\n  \"gui.refinedstorage.external_storage\": \"Külső Tárhely\",\n  \"gui.refinedstorage.importer\": \"Importáló\",\n  \"gui.refinedstorage.exporter\": \"Exportáló\",\n  \"gui.refinedstorage.detector\": \"Érzékelő\",\n  \"gui.refinedstorage.destructor\": \"Megsemmisítő\",\n  \"gui.refinedstorage.constructor\": \"Építő\",\n  \"gui.refinedstorage.relay\": \"Jelfogó\",\n  \"gui.refinedstorage.interface.import\": \"Import Interfész\",\n  \"gui.refinedstorage.interface.export\": \"Export Interfész\",\n  \"gui.refinedstorage.crafting_monitor\": \"Barkácsoló Monitor\",\n  \"gui.refinedstorage.wireless_crafting_monitor\": \"Vezeték Nélküli Barkácsoló Monitor\",\n  \"gui.refinedstorage.crafting_monitor.tooltip.requested\": \"%d kérvényezve\",\n  \"gui.refinedstorage.crafting_monitor.stored\": \"Tárolva: %d\",\n  \"gui.refinedstorage.crafting_monitor.missing\": \"Hiányzik: %d\",\n  \"gui.refinedstorage.crafting_monitor.processing\": \"Feldolgozás Alatt: %d\",\n  \"gui.refinedstorage.crafting_monitor.scheduled\": \"Beütemezve: %d\",\n  \"gui.refinedstorage.crafting_monitor.crafting\": \"Barkácsolás Alatt: %d\",\n  \"gui.refinedstorage.crafting_monitor.machine_does_not_accept_item\": \"A Gép Nem Fogadja El a Tárgyat\",\n  \"gui.refinedstorage.crafting_monitor.machine_does_not_accept_fluid\": \"A Gép Nem Fogadja El a Folyadékot\",\n  \"gui.refinedstorage.crafting_monitor.machine_none\": \"Nincs Gép\",\n  \"gui.refinedstorage.crafting_monitor.crafter_is_locked\": \"Barkácsoló Lezárva\",\n  \"gui.refinedstorage.wireless_transmitter\": \"Vezeték Nélküli Adó\",\n  \"gui.refinedstorage.wireless_transmitter.distance\": \"%d blokk(ok)\",\n  \"gui.refinedstorage.crafter\": \"Barkácsoló\",\n  \"gui.refinedstorage.filter\": \"Szűrő\",\n  \"gui.refinedstorage.filter.compare_nbt\": \"NBT\",\n  \"gui.refinedstorage.filter.mod_filter\": \"Mod Szűrő\",\n  \"gui.refinedstorage.network_transmitter\": \"Hálózati Adó\",\n  \"gui.refinedstorage.network_transmitter.distance\": \"%d blokk(ok)\",\n  \"gui.refinedstorage.network_transmitter.missing_card\": \"Hiányzó Hálózati Kártya\",\n  \"gui.refinedstorage.fluid_interface\": \"Folyadék Interfész\",\n  \"gui.refinedstorage.fluid_interface.in\": \"Be\",\n  \"gui.refinedstorage.fluid_interface.out\": \"Ki\",\n  \"gui.refinedstorage.crafting_preview\": \"Barkácsolási Előnézet\",\n  \"gui.refinedstorage.crafting_preview.to_craft\": \"Barkácsolandó: %d\",\n  \"gui.refinedstorage.crafting_preview.available\": \"Elérhető: %d\",\n  \"gui.refinedstorage.crafting_preview.missing\": \"Hiányzik: %d\",\n  \"gui.refinedstorage.crafting_preview.error\": \"Kérés Elutasítva\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.0\": \"Az egyik alapanyagnak szüksége volt\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.1\": \"magára.\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.2\": \"El kell távolítanod a sablont, hogy\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.3\": \"ne legyen használva barkácsoláskor.\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.4\": \"Problémás Sablon:\",\n  \"gui.refinedstorage.crafting_preview.error.too_complex.0\": \"A barkácsolási számítás túl bonyolult volt,\",\n  \"gui.refinedstorage.crafting_preview.error.too_complex.1\": \"ezért le lett állítva, hogy ne terhelje a szervert.\",\n  \"gui.refinedstorage.security_manager\": \"Biztonsági Menedzser\",\n  \"gui.refinedstorage.security_manager.configure\": \"Beállítások\",\n  \"gui.refinedstorage.security_manager.permission.0\": \"Bevitel\",\n  \"gui.refinedstorage.security_manager.permission.0.tooltip\": \"Tárgyak és Folyadékok bevitele a hálózatba\",\n  \"gui.refinedstorage.security_manager.permission.1\": \"Kivitel\",\n  \"gui.refinedstorage.security_manager.permission.1.tooltip\": \"Tárgyak és Folyadékok kivitele a hálózatból\",\n  \"gui.refinedstorage.security_manager.permission.2\": \"Autobarkácsolás\",\n  \"gui.refinedstorage.security_manager.permission.2.tooltip\": \"Barkácsoló folyamatok elkezdése, megszakítása és megfigyelése\",\n  \"gui.refinedstorage.security_manager.permission.3\": \"Módosítás\",\n  \"gui.refinedstorage.security_manager.permission.3.tooltip\": \"Blokkok megnyitása\",\n  \"gui.refinedstorage.security_manager.permission.4\": \"Építés\",\n  \"gui.refinedstorage.security_manager.permission.4.tooltip\": \"Eszközök hozzáadása és elvétele a hálózatból\",\n  \"gui.refinedstorage.security_manager.permission.5\": \"Biztonság\",\n  \"gui.refinedstorage.security_manager.permission.5.tooltip\": \"Engedély a biztonsági beállítások módosítására\",\n  \"gui.refinedstorage.storage_monitor\": \"Tárhely Monitor\",\n  \"gui.refinedstorage.crafter_manager\": \"Barkácsoló Menedzser\",\n  \"gui.refinedstorage.alternatives\": \"Alternatívák\",\n  \"gui.refinedstorage.alternatives.apply\": \"Alkalmaz\",\n  \"gui.refinedstorage.jei.transfer.autocrafting_available\": \"Autobarkácsolás elérhető\",\n  \"gui.refinedstorage.jei.transfer.request_autocrafting\": \"CTRL + CLICK autobarkácsolás kéréséhez\",\n  \"gui.refinedstorage.jei.transfer.request_autocrafting_mac\": \"CMD + CLICK autobarkácsolás kéréséhez\",\n  \"misc.refinedstorage.energy_stored\": \"%d / %d FE\",\n  \"misc.refinedstorage.energy_usage\": \"Fogyasztás: %d FE/t\",\n  \"misc.refinedstorage.energy_usage_minimal\": \"%d FE/t\",\n  \"misc.refinedstorage.storage.stored\": \"Tárolva: %s\",\n  \"misc.refinedstorage.storage.stored_capacity\": \"Tárolva: %s / %s\",\n  \"misc.refinedstorage.storage.stored_minimal\": \"%s\",\n  \"misc.refinedstorage.storage.stored_capacity_minimal\": \"%s / %s\",\n  \"misc.refinedstorage.storage.full\": \"%d%%-ban tele\",\n  \"misc.refinedstorage.network_item.tooltip\": \"Csatlakoztatva %d, %d, %d-hez.\",\n  \"misc.refinedstorage.network_item.out_of_range\": \"Nincs Vezeték Nélküli Adó a közelben.\",\n  \"misc.refinedstorage.network_item.not_found\": \"A Hálózat nem létezik.\",\n  \"misc.refinedstorage.network_item.shortcut_not_found\": \"Semennyi %s sincs az eszköztáradban.\",\n  \"misc.refinedstorage.network_item.shortcut_duplicate\": \"Több mint egy %s van az eszköztáradban.\",\n  \"misc.refinedstorage.network_item.out_of_energy\": \"A(z) %s kifogyott energiából.\",\n\n  \"misc.refinedstorage.network_card.tooltip\": \"Csatlakoztatva %d, %d, %d-hez %s-ben.\",\n\n  \"misc.refinedstorage.pattern.inputs\": \"Bemenetek\",\n  \"misc.refinedstorage.pattern.outputs\": \"Kimenetek\",\n  \"misc.refinedstorage.pattern.invalid\": \"Érvénytelen Sablon\",\n  \"misc.refinedstorage.pattern.exact\": \"Pontos módot használ\",\n  \"misc.refinedstorage.pattern.allowed_item_tag\": \"%s-ből használ tárgyakat %s-hez\",\n  \"misc.refinedstorage.pattern.allowed_fluid_tag\": \"%s-ből használ folyadékokat %s-hez\",\n\n  \"misc.refinedstorage.pattern.error.processing_no_outputs\": \"A feldolgozási sablonnak nincs kimenete\",\n  \"misc.refinedstorage.pattern.error.no_output\": \"A receptnek nincs kimenete\",\n  \"misc.refinedstorage.pattern.error.recipe_does_not_exist\": \"A recept nem létezik\",\n  \"misc.refinedstorage.pattern.error.tag_no_longer_applicable\": \"A %s címke többé nem alkalmazható %s-re\",\n  \"misc.refinedstorage.security.no_permission\": \"Erre nincs felhatalmazásod.\",\n  \"misc.refinedstorage.start\": \"Kezdés\",\n  \"misc.refinedstorage.clear\": \"Ürítés\",\n  \"misc.refinedstorage.set\": \"Beállít\",\n  \"misc.refinedstorage.cancel_all\": \"MINDEN megszakítása\",\n  \"misc.refinedstorage.priority\": \"Prioritás\",\n  \"misc.refinedstorage.exact\": \"Pontos\",\n  \"misc.refinedstorage.processing\": \"Feldolgozás\",\n  \"misc.refinedstorage.fluidmode\": \"Folyadékok\",\n  \"misc.refinedstorage.total\": \"összesen %s\",\n  \"misc.refinedstorage.last_modified.just_now\": \"Utoljára módosítva most, %s által\",\n  \"misc.refinedstorage.last_modified.second\": \"Utoljára módosítva %d másodperce, %s által\",\n  \"misc.refinedstorage.last_modified.seconds\": \"Utoljára módosítva %d másodperce, %s által\",\n  \"misc.refinedstorage.last_modified.minute\": \"Utoljára módosítva %d perce, %s által\",\n  \"misc.refinedstorage.last_modified.minutes\": \"Utoljára módosítva %d perce, %s által\",\n  \"misc.refinedstorage.last_modified.hour\": \"Utoljára módosítva %d órája, %s által\",\n  \"misc.refinedstorage.last_modified.hours\": \"Utoljára módosítva %d órája, %s által\",\n  \"misc.refinedstorage.last_modified.day\": \"Utoljára módosítva %d napja, %s által\",\n  \"misc.refinedstorage.last_modified.days\": \"Utoljára módosítva %d napja, %s által\",\n  \"misc.refinedstorage.last_modified.week\": \"Utoljára módosítva %d hete, %s által\",\n  \"misc.refinedstorage.last_modified.weeks\": \"Utoljára módosítva %d hete, %s által\",\n  \"misc.refinedstorage.last_modified.year\": \"Utoljára módosítva %d éve, %s által\",\n  \"misc.refinedstorage.last_modified.years\": \"Utoljára módosítva %d éve, %s által\",\n\n  \"sidebutton.refinedstorage.exact_mode\": \"Pontos mód\",\n  \"sidebutton.refinedstorage.exact_mode.on\": \"Be\",\n  \"sidebutton.refinedstorage.exact_mode.off\": \"Ki\",\n\n  \"sidebutton.refinedstorage.redstone_mode\": \"Redstone mód\",\n  \"sidebutton.refinedstorage.redstone_mode.0\": \"Redstone jel figyelmen kívül hagyása\",\n  \"sidebutton.refinedstorage.redstone_mode.1\": \"Csak redstone jellel működjön\",\n  \"sidebutton.refinedstorage.redstone_mode.2\": \"Csak redstone jel nélkül működjön\",\n\n  \"sidebutton.refinedstorage.crafter_mode\": \"Barkácsoló mód\",\n  \"sidebutton.refinedstorage.crafter_mode.0\": \"Redstone jel figyelmen kívül hagyása\",\n  \"sidebutton.refinedstorage.crafter_mode.1\": \"Redstone jel feloldja az autobarkácsolást\",\n  \"sidebutton.refinedstorage.crafter_mode.2\": \"Redstone jel lezárja az autobarkácsolást\",\n  \"sidebutton.refinedstorage.crafter_mode.3\": \"Redstone impulzus beilleszti a következő készletet\",\n\n  \"sidebutton.refinedstorage.grid.view_type\": \"Kijelző\",\n  \"sidebutton.refinedstorage.grid.view_type.0\": \"Normál\",\n  \"sidebutton.refinedstorage.grid.view_type.1\": \"Barkácsolhatók nélkül\",\n  \"sidebutton.refinedstorage.grid.view_type.2\": \"Csak Barkácsolhatók\",\n  \"sidebutton.refinedstorage.grid.sorting.direction\": \"Rendezési irány\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.0\": \"Növekvő\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.1\": \"Csökkenő\",\n  \"sidebutton.refinedstorage.grid.sorting.type\": \"Rendezés módja\",\n  \"sidebutton.refinedstorage.grid.sorting.type.0\": \"Mennyiség\",\n  \"sidebutton.refinedstorage.grid.sorting.type.1\": \"Név\",\n  \"sidebutton.refinedstorage.grid.sorting.type.2\": \"ID\",\n  \"sidebutton.refinedstorage.grid.sorting.type.3\": \"InventoryTweaks\",\n  \"sidebutton.refinedstorage.grid.sorting.type.4\": \"Utoljára módosítva\",\n  \"sidebutton.refinedstorage.grid.search_box_mode\": \"Kereső mező mód\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.0\": \"Normál\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.1\": \"Normál (automatikusan választva)\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.2\": \"JEI szinkronizált\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.3\": \"JEI szinkronizált (automatikusan választva)\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.4\": \"JEI szinkronizált (kétirányú)\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.5\": \"JEI szinkronizált (kétirányú automatikusan választva)\",\n  \"sidebutton.refinedstorage.grid.size\": \"Méret\",\n  \"sidebutton.refinedstorage.grid.size.0\": \"Nyújtott\",\n  \"sidebutton.refinedstorage.grid.size.1\": \"Kicsi\",\n  \"sidebutton.refinedstorage.grid.size.2\": \"Közepes\",\n  \"sidebutton.refinedstorage.grid.size.3\": \"Nagy\",\n\n  \"sidebutton.refinedstorage.mode\": \"Mód\",\n  \"sidebutton.refinedstorage.mode.whitelist\": \"Fehérlista\",\n  \"sidebutton.refinedstorage.mode.blacklist\": \"Feketelista\",\n\n  \"sidebutton.refinedstorage.iomode\": \"IO mód\",\n  \"sidebutton.refinedstorage.iomode.insert\": \"Hálózatba helyezés\",\n  \"sidebutton.refinedstorage.iomode.extract\": \"Hálózatból eltávolítás\",\n\n  \"sidebutton.refinedstorage.type\": \"Típus\",\n  \"sidebutton.refinedstorage.type.0\": \"Tárgyak\",\n  \"sidebutton.refinedstorage.type.1\": \"Folyadékok\",\n\n  \"sidebutton.refinedstorage.detector.mode\": \"Mód\",\n  \"sidebutton.refinedstorage.detector.mode.0\": \"Jel kiadása adott mennyiség alatt\",\n  \"sidebutton.refinedstorage.detector.mode.1\": \"Jel kiadása adott mennyiségnél\",\n  \"sidebutton.refinedstorage.detector.mode.2\": \"Jel kiadása adott mennyiség felett\",\n  \"sidebutton.refinedstorage.constructor.drop\": \"Blokkok kidobása lehelyezés helyett\",\n  \"sidebutton.refinedstorage.destructor.pickup\": \"Tárgyak felvétele eltörés helyett\",\n  \"sidebutton.refinedstorage.access_type\": \"Hozzáférés típusa\",\n  \"sidebutton.refinedstorage.access_type.0\": \"Betétel és kivétel\",\n  \"sidebutton.refinedstorage.access_type.1\": \"Csak betétel\",\n  \"sidebutton.refinedstorage.access_type.2\": \"Csak kivétel\",\n  \"block.refinedstorage.controller\": \"Vezérlő\",\n  \"block.refinedstorage.creative_controller\": \"Kreatív Vezérlő\",\n  \"block.refinedstorage.cable\": \"Kábel\",\n  \"block.refinedstorage.grid\": \"Rács\",\n  \"block.refinedstorage.crafting_grid\": \"Barkácsoló Rács\",\n  \"block.refinedstorage.pattern_grid\": \"Sablon Rács\",\n  \"block.refinedstorage.fluid_grid\": \"Folyadék Rács\",\n  \"block.refinedstorage.disk_drive\": \"Lemez Meghajtó\",\n  \"block.refinedstorage.disk_manipulator\": \"Lemez Kezelő\",\n  \"block.refinedstorage.external_storage\": \"Külső Tárhely\",\n  \"block.refinedstorage.importer\": \"Importáló\",\n  \"block.refinedstorage.exporter\": \"Exportáló\",\n  \"block.refinedstorage.detector\": \"Érzékelő\",\n  \"block.refinedstorage.machine_casing\": \"Gépház\",\n  \"block.refinedstorage.destructor\": \"Megsemmisítő\",\n  \"block.refinedstorage.constructor\": \"Építő\",\n  \"block.refinedstorage.1k_storage_block\": \"1k Tároló Blokk\",\n  \"block.refinedstorage.4k_storage_block\": \"4k Tároló Blokk\",\n  \"block.refinedstorage.16k_storage_block\": \"16k Tároló Blokk\",\n  \"block.refinedstorage.64k_storage_block\": \"64k Tároló Blokk\",\n  \"block.refinedstorage.creative_storage_block\": \"Kreatív Tároló Blokk\",\n  \"block.refinedstorage.relay\": \"Jelfogó\",\n  \"block.refinedstorage.interface\": \"Interfész\",\n  \"block.refinedstorage.crafting_monitor\": \"Barkácsoló Monitor\",\n  \"block.refinedstorage.wireless_transmitter\": \"Vezeték Nélküli Jeladó\",\n  \"block.refinedstorage.crafter\": \"Barkácsoló\",\n  \"block.refinedstorage.network_receiver\": \"Hálózat Jelfogadó\",\n  \"block.refinedstorage.network_transmitter\": \"Hálózat Jeladó\",\n  \"block.refinedstorage.fluid_interface\": \"Folyadék Interfész\",\n  \"block.refinedstorage.64k_fluid_storage_block\": \"64k Folyadék Tároló Blokk\",\n  \"block.refinedstorage.256k_fluid_storage_block\": \"256k Folyadék Tároló Blokk\",\n  \"block.refinedstorage.1024k_fluid_storage_block\": \"1024k Folyadék Tároló Blokk\",\n  \"block.refinedstorage.4096k_fluid_storage_block\": \"4096k Folyadék Tároló Blokk\",\n  \"block.refinedstorage.creative_fluid_storage_block\": \"Kreatív Folyadék Tároló Blokk\",\n  \"block.refinedstorage.security_manager\": \"Biztonsági Menedzser\",\n  \"block.refinedstorage.quartz_enriched_iron_block\": \"Kvarccal Dúsított Vas Blokk\",\n  \"block.refinedstorage.storage_monitor\": \"Tárhely Monitor\",\n  \"block.refinedstorage.portable_grid\": \"Hordozható Rács\",\n  \"block.refinedstorage.creative_portable_grid\": \"Kreatív Hordozható Rács\",\n  \"block.refinedstorage.portable_grid.tooltip\": \"Lopakodj a világban elhelyezéshez.\",\n  \"block.refinedstorage.crafter_manager\": \"Barkácsoló Menedzser\",\n  \"item.refinedstorage.1k_storage_disk\": \"1k Tároló Lemez\",\n  \"item.refinedstorage.4k_storage_disk\": \"4k Tároló Lemez\",\n  \"item.refinedstorage.16k_storage_disk\": \"16k Tároló Lemez\",\n  \"item.refinedstorage.64k_storage_disk\": \"64k Tároló Lemez\",\n  \"item.refinedstorage.creative_storage_disk\": \"Kreatív Tároló Lemez\",\n  \"item.refinedstorage.64k_fluid_storage_disk\": \"64k Folyadék Tároló Lemez\",\n  \"item.refinedstorage.256k_fluid_storage_disk\": \"256k Folyadék Tároló Lemez\",\n  \"item.refinedstorage.1024k_fluid_storage_disk\": \"1024k Folyadék Tároló Lemez\",\n  \"item.refinedstorage.4096k_fluid_storage_disk\": \"4096k Folyadék Tároló Lemez\",\n  \"item.refinedstorage.creative_fluid_storage_disk\": \"Kreatív Folyadék Tároló Lemez\",\n  \"item.refinedstorage.wireless_grid\": \"Vezeték Nélküli Rács\",\n  \"item.refinedstorage.creative_wireless_grid\": \"Kreatív Vezeték Nélküli Rács\",\n  \"item.refinedstorage.wireless_fluid_grid\": \"Vezeték Nélküli Folyadék Rács\",\n  \"item.refinedstorage.creative_wireless_fluid_grid\": \"Kreatív Vezeték Nélküli Folyadék Rács\",\n  \"item.refinedstorage.wireless_crafting_monitor\": \"Vezeték Nélküli Barkácsoló Monitor\",\n  \"item.refinedstorage.creative_wireless_crafting_monitor\": \"Kreatív Vezeték Nélküli Barkácsoló Monitor\",\n  \"item.refinedstorage.quartz_enriched_iron\": \"Kvarccal Dúsított Vas\",\n  \"item.refinedstorage.construction_core\": \"Építő Mag\",\n  \"item.refinedstorage.destruction_core\": \"Megsemmisítő Mag\",\n  \"item.refinedstorage.silicon\": \"Szilikon\",\n  \"item.refinedstorage.raw_basic_processor\": \"Nyers Szimpla Processzor\",\n  \"item.refinedstorage.raw_improved_processor\": \"Nyers Javított Processzor\",\n  \"item.refinedstorage.raw_advanced_processor\": \"Nyers Fejlett Processzor\",\n  \"item.refinedstorage.basic_processor\": \"Szimpla Processzor\",\n  \"item.refinedstorage.improved_processor\": \"Javított Processzor\",\n  \"item.refinedstorage.advanced_processor\": \"Fejlett Processzor\",\n  \"item.refinedstorage.1k_storage_part\": \"1k Tároló Rész\",\n  \"item.refinedstorage.4k_storage_part\": \"4k Tároló Rész\",\n  \"item.refinedstorage.16k_storage_part\": \"16k Tároló Rész\",\n  \"item.refinedstorage.64k_storage_part\": \"64k Tároló Rész\",\n  \"item.refinedstorage.64k_fluid_storage_part\": \"64k Folyadék Tároló Rész\",\n  \"item.refinedstorage.256k_fluid_storage_part\": \"256k Folyadék Tároló Rész\",\n  \"item.refinedstorage.1024k_fluid_storage_part\": \"1024k Folyadék Tároló Rész\",\n  \"item.refinedstorage.4096k_fluid_storage_part\": \"4096k Folyadék Tároló Rész\",\n  \"item.refinedstorage.pattern\": \"Sablon\",\n  \"item.refinedstorage.upgrade\": \"Fejlesztés\",\n  \"item.refinedstorage.range_upgrade\": \"Hatótáv Fejlesztés\",\n  \"item.refinedstorage.speed_upgrade\": \"Sebesség Fejlesztés\",\n  \"item.refinedstorage.crafting_upgrade\": \"Barkácsolás Fejlesztés\",\n  \"item.refinedstorage.stack_upgrade\": \"Stack Fejlesztés\",\n  \"item.refinedstorage.silk_touch_upgrade\": \"Gyengéd Érintés Fejlesztés\",\n  \"item.refinedstorage.fortune_1_upgrade\": \"Szerencse Fejlesztés\",\n  \"item.refinedstorage.fortune_2_upgrade\": \"Szerencse Fejlesztés\",\n  \"item.refinedstorage.fortune_3_upgrade\": \"Szerencse Fejlesztés\",\n  \"item.refinedstorage.regulator_upgrade\": \"Szabályozó Fejlesztés\",\n  \"item.refinedstorage.storage_housing\": \"Tárhely Ház\",\n  \"item.refinedstorage.filter\": \"Szűrő\",\n  \"item.refinedstorage.network_card\": \"Hálózati Kártya\",\n  \"item.refinedstorage.wrench\": \"Villáskulcs\",\n  \"item.refinedstorage.security_card\": \"Biztonsági Kártya\",\n  \"item.refinedstorage.security_card.owner\": \"%s-hoz kötve\",\n  \"item.refinedstorage.processor_binding\": \"Processzor Kötés\",\n  \"item.refinedstorage.cover\": \"Fedő\",\n  \"item.refinedstorage.hollow_cover\": \"Üreges Fedő\",\n  \"commands.refinedstorage.disk.create.error.disk_not_found\": \"%s lemez nem található.\",\n  \"commands.refinedstorage.disk.create.success\": \"%s lemez sikeresen hozzáadva %s-hez.\",\n  \"commands.refinedstorage.network.list.pos\": \"Hálózat X: %d, Y: %d, Z: %d koordinátákon\",\n  \"commands.refinedstorage.network.list.tick_times\": \"Közelítőleges tick idő: %s ms. Közelítőleges TPS: %s\",\n  \"commands.refinedstorage.network.list.autocrafting_tasks\": \"%s folyamatok\",\n  \"commands.refinedstorage.network.list.nodes\": \"%s csomópontok\",\n  \"commands.refinedstorage.network.list.energy_usage\": \"Energia felhasználás: %s\",\n  \"commands.refinedstorage.network.get.error.not_found\": \"Hálózat nem található.\",\n  \"commands.refinedstorage.network.autocrafting.get.error.not_found\": \"Folyamat nem található.\",\n  \"commands.refinedstorage.network.autocrafting.cancel.single\": \"%d folyamat megszakítva.\",\n  \"commands.refinedstorage.network.autocrafting.cancel.multiple\": \"%d folyamat megszakítva.\",\n  \"advancements.refinedstorage.controlling.description\": \"Készíts egy Vezérlőt\",\n  \"advancements.refinedstorage.connecting\": \"Csatlakozás\",\n  \"advancements.refinedstorage.connecting.description\": \"Az összes eszközt egymás mellé teheted hogy csatlakozzanak, vagy használhatsz kábeleket\",\n  \"advancements.refinedstorage.conditional_connecting\": \"Feltételes csatlakozás\",\n  \"advancements.refinedstorage.conditional_connecting.description\": \"Készíts egy jelfogót, hogy irányítsd, hogy egy hálózati jel továbbítható-e redstone-al\",\n  \"advancements.refinedstorage.drives\": \"Meghajtók\",\n  \"advancements.refinedstorage.drives.description\": \"Készíts egy Lemez meghajtót, hogy tárolni tudd a lemezeidet\",\n  \"advancements.refinedstorage.manipulating_disks\": \"Lemezek kezelése\",\n  \"advancements.refinedstorage.manipulating_disks.description\": \"Használj egy Lemez Kezelőt, hogy könnyen módosítsd egy lemez tartalmát\",\n  \"advancements.refinedstorage.storing_items\": \"Tárgyak tárolása\",\n  \"advancements.refinedstorage.storing_items.description\": \"Készíts egy Tároló Lemezt és tedd a Lemez Meghajtóba\",\n  \"advancements.refinedstorage.viewing_items\": \"Tárgyak megnézése\",\n  \"advancements.refinedstorage.viewing_items.description\": \"Készíts egy Rácsot, hogy használhasd a tárhelyedet\",\n  \"advancements.refinedstorage.portable_storage\": \"Hordozható Tárhely\",\n  \"advancements.refinedstorage.portable_storage.description\": \"Készíts egy Hordozható Tárhelyet, hogy hozzáférj tárgyakhoz és folyadékokhoz anélkül, hogy a hálózatban lennél\",\n  \"advancements.refinedstorage.upgrading_your_grid\": \"A Rácsod fejlesztése\",\n  \"advancements.refinedstorage.upgrading_your_grid.description\": \"Fejleszd a Rácsodat egy Barkácsoló Ráccsá, hogy barkácsolhass a Rácsodban\",\n  \"advancements.refinedstorage.storing_fluids\": \"Folyadékok tárolása\",\n  \"advancements.refinedstorage.storing_fluids.description\": \"Készíts egy Folyadék Tároló Lemezt és tedd a Lemez Meghajtóba\",\n  \"advancements.refinedstorage.viewing_fluids\": \"Folyadékok megnézése\",\n  \"advancements.refinedstorage.viewing_fluids.description\": \"Készíts egy Folyadék Rácsot, hogy használhasd a folyadék tárhelyedet\",\n  \"advancements.refinedstorage.better_than_a_barrel\": \"Jobb mint egy hordó\",\n  \"advancements.refinedstorage.better_than_a_barrel.description\": \"Készíts egy Tárhely Monitort, hogy megnézz, kivegyél és betegyél tárgyakat a hálózatba\",\n  \"advancements.refinedstorage.autocrafting\": \"Autobarkácsolás\",\n  \"advancements.refinedstorage.autocrafting.description\": \"Barkácsolj egy Barkácsolót\",\n  \"advancements.refinedstorage.pattern_creation\": \"Sablon készítés\",\n  \"advancements.refinedstorage.pattern_creation.description\": \"Készíts sablonokat egy Sablon Ráccsal és egy üres Sablonnal\",\n  \"advancements.refinedstorage.monitoring\": \"Monitorozás\",\n  \"advancements.refinedstorage.monitoring.description\": \"Nézd meg a barkácsoló folyamataid állapotát a Barkácsoló Monitorban\",\n  \"advancements.refinedstorage.managing_patterns\": \"Sablonok kezelése\",\n  \"advancements.refinedstorage.managing_patterns.description\": \"Készíts egy Barkácsoló Menedzsert, hogy egy jobb módon kezeld a sablonjaidat\",\n  \"advancements.refinedstorage.importing\": \"Importálás\",\n  \"advancements.refinedstorage.importing.description\": \"Tegyél tárgyakat vagy folyadékokat a tároló hálózatba egy Importálóval\",\n  \"advancements.refinedstorage.destruction\": \"Megsemmisítés\",\n  \"advancements.refinedstorage.destruction.description\": \"Tegyél tárgyakat vagy folyadékokat a tároló hálózatba egy Megsemmisítővel\",\n  \"advancements.refinedstorage.exporting\": \"Exportálás\",\n  \"advancements.refinedstorage.exporting.description\": \"Vegyél ki tárgyakat vagy folyadékokat a tároló hálózatból egy Exportálóval\",\n  \"advancements.refinedstorage.construction\": \"Építés\",\n  \"advancements.refinedstorage.construction.description\": \"Vegyél ki tárgyakat vagy folyadékokat a tároló hálózatból egy Építővel\",\n  \"advancements.refinedstorage.security\": \"Biztonság\",\n  \"advancements.refinedstorage.security.description\": \"Biztosítsd a hálózatodat egy Biztonsági Menedzserrel és egy Biztonsági Kártyával\",\n  \"advancements.refinedstorage.wireless\": \"Vezeték Nélküli\",\n  \"advancements.refinedstorage.wireless.description\": \"Továbbíts egy hálózati jelet egy Vezeték Nélküli Jeladóval\",\n  \"advancements.refinedstorage.wireless_items\": \"Vezeték nélküli tárgyak\",\n  \"advancements.refinedstorage.wireless_items.description\": \"Használd a tárolt tárgyaidat egy Vezeték Nélküli Ráccsal\",\n  \"advancements.refinedstorage.wireless_fluids\": \"Vezeték nélküli folyadékok\",\n  \"advancements.refinedstorage.wireless_fluids.description\": \"Használd a tárolt folyadékaidat egy Vezeték Nélküli Folyadék Ráccsal\",\n  \"advancements.refinedstorage.wireless_monitoring\": \"Vezeték nélküli menedzselés\",\n  \"advancements.refinedstorage.wireless_monitoring.description\": \"Nézd meg a barkácsoló folyamataid állapotát egy Vezeték Nélküli Barkácsolás Menedzserrel\",\n  \"advancements.refinedstorage.no_cables_required\": \"Nincs szükség kábelekre\",\n  \"advancements.refinedstorage.no_cables_required.description\": \"Adj extra komponenseket a hálózatodhoz vezetékek nélkül egy Hálózati Jeladó, Hálózati Jelfogadó és Hálózati Kártya használatával\",\n  \"advancements.refinedstorage.upgrading\": \"Fejlesztés\",\n  \"advancements.refinedstorage.upgrading.description\": \"Készíts egy Fejlesztést, hogy javíts az egyik eszközödön\",\n  \"advancements.refinedstorage.crafting_on_demand\": \"Kérésre barkácsolás\",\n  \"advancements.refinedstorage.crafting_on_demand.description\": \"Használj egy Barkácsoló Fejlesztést egy Interfészben, Exportálóban vagy Építőben hogy szükség szerint készíts tárgyakat és blokkokat\",\n  \"advancements.refinedstorage.detecting\": \"Érzékelés\",\n  \"advancements.refinedstorage.detecting.description\": \"Érzékelj Tárgyakat és Folyadékokat a hálózatban egy Érzékelővel\",\n  \"advancements.refinedstorage.interface_to_the_world\": \"Interfész a világhoz\",\n  \"advancements.refinedstorage.interface_to_the_world.description\": \"Exportálj és Importálj tárgyakat egyszerre egy Interfésszel\",\n  \"advancements.refinedstorage.storing_externally\": \"Kívül tárolva\",\n  \"advancements.refinedstorage.storing_externally.description\": \"Használj egy Külső Tárhelyet, hogy tárhelyet niztosíts a hálózatnak egy külső blokkból, mint például egy láda\"\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/lang/it_it.json",
    "content": "{\n  \"itemGroup.refinedstorage\": \"Stoccaggio raffinato\",\n  \"itemGroup.refinedstorage.covers\": \"Coperture di Stoccaggio raffinato\",\n  \"key.refinedstorage.focusSearchBar\": \"Metti a fuoco la barra di ricerca della griglia\",\n  \"key.refinedstorage.clearGridCraftingMatrix\": \"Pulisci la matrice di fabbricazione della griglia\",\n  \"key.refinedstorage.openWirelessGrid\": \"Apri Griglia wireless\",\n  \"key.refinedstorage.openWirelessFluidGrid\": \"Apri Griglia fluidi wireless\",\n  \"key.refinedstorage.openPortableGrid\": \"Apri Griglia portatile\",\n  \"key.refinedstorage.openWirelessCraftingMonitor\": \"Apri il monitor di fabbricazione wireless\",\n  \"gui.refinedstorage.controller\": \"Regolatore\",\n  \"gui.refinedstorage.creative_controller\": \"Regolatore creativo\",\n  \"gui.refinedstorage.grid\": \"Griglia\",\n  \"gui.refinedstorage.grid.craft\": \"Fabbrica\",\n  \"gui.refinedstorage.crafting_grid\": \"Griglia di fabbricazione\",\n  \"gui.refinedstorage.pattern_grid\": \"Griglia di modellazione\",\n  \"gui.refinedstorage.grid.pattern_create\": \"Crea\",\n  \"gui.refinedstorage.fluid_grid\": \"Griglia fluidi\",\n  \"gui.refinedstorage.portable_grid\": \"Griglia portatile\",\n  \"gui.refinedstorage.item_amount\": \"Quantità oggetto\",\n  \"gui.refinedstorage.fluid_amount\": \"Quantità di fluido in mB\",\n  \"gui.refinedstorage.disk_drive\": \"Unità disco\",\n  \"gui.refinedstorage.disk_drive.disks\": \"Dischi\",\n  \"gui.refinedstorage.disk_manipulator\": \"Manipolatore di dischi\",\n  \"gui.refinedstorage.disk_manipulator.in\": \"In\",\n  \"gui.refinedstorage.disk_manipulator.out\": \"Out\",\n  \"gui.refinedstorage.external_storage\": \"Archiviazione esterna\",\n  \"gui.refinedstorage.importer\": \"Importatore\",\n  \"gui.refinedstorage.exporter\": \"Esportatore\",\n  \"gui.refinedstorage.detector\": \"Rilevatore\",\n  \"gui.refinedstorage.destructor\": \"Distruttore\",\n  \"gui.refinedstorage.constructor\": \"Costruttore\",\n  \"gui.refinedstorage.relay\": \"Relè\",\n  \"gui.refinedstorage.interface.import\": \"Importazione interfaccia\",\n  \"gui.refinedstorage.interface.export\": \"Esportazione interfaccia\",\n  \"gui.refinedstorage.crafting_monitor\": \"Monitor di fabbricazione\",\n  \"gui.refinedstorage.wireless_crafting_monitor\": \"Monitor di fabbricazione wireless\",\n  \"gui.refinedstorage.crafting_monitor.tooltip.requested\": \"%d richiesto\",\n  \"gui.refinedstorage.crafting_monitor.stored\": \"Immagazzinato: %d\",\n  \"gui.refinedstorage.crafting_monitor.missing\": \"Mancante: %d\",\n  \"gui.refinedstorage.crafting_monitor.processing\": \"Elaborazione: %d\",\n  \"gui.refinedstorage.crafting_monitor.scheduled\": \"In programma: %d\",\n  \"gui.refinedstorage.crafting_monitor.crafting\": \"Fabbricazione: %d\",\n  \"gui.refinedstorage.crafting_monitor.machine_does_not_accept_item\": \"La macchina non accetta l'oggetto\",\n  \"gui.refinedstorage.crafting_monitor.machine_does_not_accept_fluid\": \"La macchina non accetta il fluido\",\n  \"gui.refinedstorage.crafting_monitor.machine_none\": \"Nessuna macchina trovata\",\n  \"gui.refinedstorage.crafting_monitor.crafter_is_locked\": \"Il fabbricatore è bloccato\",\n  \"gui.refinedstorage.wireless_transmitter\": \"Trasmettitore wireless\",\n  \"gui.refinedstorage.wireless_transmitter.distance\": \"%d blocco(i)\",\n  \"gui.refinedstorage.crafter\": \"Fabbricatore\",\n  \"gui.refinedstorage.filter\": \"Filtro\",\n  \"gui.refinedstorage.filter.compare_nbt\": \"NBT\",\n  \"gui.refinedstorage.filter.mod_filter\": \"Filtro mod\",\n  \"gui.refinedstorage.network_transmitter\": \"Trasmettitore di rete\",\n  \"gui.refinedstorage.network_transmitter.distance\": \"%d blocco(i)\",\n  \"gui.refinedstorage.network_transmitter.missing_card\": \"Scheda di rete mancante\",\n  \"gui.refinedstorage.fluid_interface\": \"Interfaccia fluidi\",\n  \"gui.refinedstorage.fluid_interface.in\": \"In\",\n  \"gui.refinedstorage.fluid_interface.out\": \"Out\",\n  \"gui.refinedstorage.crafting_preview\": \"Anteprima della fabbricazione\",\n  \"gui.refinedstorage.crafting_preview.to_craft\": \"Da fabbricare: %d\",\n  \"gui.refinedstorage.crafting_preview.available\": \"Disponibile: %d\",\n  \"gui.refinedstorage.crafting_preview.missing\": \"Mancante: %d\",\n  \"gui.refinedstorage.crafting_preview.error\": \"Richiesta fallita\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.0\": \"Uno degli ingredienti della fabbricazione ha finito per aver bisogno di\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.1\": \"se stesso.\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.2\": \"È necessario rimuovere il modello o assicurarsi che\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.3\": \"il modello non viene utilizzato durante la fabbricazione.\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.4\": \"Modello offensivo:\",\n  \"gui.refinedstorage.crafting_preview.error.too_complex.0\": \"Il calcolo dell'attività di fabbricazione era troppo complesso\",\n  \"gui.refinedstorage.crafting_preview.error.too_complex.1\": \"ed è stato fermato per evitare lo sforzo del server.\",\n  \"gui.refinedstorage.security_manager\": \"Responsabile della sicurezza\",\n  \"gui.refinedstorage.security_manager.configure\": \"Configura\",\n  \"gui.refinedstorage.security_manager.permission.0\": \"Inserisci\",\n  \"gui.refinedstorage.security_manager.permission.0.tooltip\": \"Inserimento di oggetti o fluidi nella rete\",\n  \"gui.refinedstorage.security_manager.permission.1\": \"Estrazione\",\n  \"gui.refinedstorage.security_manager.permission.1.tooltip\": \"Estrai oggetti o fluidi dalla rete\",\n  \"gui.refinedstorage.security_manager.permission.2\": \"Fabbricazione automatica\",\n  \"gui.refinedstorage.security_manager.permission.2.tooltip\": \"Avviare, cancellare e visualizzare le attività di fabbricazione\",\n  \"gui.refinedstorage.security_manager.permission.3\": \"Modifica\",\n  \"gui.refinedstorage.security_manager.permission.3.tooltip\": \"Blocchi di apertura\",\n  \"gui.refinedstorage.security_manager.permission.4\": \"Costruisci\",\n  \"gui.refinedstorage.security_manager.permission.4.tooltip\": \"Aggiungi o rimuovi dispositivi alla o dalla rete\",\n  \"gui.refinedstorage.security_manager.permission.5\": \"Sicurezza\",\n  \"gui.refinedstorage.security_manager.permission.5.tooltip\": \"Possibilità di cambiare le opzioni di sicurezza\",\n  \"gui.refinedstorage.storage_monitor\": \"Monitor di archiviazione\",\n  \"gui.refinedstorage.crafter_manager\": \"Gestore dei fabbricatori\",\n  \"gui.refinedstorage.alternatives\": \"Alternative\",\n  \"gui.refinedstorage.alternatives.apply\": \"Applica\",\n  \"gui.refinedstorage.jei.transfer.autocrafting_available\": \"Fabbricazione automatica disponibile\",\n  \"gui.refinedstorage.jei.transfer.request_autocrafting\": \"CTRL + CLICK per richiedere la fabbricazione automatica\",\n  \"gui.refinedstorage.jei.transfer.request_autocrafting_mac\": \"CMD + CLICK per richiedere la fabbricazione automatica\",\n  \"misc.refinedstorage.energy_stored\": \"%d / %d FE\",\n  \"misc.refinedstorage.energy_usage\": \"Utilizzo: %d FE/t\",\n  \"misc.refinedstorage.energy_usage_minimal\": \"%d FE/t\",\n  \"misc.refinedstorage.storage.stored\": \"Immagazzinato: %s\",\n  \"misc.refinedstorage.storage.stored_capacity\": \"Immagazinato: %s / %s\",\n  \"misc.refinedstorage.storage.stored_minimal\": \"%s\",\n  \"misc.refinedstorage.storage.stored_capacity_minimal\": \"%s / %s\",\n  \"misc.refinedstorage.storage.full\": \"%d%% pieno\",\n  \"misc.refinedstorage.network_item.tooltip\": \"Collegato a %d, %d, %d.\",\n  \"misc.refinedstorage.network_item.out_of_range\": \"Non c'è nessun trasmettitore wireless nel raggio d'azione.\",\n  \"misc.refinedstorage.network_item.not_found\": \"Rete non trovata.\",\n  \"misc.refinedstorage.network_item.shortcut_not_found\": \"Non c'è nessun %s nel tuo inventario.\",\n  \"misc.refinedstorage.network_item.shortcut_duplicate\": \"C'è più di un %s nel tuo inventario.\",\n  \"misc.refinedstorage.network_item.out_of_energy\": \"Il %s non ha più energia.\",\n  \"misc.refinedstorage.network_card.tooltip\": \"Collegato a %d, %d, %d in %s.\",\n  \"misc.refinedstorage.pattern.inputs\": \"Input\",\n  \"misc.refinedstorage.pattern.outputs\": \"Output\",\n  \"misc.refinedstorage.pattern.invalid\": \"Pattern non valido\",\n  \"misc.refinedstorage.pattern.exact\": \"Utilizza la modalità esatta\",\n  \"misc.refinedstorage.pattern.allowed_item_tag\": \"Utilizza oggetti da %s per %s\",\n  \"misc.refinedstorage.pattern.allowed_fluid_tag\": \"Utilizza i fluidi da %s per %s\",\n  \"misc.refinedstorage.pattern.error.processing_no_outputs\": \"Il modello di elaborazione non ha output\",\n  \"misc.refinedstorage.pattern.error.no_output\": \"La ricetta non ha output\",\n  \"misc.refinedstorage.pattern.error.recipe_does_not_exist\": \"La ricetta non esiste\",\n  \"misc.refinedstorage.pattern.error.tag_no_longer_applicable\": \"Il tag %s non è più applicabile per %s\",\n  \"misc.refinedstorage.security.no_permission\": \"Non hai il permesso di eseguire quell'azione.\",\n  \"misc.refinedstorage.start\": \"Avvia\",\n  \"misc.refinedstorage.clear\": \"Azzera\",\n  \"misc.refinedstorage.set\": \"Imposta\",\n  \"misc.refinedstorage.cancel_all\": \"Annulla tutto\",\n  \"misc.refinedstorage.priority\": \"Priorità\",\n  \"misc.refinedstorage.exact\": \"Esatto\",\n  \"misc.refinedstorage.processing\": \"Elaborazione\",\n  \"misc.refinedstorage.total\": \"%s totale\",\n  \"misc.refinedstorage.last_modified.just_now\": \"Ultima modifica di poco fa da %s\",\n  \"misc.refinedstorage.last_modified.second\": \"Ultima modifica %d secondo fa da %s\",\n  \"misc.refinedstorage.last_modified.seconds\": \"Ultima modifica %d secondi fa da %s\",\n  \"misc.refinedstorage.last_modified.minute\": \"Ultima modifica %d minuto fa da %s\",\n  \"misc.refinedstorage.last_modified.minutes\": \"Ultima modifica %d minuti fa da %s\",\n  \"misc.refinedstorage.last_modified.hour\": \"Ultima modifica %d ora fa da %s\",\n  \"misc.refinedstorage.last_modified.hours\": \"Ultima modifica %d ore fa da %s\",\n  \"misc.refinedstorage.last_modified.day\": \"Ultima modifica %d giorno fa da %s\",\n  \"misc.refinedstorage.last_modified.days\": \"Ultima modifica %d giorni fa da %s\",\n  \"misc.refinedstorage.last_modified.week\": \"Ultima modifica %d settimana fa da %s\",\n  \"misc.refinedstorage.last_modified.weeks\": \"Ultima modifica %d settimane fa da %s\",\n  \"misc.refinedstorage.last_modified.year\": \"Ultima modifica %d anno fa da %s\",\n  \"misc.refinedstorage.last_modified.years\": \"Ultima modifica %d anni fa da %s\",\n  \"sidebutton.refinedstorage.exact_mode\": \"Modalità esatta\",\n  \"sidebutton.refinedstorage.exact_mode.on\": \"On\",\n  \"sidebutton.refinedstorage.exact_mode.off\": \"Off\",\n  \"sidebutton.refinedstorage.redstone_mode\": \"Modalità di Redstone\",\n  \"sidebutton.refinedstorage.redstone_mode.0\": \"Ignora segnale di redstone\",\n  \"sidebutton.refinedstorage.redstone_mode.1\": \"Funziona solo con un segnale di redstone\",\n  \"sidebutton.refinedstorage.redstone_mode.2\": \"Funziona solo senza un segnale di redstone\",\n  \"sidebutton.refinedstorage.crafter_mode\": \"Modalità Fabbricatore\",\n  \"sidebutton.refinedstorage.crafter_mode.0\": \"Ignora segnale di redstone\",\n  \"sidebutton.refinedstorage.crafter_mode.1\": \"Il segnale di redstone sblocca la fabbricazione automatica\",\n  \"sidebutton.refinedstorage.crafter_mode.2\": \"Il segnale di redstone blocca la fabbricazione automatica\",\n  \"sidebutton.refinedstorage.crafter_mode.3\": \"L'impulso di redstone inserisce il prossimo set\",\n  \"sidebutton.refinedstorage.grid.view_type\": \"Visualizzazione\",\n  \"sidebutton.refinedstorage.grid.view_type.0\": \"Normale\",\n  \"sidebutton.refinedstorage.grid.view_type.1\": \"Nessuno fabbricabile\",\n  \"sidebutton.refinedstorage.grid.view_type.2\": \"Solo i fabbricabili\",\n  \"sidebutton.refinedstorage.grid.sorting.direction\": \"Direzione di ordinamento\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.0\": \"Crescente\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.1\": \"Decrescente\",\n  \"sidebutton.refinedstorage.grid.sorting.type\": \"Tipo di ordinamento\",\n  \"sidebutton.refinedstorage.grid.sorting.type.0\": \"Quantità\",\n  \"sidebutton.refinedstorage.grid.sorting.type.1\": \"Nome\",\n  \"sidebutton.refinedstorage.grid.sorting.type.2\": \"ID\",\n  \"sidebutton.refinedstorage.grid.sorting.type.3\": \"InventoryTweaks\",\n  \"sidebutton.refinedstorage.grid.sorting.type.4\": \"Ultima modifica\",\n  \"sidebutton.refinedstorage.grid.search_box_mode\": \"Modalità casella di ricerca\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.0\": \"Normale\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.1\": \"Normale (autoselezionato)\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.2\": \"Sincronizzato con JEI\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.3\": \"Sincronizzato con JEI (autoselezionato)\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.4\": \"Sincronizzato con JEI (bidirezionale)\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.5\": \"Sincronizzato con JEI (autoselezione bidirezionale)\",\n  \"sidebutton.refinedstorage.grid.size\": \"Dimensione\",\n  \"sidebutton.refinedstorage.grid.size.0\": \"Allungato\",\n  \"sidebutton.refinedstorage.grid.size.1\": \"Piccolo\",\n  \"sidebutton.refinedstorage.grid.size.2\": \"Medio\",\n  \"sidebutton.refinedstorage.grid.size.3\": \"Grande\",\n  \"sidebutton.refinedstorage.mode\": \"Modalità\",\n  \"sidebutton.refinedstorage.mode.whitelist\": \"Lista bianca\",\n  \"sidebutton.refinedstorage.mode.blacklist\": \"Lista nera\",\n  \"sidebutton.refinedstorage.iomode\": \"Modalità IO\",\n  \"sidebutton.refinedstorage.iomode.insert\": \"Inserire nella rete\",\n  \"sidebutton.refinedstorage.iomode.extract\": \"Estrai dalla rete\",\n  \"sidebutton.refinedstorage.type\": \"Tipo\",\n  \"sidebutton.refinedstorage.type.0\": \"Oggetti\",\n  \"sidebutton.refinedstorage.type.1\": \"Fluidi\",\n  \"sidebutton.refinedstorage.detector.mode\": \"Modalità\",\n  \"sidebutton.refinedstorage.detector.mode.0\": \"Emetti il segnale quando è inferiore alla quantità\",\n  \"sidebutton.refinedstorage.detector.mode.1\": \"Emetti il segnale quando si arriva alla quantità\",\n  \"sidebutton.refinedstorage.detector.mode.2\": \"Emetti il segnale quando si supera la quantità\",\n  \"sidebutton.refinedstorage.constructor.drop\": \"Rilascia i blocchi invece di posizionarli\",\n  \"sidebutton.refinedstorage.destructor.pickup\": \"Raccogli oggetti invece di romperli\",\n  \"sidebutton.refinedstorage.access_type\": \"Tipo di accesso\",\n  \"sidebutton.refinedstorage.access_type.0\": \"Inserisci ed estrai\",\n  \"sidebutton.refinedstorage.access_type.1\": \"Inserisci solo\",\n  \"sidebutton.refinedstorage.access_type.2\": \"Estrai solo\",\n  \"block.refinedstorage.controller\": \"Regolatore\",\n  \"block.refinedstorage.creative_controller\": \"Regolatore creativo\",\n  \"block.refinedstorage.cable\": \"Cavo\",\n  \"block.refinedstorage.grid\": \"Griglia\",\n  \"block.refinedstorage.crafting_grid\": \"Griglia di fabbricazione\",\n  \"block.refinedstorage.pattern_grid\": \"Griglia di modellazione\",\n  \"block.refinedstorage.fluid_grid\": \"Griglia fluidi\",\n  \"block.refinedstorage.disk_drive\": \"Unità disco\",\n  \"block.refinedstorage.disk_manipulator\": \"Manipolatore di dischi\",\n  \"block.refinedstorage.external_storage\": \"Archiviazione esterna\",\n  \"block.refinedstorage.importer\": \"Importatore\",\n  \"block.refinedstorage.exporter\": \"Esportatore\",\n  \"block.refinedstorage.detector\": \"Rilevatore\",\n  \"block.refinedstorage.machine_casing\": \"Involucro della macchina\",\n  \"block.refinedstorage.destructor\": \"Distruttore\",\n  \"block.refinedstorage.constructor\": \"Costruttore\",\n  \"block.refinedstorage.1k_storage_block\": \"Blocco di memoria da 1k\",\n  \"block.refinedstorage.4k_storage_block\": \"Blocco di memoria da 4k\",\n  \"block.refinedstorage.16k_storage_block\": \"Blocco di memoria da 16k\",\n  \"block.refinedstorage.64k_storage_block\": \"Blocco di memoria da 64k\",\n  \"block.refinedstorage.creative_storage_block\": \"Blocco di memoria creativo\",\n  \"block.refinedstorage.relay\": \"Relè\",\n  \"block.refinedstorage.interface\": \"Interfaccia\",\n  \"block.refinedstorage.crafting_monitor\": \"Monitor di fabbricazione\",\n  \"block.refinedstorage.wireless_transmitter\": \"Trasmettitore wireless\",\n  \"block.refinedstorage.crafter\": \"Fabbricatore\",\n  \"block.refinedstorage.network_receiver\": \"Ricevitore di rete\",\n  \"block.refinedstorage.network_transmitter\": \"Trasmettitore di rete\",\n  \"block.refinedstorage.fluid_interface\": \"Interfaccia fluidi\",\n  \"block.refinedstorage.64k_fluid_storage_block\": \"Blocco di memoria fluida da 64k\",\n  \"block.refinedstorage.256k_fluid_storage_block\": \"Blocco di memoria fluida da 256k\",\n  \"block.refinedstorage.1024k_fluid_storage_block\": \"Blocco di memoria fluida da 1024k\",\n  \"block.refinedstorage.4096k_fluid_storage_block\": \"Blocco di memoria fluida da 4096k\",\n  \"block.refinedstorage.creative_fluid_storage_block\": \"Blocco di memoria fluida creativa\",\n  \"block.refinedstorage.security_manager\": \"Responsabile della sicurezza\",\n  \"block.refinedstorage.quartz_enriched_iron_block\": \"Blocco di ferro arricchito di quarzo\",\n  \"block.refinedstorage.storage_monitor\": \"Monitor di archiviazione\",\n  \"block.refinedstorage.portable_grid\": \"Griglia portatile\",\n  \"block.refinedstorage.creative_portable_grid\": \"Griglia portatile creativa\",\n  \"block.refinedstorage.portable_grid.tooltip\": \"Accovacciati per posizionare nel mondo.\",\n  \"block.refinedstorage.crafter_manager\": \"Gestore dei fabbricatori\",\n  \"item.refinedstorage.1k_storage_disk\": \"Disco di archiviazione da 1k\",\n  \"item.refinedstorage.4k_storage_disk\": \"Disco di archiviazione 4k\",\n  \"item.refinedstorage.16k_storage_disk\": \"Disco di archiviazione da 16k\",\n  \"item.refinedstorage.64k_storage_disk\": \"Disco di archiviazione da 64k\",\n  \"item.refinedstorage.creative_storage_disk\": \"Disco di archiviazione creativo\",\n  \"item.refinedstorage.64k_fluid_storage_disk\": \"Disco di archiviazione fluido da 64k\",\n  \"item.refinedstorage.256k_fluid_storage_disk\": \"Disco di archiviazione fluido da 256k\",\n  \"item.refinedstorage.1024k_fluid_storage_disk\": \"Disco di archiviazione fluido da 1024k\",\n  \"item.refinedstorage.4096k_fluid_storage_disk\": \"Disco di archiviazione fluido da 4096k\",\n  \"item.refinedstorage.creative_fluid_storage_disk\": \"Disco di archiviazione fluido creativo\",\n  \"item.refinedstorage.wireless_grid\": \"Griglia wireless\",\n  \"item.refinedstorage.creative_wireless_grid\": \"Griglia wireless creativa\",\n  \"item.refinedstorage.wireless_fluid_grid\": \"Griglia fluida wireless\",\n  \"item.refinedstorage.creative_wireless_fluid_grid\": \"Griglia fluida wireless creativa\",\n  \"item.refinedstorage.wireless_crafting_monitor\": \"Monitor di fabbricazione wireless\",\n  \"item.refinedstorage.creative_wireless_crafting_monitor\": \"Monitor fabbricazione wireless creativo\",\n  \"item.refinedstorage.quartz_enriched_iron\": \"Ferro arricchito di quarzo\",\n  \"item.refinedstorage.construction_core\": \"Nucleo di costruzione\",\n  \"item.refinedstorage.destruction_core\": \"Nucleo di distruzione\",\n  \"item.refinedstorage.silicon\": \"Silicio\",\n  \"item.refinedstorage.raw_basic_processor\": \"Processore di base grezzo\",\n  \"item.refinedstorage.raw_improved_processor\": \"Processore migliorato grezzo\",\n  \"item.refinedstorage.raw_advanced_processor\": \"Processore avanzato grezzo\",\n  \"item.refinedstorage.basic_processor\": \"Processore di base\",\n  \"item.refinedstorage.improved_processor\": \"Processore migliorato\",\n  \"item.refinedstorage.advanced_processor\": \"Processore avanzato\",\n  \"item.refinedstorage.1k_storage_part\": \"Parte di archiviazione da 1k\",\n  \"item.refinedstorage.4k_storage_part\": \"Parte di archiviazione da 4k\",\n  \"item.refinedstorage.16k_storage_part\": \"Parte di archiviazione da 16k\",\n  \"item.refinedstorage.64k_storage_part\": \"Parte di archiviazione da 64k\",\n  \"item.refinedstorage.64k_fluid_storage_part\": \"Parte di archiviazione fluida da 64k\",\n  \"item.refinedstorage.256k_fluid_storage_part\": \"Parte di archiviazione fluida da 256k\",\n  \"item.refinedstorage.1024k_fluid_storage_part\": \"Parte di archiviazione fluida da 1024k\",\n  \"item.refinedstorage.4096k_fluid_storage_part\": \"Parte di archiviazione fluida da 4096k\",\n  \"item.refinedstorage.pattern\": \"Modello\",\n  \"item.refinedstorage.upgrade\": \"Potenziamento\",\n  \"item.refinedstorage.range_upgrade\": \"Potenziamento raggio\",\n  \"item.refinedstorage.speed_upgrade\": \"Potenziamento velocità\",\n  \"item.refinedstorage.crafting_upgrade\": \"Potenziamento fabbricazione\",\n  \"item.refinedstorage.stack_upgrade\": \"Potenziamento stack\",\n  \"item.refinedstorage.silk_touch_upgrade\": \"Potenziamento Tocco di velluto\",\n  \"item.refinedstorage.fortune_1_upgrade\": \"Potenziamento Fortuna\",\n  \"item.refinedstorage.fortune_2_upgrade\": \"Potenziamento Fortuna\",\n  \"item.refinedstorage.fortune_3_upgrade\": \"Potenziamento Fortuna\",\n  \"item.refinedstorage.regulator_upgrade\": \"Potenziamento regolatore\",\n  \"item.refinedstorage.storage_housing\": \"Custodia di archiviazione\",\n  \"item.refinedstorage.filter\": \"Filtro\",\n  \"item.refinedstorage.network_card\": \"Scheda di rete\",\n  \"item.refinedstorage.wrench\": \"Chiave inglese\",\n  \"item.refinedstorage.security_card\": \"Scheda di sicurezza\",\n  \"item.refinedstorage.security_card.owner\": \"Associato a: %s\",\n  \"item.refinedstorage.processor_binding\": \"Legatura del processore\",\n  \"commands.refinedstorage.disk.create.error.disk_not_found\": \"Il disco %s non è stato trovato.\",\n  \"commands.refinedstorage.disk.create.success\": \"Dato con successo il disco %s a %s.\",\n  \"commands.refinedstorage.network.list.pos\": \"Rete a X: %d, Y: %d, Z: %d\",\n  \"commands.refinedstorage.network.list.tick_times\": \"Tempo medio di tick: %s ms. TPS medio: %s\",\n  \"commands.refinedstorage.network.list.autocrafting_tasks\": \"%s attività\",\n  \"commands.refinedstorage.network.list.nodes\": \"%s nodi\",\n  \"commands.refinedstorage.network.list.energy_usage\": \"Consumo energetico: %s\",\n  \"commands.refinedstorage.network.get.error.not_found\": \"Rete non trovata.\",\n  \"commands.refinedstorage.network.autocrafting.get.error.not_found\": \"Attività non trovata.\",\n  \"commands.refinedstorage.network.autocrafting.cancel.single\": \"Attività %d annullata.\",\n  \"commands.refinedstorage.network.autocrafting.cancel.multiple\": \"%d attività annullate.\",\n  \"advancements.refinedstorage.controlling.description\": \"Fabbrica un regolatore\",\n  \"advancements.refinedstorage.connecting\": \"Connessione in corso\",\n  \"advancements.refinedstorage.connecting.description\": \"Si possono mettere tutti i dispositivi uno accanto all'altro per collegarli, oppure, utilizzare dei Cavi\",\n  \"advancements.refinedstorage.conditional_connecting\": \"Collegamento condizionale\",\n  \"advancements.refinedstorage.conditional_connecting.description\": \"Fabbrica un relè per controllare se un segnale di rete può passare con la redstone\",\n  \"advancements.refinedstorage.drives\": \"Unità\",\n  \"advancements.refinedstorage.drives.description\": \"Fabbrica un'unità disco per poter conservare i tuoi dischi\",\n  \"advancements.refinedstorage.manipulating_disks\": \"Manipolazione dei dischi\",\n  \"advancements.refinedstorage.manipulating_disks.description\": \"Utilizza un manipolatore di dischi per modificare facilmente il contenuto dei dischi\",\n  \"advancements.refinedstorage.storing_items\": \"Archiviazione di oggetti\",\n  \"advancements.refinedstorage.storing_items.description\": \"Crea un disco di archiviazione e mettilo nell'unità disco\",\n  \"advancements.refinedstorage.viewing_items\": \"Visualizzazione degli oggetti\",\n  \"advancements.refinedstorage.viewing_items.description\": \"Fabbrica una griglia per interagire con lo spazio di archiviazione degli oggetti\",\n  \"advancements.refinedstorage.portable_storage\": \"Archiviazione portatile\",\n  \"advancements.refinedstorage.portable_storage.description\": \"Fabbrica una Griglia portatile per accedere a oggetti e fluidi nei dischi senza essere in una rete\",\n  \"advancements.refinedstorage.upgrading_your_grid\": \"Potenziamento della tua Griglia\",\n  \"advancements.refinedstorage.upgrading_your_grid.description\": \"Potenzia la tua griglia in una Griglia di fabbricazione per ottenere abilità di fabbricazione nella tua griglia\",\n  \"advancements.refinedstorage.storing_fluids\": \"Archiviazione dei fluidi\",\n  \"advancements.refinedstorage.storing_fluids.description\": \"Crea un disco di archiviazione fluido e mettilo nell'unità disco\",\n  \"advancements.refinedstorage.viewing_fluids\": \"Visualizzazione dei fluidi\",\n  \"advancements.refinedstorage.viewing_fluids.description\": \"Fabbrica una Griglia fluida per interagire con lo spazio di archiviazione degli oggetti\",\n  \"advancements.refinedstorage.better_than_a_barrel\": \"Meglio di un barile\",\n  \"advancements.refinedstorage.better_than_a_barrel.description\": \"Fabbrica un Monitor di archiviazione per visualizzare, inserire o estrarre elementi di una rete\",\n  \"advancements.refinedstorage.autocrafting\": \"Fabbricazione automatica\",\n  \"advancements.refinedstorage.autocrafting.description\": \"Fabbrica un Fabbricatore\",\n  \"advancements.refinedstorage.pattern_creation\": \"Creazione di modello\",\n  \"advancements.refinedstorage.pattern_creation.description\": \"Fabbrica modelli con una Griglia di modellazione e un Modello\",\n  \"advancements.refinedstorage.monitoring\": \"Controllo\",\n  \"advancements.refinedstorage.monitoring.description\": \"Controlla lo stato delle tue attività di fabbricazione con il Monitor di Fabbricazione\",\n  \"advancements.refinedstorage.managing_patterns\": \"Gestione dei modelli\",\n  \"advancements.refinedstorage.managing_patterns.description\": \"Fabbrica un Gestore dei fabbricatori per gestire meglio i tuoi modelli\",\n  \"advancements.refinedstorage.importing\": \"Importazione in corso\",\n  \"advancements.refinedstorage.importing.description\": \"Introduci oggetti o fluidi nella rete di archiviazione con un Importatore\",\n  \"advancements.refinedstorage.destruction\": \"Distruzione\",\n  \"advancements.refinedstorage.destruction.description\": \"Introduci blocchi o fluidi nella rete di archiviazione con un Distruttore\",\n  \"advancements.refinedstorage.exporting\": \"Esportazione in corso\",\n  \"advancements.refinedstorage.exporting.description\": \"Estrai oggetti o fluidi dalla rete di archiviazione con un Esportatore\",\n  \"advancements.refinedstorage.construction\": \"Costruzione\",\n  \"advancements.refinedstorage.construction.description\": \"Estrai blocchi o fluidi dalla rete di archiviazione con un Costruttore\",\n  \"advancements.refinedstorage.security\": \"Sicurezza\",\n  \"advancements.refinedstorage.security.description\": \"Proteggi la tua rete con un Responsabile della sicurezza e una Scheda di sicurezza\",\n  \"advancements.refinedstorage.wireless\": \"Wireless\",\n  \"advancements.refinedstorage.wireless.description\": \"Trasmetti un segnale di rete con un Trasmettitore wireless\",\n  \"advancements.refinedstorage.wireless_items\": \"Oggetti wireless\",\n  \"advancements.refinedstorage.wireless_items.description\": \"Interagisci con lo spazio di archiviazione degli oggetti in modalità wireless con una Griglia wireless\",\n  \"advancements.refinedstorage.wireless_fluids\": \"Fluidi wireless\",\n  \"advancements.refinedstorage.wireless_fluids.description\": \"Interagisci con lo spazio di archiviazione di fluidi in modalità wireless con una Griglia fluidi wireless\",\n  \"advancements.refinedstorage.wireless_monitoring\": \"Monitoraggio wireless\",\n  \"advancements.refinedstorage.wireless_monitoring.description\": \"Controlla lo stato delle tue attività di fabbricazione in modalità wireless con il Monitor di fabbricazione wireless\",\n  \"advancements.refinedstorage.no_cables_required\": \"Nessun cavo richiesto\",\n  \"advancements.refinedstorage.no_cables_required.description\": \"Aggiungi componenti extra alla tua rete senza usare cavi utilizzando un Trasmettitore di rete, un Ricevitore di rete e una Scheda di rete\",\n  \"advancements.refinedstorage.upgrading\": \"Potenziamento\",\n  \"advancements.refinedstorage.upgrading.description\": \"Fabbrica un potenziamento per migliorare vari dispositivi\",\n  \"advancements.refinedstorage.crafting_on_demand\": \"Fabbricazione su richiesta\",\n  \"advancements.refinedstorage.crafting_on_demand.description\": \"Usa un potenziamento di fabbricazione in un'interfaccia, un esportatore o un costruttore per creare oggetti e blocchi su richiesta\",\n  \"advancements.refinedstorage.detecting\": \"Rilevamento\",\n  \"advancements.refinedstorage.detecting.description\": \"Rileva oggetti o fluidi nella rete con il rilevatore\",\n  \"advancements.refinedstorage.interface_to_the_world\": \"Interfaccia con il mondo\",\n  \"advancements.refinedstorage.interface_to_the_world.description\": \"Esporta e importa oggetti allo stesso tempo con un'interfaccia\",\n  \"advancements.refinedstorage.storing_externally\": \"Conservazione esterna\",\n  \"advancements.refinedstorage.storing_externally.description\": \"Utilizza un'Archiviazione esterna per fornire alla rete l'archiviazione da un blocco esterno come un baule\"\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/lang/ja_jp.json",
    "content": "{\n  \"itemGroup.refinedstorage\": \"Refined Storage\",\n  \"itemGroup.refinedstorage.covers\": \"Refined Storage カバー\",\n\n  \"key.refinedstorage.focusSearchBar\": \"グリッドの検索欄を選択\",\n  \"key.refinedstorage.clearGridCraftingMatrix\": \"グリッドのクラフト欄をクリア\",\n  \"key.refinedstorage.openWirelessGrid\": \"ワイヤレスグリッドを開く\",\n  \"key.refinedstorage.openWirelessFluidGrid\": \"ワイヤレス流体グリッドを開く\",\n  \"key.refinedstorage.openPortableGrid\": \"携帯グリッドを開く\",\n  \"key.refinedstorage.openWirelessCraftingMonitor\": \"ワイヤレスクラフトモニターを開く\",\n\n  \"gui.refinedstorage.controller\": \"コントローラー\",\n  \"gui.refinedstorage.creative_controller\": \"クリエイティブコントローラー\",\n  \"gui.refinedstorage.grid\": \"グリッド\",\n  \"gui.refinedstorage.grid.craft\": \"クラフト\",\n  \"gui.refinedstorage.crafting_grid\": \"製作グリッド\",\n  \"gui.refinedstorage.pattern_grid\": \"パターングリッド\",\n  \"gui.refinedstorage.grid.pattern_create\": \"作成\",\n  \"gui.refinedstorage.fluid_grid\": \"流体グリッド\",\n  \"gui.refinedstorage.portable_grid\": \"携帯グリッド\",\n  \"gui.refinedstorage.item_amount\": \"アイテムの量\",\n  \"gui.refinedstorage.fluid_amount\": \"流体の量 (mB)\",\n  \"gui.refinedstorage.disk_drive\": \"ディスクドライブ\",\n  \"gui.refinedstorage.disk_drive.disks\": \"ディスク\",\n  \"gui.refinedstorage.disk_manipulator\": \"ディスクマニピュレーター\",\n  \"gui.refinedstorage.disk_manipulator.in\": \"搬入\",\n  \"gui.refinedstorage.disk_manipulator.out\": \"搬出\",\n  \"gui.refinedstorage.external_storage\": \"拡張ストレージ\",\n  \"gui.refinedstorage.importer\": \"インポーター\",\n  \"gui.refinedstorage.exporter\": \"エクスポーター\",\n  \"gui.refinedstorage.detector\": \"ディテクター\",\n  \"gui.refinedstorage.destructor\": \"デストラクター\",\n  \"gui.refinedstorage.constructor\": \"コンストラクター\",\n  \"gui.refinedstorage.relay\": \"リレー\",\n  \"gui.refinedstorage.interface.import\": \"インターフェース:搬入\",\n  \"gui.refinedstorage.interface.export\": \"インターフェース:搬出\",\n  \"gui.refinedstorage.crafting_monitor\": \"クラフトモニター\",\n  \"gui.refinedstorage.wireless_crafting_monitor\": \"ワイヤレスクラフトモニター\",\n  \"gui.refinedstorage.crafting_monitor.tooltip.requested\": \"要求数 %d\",\n  \"gui.refinedstorage.crafting_monitor.stored\": \"在庫: %d\",\n  \"gui.refinedstorage.crafting_monitor.missing\": \"不足: %d\",\n  \"gui.refinedstorage.crafting_monitor.processing\": \"加工中: %d\",\n  \"gui.refinedstorage.crafting_monitor.scheduled\": \"加工予定: %d\",\n  \"gui.refinedstorage.crafting_monitor.crafting\": \"クラフト中: %d\",\n  \"gui.refinedstorage.crafting_monitor.machine_does_not_accept_item\": \"機械にアイテムを搬入できません\",\n  \"gui.refinedstorage.crafting_monitor.machine_does_not_accept_fluid\": \"機械に流体を搬入できません\",\n  \"gui.refinedstorage.crafting_monitor.machine_none\": \"機械が見つかりません\",\n  \"gui.refinedstorage.crafting_monitor.crafter_is_locked\": \"クラフターがロックされています\",\n  \"gui.refinedstorage.wireless_transmitter\": \"ワイヤレス送信機\",\n  \"gui.refinedstorage.wireless_transmitter.distance\": \"%dブロック\",\n  \"gui.refinedstorage.crafter\": \"クラフター\",\n  \"gui.refinedstorage.filter\": \"フィルター\",\n  \"gui.refinedstorage.filter.compare_nbt\": \"NBT\",\n  \"gui.refinedstorage.filter.mod_filter\": \"Modフィルター\",\n  \"gui.refinedstorage.network_transmitter\": \"ネットワーク送信機\",\n  \"gui.refinedstorage.network_transmitter.distance\": \"%dブロック\",\n  \"gui.refinedstorage.network_transmitter.missing_card\": \"ネットワークカードが見つかりません\",\n  \"gui.refinedstorage.fluid_interface\": \"流体インターフェース\",\n  \"gui.refinedstorage.fluid_interface.in\": \"搬入\",\n  \"gui.refinedstorage.fluid_interface.out\": \"搬出\",\n  \"gui.refinedstorage.crafting_preview\": \"クラフトのプレビュー\",\n  \"gui.refinedstorage.crafting_preview.to_craft\": \"作成数: %d\",\n  \"gui.refinedstorage.crafting_preview.available\": \"使用: %d\",\n  \"gui.refinedstorage.crafting_preview.missing\": \"不足: %d\",\n  \"gui.refinedstorage.crafting_preview.error\": \"リクエストに失敗しました\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.0\": \"材料が自身を要求しています\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.1\": \"該当パターンの削除\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.2\": \"または\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.3\": \"クラフト中に使われていないことを確認する必要があります\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.4\": \"該当パターン:\",\n  \"gui.refinedstorage.crafting_preview.error.too_complex.0\": \"クラフト過程の計算が複雑すぎます\",\n  \"gui.refinedstorage.crafting_preview.error.too_complex.1\": \"サーバーの負担を避けるため計算が停止されました\",\n  \"gui.refinedstorage.security_manager\": \"セキュリティマネージャー\",\n  \"gui.refinedstorage.security_manager.configure\": \"設定\",\n  \"gui.refinedstorage.security_manager.permission.0\": \"搬入\",\n  \"gui.refinedstorage.security_manager.permission.0.tooltip\": \"アイテムをネットワークに搬入する\",\n  \"gui.refinedstorage.security_manager.permission.1\": \"搬出\",\n  \"gui.refinedstorage.security_manager.permission.1.tooltip\": \"アイテムをネットワークから搬出する\",\n  \"gui.refinedstorage.security_manager.permission.2\": \"自動クラフト\",\n  \"gui.refinedstorage.security_manager.permission.2.tooltip\": \"自動クラフトの開始・キャンセルやクラフト過程の確認\",\n  \"gui.refinedstorage.security_manager.permission.3\": \"変更\",\n  \"gui.refinedstorage.security_manager.permission.3.tooltip\": \"ブロックのGUIを開く\",\n  \"gui.refinedstorage.security_manager.permission.4\": \"構築\",\n  \"gui.refinedstorage.security_manager.permission.4.tooltip\": \"ネットワークのデバイスを追加または撤去する\",\n  \"gui.refinedstorage.security_manager.permission.5\": \"セキュリティ\",\n  \"gui.refinedstorage.security_manager.permission.5.tooltip\": \"セキュリティ設定を変更する権限\",\n  \"gui.refinedstorage.storage_monitor\": \"ストレージモニター\",\n  \"gui.refinedstorage.crafter_manager\": \"クラフターマネージャー\",\n  \"gui.refinedstorage.alternatives\": \"代替案\",\n  \"gui.refinedstorage.alternatives.apply\": \"適用\",\n  \"gui.refinedstorage.jei.transfer.autocrafting_available\": \"自動クラフトが出来る\",\n  \"gui.refinedstorage.jei.transfer.request_autocrafting\": \"CTRLキーを押しながらクリックするために自動クラフトする\",\n  \"gui.refinedstorage.jei.transfer.request_autocrafting_mac\": \"CMDキーを押しながらクリックするために自動クラフトする\",\n  \"misc.refinedstorage.energy_stored\": \"%d / %d FE\",\n  \"misc.refinedstorage.energy_usage\": \"消費電力: %d FE/t\",\n  \"misc.refinedstorage.energy_usage_minimal\": \"%d FE/t\",\n\n  \"misc.refinedstorage.storage.stored\": \"在庫: %s\",\n  \"misc.refinedstorage.storage.stored_capacity\": \"在庫: %s / %s\",\n  \"misc.refinedstorage.storage.stored_minimal\": \"%s\",\n  \"misc.refinedstorage.storage.stored_capacity_minimal\": \"%s / %s\",\n  \"misc.refinedstorage.storage.full\": \"%d%%を使用中\",\n\n  \"misc.refinedstorage.network_item.tooltip\": \"%d, %d, %dにリンク済\",\n  \"misc.refinedstorage.network_item.out_of_range\": \"有効範囲内のワイヤレス送信機がありません\",\n  \"misc.refinedstorage.network_item.not_found\": \"ネットワークが見つかりません\",\n  \"misc.refinedstorage.network_item.shortcut_not_found\": \"インベントリに%sがありません\",\n  \"misc.refinedstorage.network_item.shortcut_duplicate\": \"インベントリに%sが複数あります\",\n  \"misc.refinedstorage.network_item.out_of_energy\": \"%sがエネルギー切れです\",\n\n  \"misc.refinedstorage.network_card.tooltip\": \"%sの%d, %d, %dにリンク済\",\n\n  \"misc.refinedstorage.pattern.inputs\": \"材料\",\n  \"misc.refinedstorage.pattern.outputs\": \"完成品\",\n  \"misc.refinedstorage.pattern.invalid\": \"無効なパターン\",\n  \"misc.refinedstorage.pattern.exact\": \"精密モードを使用\",\n  \"misc.refinedstorage.pattern.allowed_item_tag\": \"%sに%sのアイテムを使用する\",\n  \"misc.refinedstorage.pattern.allowed_fluid_tag\": \"%sに%sの流体を使用する\",\n\n  \"misc.refinedstorage.pattern.error.processing_no_outputs\": \"加工中のパターンに完成品がありません\",\n  \"misc.refinedstorage.pattern.error.no_output\": \"指定されたレシピに完成品がありません\",\n  \"misc.refinedstorage.pattern.error.recipe_does_not_exist\": \"指定されたレシピは存在しません\",\n  \"misc.refinedstorage.pattern.error.tag_no_longer_applicable\": \"タグ %s は%sに適用できなくなりました\",\n\n  \"misc.refinedstorage.security.no_permission\": \"その行動をする権限がありません\",\n\n  \"misc.refinedstorage.start\": \"開始\",\n  \"misc.refinedstorage.clear\": \"クリア\",\n  \"misc.refinedstorage.set\": \"完了\",\n  \"misc.refinedstorage.cancel_all\": \"全てキャンセル\",\n  \"misc.refinedstorage.priority\": \"優先度\",\n  \"misc.refinedstorage.exact\": \"精密モード\",\n  \"misc.refinedstorage.processing\": \"加工\",\n\n  \"misc.refinedstorage.total\": \"%s個\",\n\n  \"misc.refinedstorage.last_modified.just_now\": \"%sが直前に変更\",\n  \"misc.refinedstorage.last_modified.second\": \"%dが%s秒前に変更\",\n  \"misc.refinedstorage.last_modified.seconds\": \"%dが%s秒前に変更\",\n  \"misc.refinedstorage.last_modified.minute\": \"%dが%s分前に変更\",\n  \"misc.refinedstorage.last_modified.minutes\": \"%dが%s分前に変更\",\n  \"misc.refinedstorage.last_modified.hour\": \"%dが%s時間前に変更\",\n  \"misc.refinedstorage.last_modified.hours\": \"%dが%s時間前に変更\",\n  \"misc.refinedstorage.last_modified.day\": \"%dが%s日前に変更\",\n  \"misc.refinedstorage.last_modified.days\": \"%dが%s日前に変更\",\n  \"misc.refinedstorage.last_modified.week\": \"%dが%s週間前に変更\",\n  \"misc.refinedstorage.last_modified.weeks\": \"%dが%s週間前に変更\",\n  \"misc.refinedstorage.last_modified.year\": \"%dが%s年前に変更\",\n  \"misc.refinedstorage.last_modified.years\": \"%dが%s年前に変更\",\n\n  \"sidebutton.refinedstorage.exact_mode\": \"精密モード\",\n  \"sidebutton.refinedstorage.exact_mode.on\": \"オン\",\n  \"sidebutton.refinedstorage.exact_mode.off\": \"オフ\",\n\n  \"sidebutton.refinedstorage.redstone_mode\": \"レッドストーン\",\n  \"sidebutton.refinedstorage.redstone_mode.0\": \"レッドストーン信号を無視\",\n  \"sidebutton.refinedstorage.redstone_mode.1\": \"レッドストーン入力時のみ動作\",\n  \"sidebutton.refinedstorage.redstone_mode.2\": \"レッドストーン入力がない時のみ動作\",\n\n  \"sidebutton.refinedstorage.crafter_mode\": \"動作モード\",\n  \"sidebutton.refinedstorage.crafter_mode.0\": \"レッドストーン信号を無視\",\n  \"sidebutton.refinedstorage.crafter_mode.1\": \"レッドストーン信号で自動クラフトのロック解除\",\n  \"sidebutton.refinedstorage.crafter_mode.2\": \"レッドストーン信号で自動クラフトをロック\",\n  \"sidebutton.refinedstorage.crafter_mode.3\": \"レッドストーンパルスで次セットを搬入\",\n\n  \"sidebutton.refinedstorage.grid.view_type\": \"表示\",\n  \"sidebutton.refinedstorage.grid.view_type.0\": \"通常\",\n  \"sidebutton.refinedstorage.grid.view_type.1\": \"クラフト不可能な物のみ表示\",\n  \"sidebutton.refinedstorage.grid.view_type.2\": \"クラフト可能な物のみ表示\",\n  \"sidebutton.refinedstorage.grid.sorting.direction\": \"並び順\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.0\": \"昇順\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.1\": \"降順\",\n  \"sidebutton.refinedstorage.grid.sorting.type\": \"並べ替え\",\n  \"sidebutton.refinedstorage.grid.sorting.type.0\": \"量\",\n  \"sidebutton.refinedstorage.grid.sorting.type.1\": \"名前\",\n  \"sidebutton.refinedstorage.grid.sorting.type.2\": \"ID\",\n  \"sidebutton.refinedstorage.grid.sorting.type.3\": \"InventoryTweaks\",\n  \"sidebutton.refinedstorage.grid.sorting.type.4\": \"最終変更時間\",\n  \"sidebutton.refinedstorage.grid.search_box_mode\": \"検索ボックス\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.0\": \"通常\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.1\": \"通常 (自動選択)\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.2\": \"JEIと連動\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.3\": \"JEIと連動 (自動選択)\",\n  \"sidebutton.refinedstorage.grid.size\": \"サイズ\",\n  \"sidebutton.refinedstorage.grid.size.0\": \"画面サイズと連動\",\n  \"sidebutton.refinedstorage.grid.size.1\": \"小\",\n  \"sidebutton.refinedstorage.grid.size.2\": \"中\",\n  \"sidebutton.refinedstorage.grid.size.3\": \"大\",\n\n  \"sidebutton.refinedstorage.mode\": \"モード\",\n  \"sidebutton.refinedstorage.mode.whitelist\": \"ホワイトリスト\",\n  \"sidebutton.refinedstorage.mode.blacklist\": \"ブラックリスト\",\n\n  \"sidebutton.refinedstorage.iomode\": \"搬入出\",\n  \"sidebutton.refinedstorage.iomode.insert\": \"ネットワークへ搬出\",\n  \"sidebutton.refinedstorage.iomode.extract\": \"ネットワークから搬入\",\n\n  \"sidebutton.refinedstorage.type\": \"種類\",\n  \"sidebutton.refinedstorage.type.0\": \"アイテム\",\n  \"sidebutton.refinedstorage.type.1\": \"流体\",\n\n  \"sidebutton.refinedstorage.detector.mode\": \"モード\",\n  \"sidebutton.refinedstorage.detector.mode.0\": \"指定数を下回ると信号出力\",\n  \"sidebutton.refinedstorage.detector.mode.1\": \"指定数で信号出力\",\n  \"sidebutton.refinedstorage.detector.mode.2\": \"指定数を上回ると信号出力\",\n\n  \"sidebutton.refinedstorage.constructor.drop\": \"ブロックを設置せずにアイテム化させる\",\n\n  \"sidebutton.refinedstorage.destructor.pickup\": \"ブロックを破壊せずにアイテムを拾う\",\n\n  \"sidebutton.refinedstorage.access_type\": \"アクセスの種類\",\n  \"sidebutton.refinedstorage.access_type.0\": \"搬入・搬出\",\n  \"sidebutton.refinedstorage.access_type.1\": \"搬入のみ\",\n  \"sidebutton.refinedstorage.access_type.2\": \"搬出のみ\",\n\n  \"block.refinedstorage.controller\": \"コントローラー\",\n  \"block.refinedstorage.creative_controller\": \"クリエイティブコントローラー\",\n  \"block.refinedstorage.cable\": \"ケーブル\",\n  \"block.refinedstorage.grid\": \"グリッド\",\n  \"block.refinedstorage.crafting_grid\": \"製作グリッド\",\n  \"block.refinedstorage.pattern_grid\": \"パターングリッド\",\n  \"block.refinedstorage.fluid_grid\": \"流体グリッド\",\n  \"block.refinedstorage.disk_drive\": \"ディスクドライブ\",\n  \"block.refinedstorage.disk_manipulator\": \"ディスクマニピュレーター\",\n  \"block.refinedstorage.external_storage\": \"外部ストレージ\",\n  \"block.refinedstorage.importer\": \"インポーター\",\n  \"block.refinedstorage.exporter\": \"エクスポーター\",\n  \"block.refinedstorage.detector\": \"検出器\",\n  \"block.refinedstorage.machine_casing\": \"マシンケーシング\",\n  \"block.refinedstorage.destructor\": \"ディストラクター\",\n  \"block.refinedstorage.constructor\": \"コンストラクター\",\n  \"block.refinedstorage.1k_storage_block\": \"1千ストレージブロック\",\n  \"block.refinedstorage.4k_storage_block\": \"4千ストレージブロック\",\n  \"block.refinedstorage.16k_storage_block\": \"16千ストレージブロック\",\n  \"block.refinedstorage.64k_storage_block\": \"64千ストレージブロック\",\n  \"block.refinedstorage.creative_storage_block\": \"クリエイティブストレージブロック\",\n  \"block.refinedstorage.relay\": \"リレー\",\n  \"block.refinedstorage.interface\": \"インターフェース\",\n  \"block.refinedstorage.crafting_monitor\": \"クラフトモニター\",\n  \"block.refinedstorage.wireless_transmitter\": \"ワイヤレス送信機\",\n  \"block.refinedstorage.wireless_transmitter.tooltip\": \"%sの上に設置する必要があります\",\n  \"block.refinedstorage.crafter\": \"クラフター\",\n  \"block.refinedstorage.network_receiver\": \"ネットワーク受信機\",\n  \"block.refinedstorage.network_transmitter\": \"ネットワーク送信機\",\n  \"block.refinedstorage.fluid_interface\": \"流体インターフェース\",\n  \"block.refinedstorage.64k_fluid_storage_block\": \"64千流体ストレージブロック\",\n  \"block.refinedstorage.256k_fluid_storage_block\": \"256千流体ストレージブロック\",\n  \"block.refinedstorage.1024k_fluid_storage_block\": \"1024千流体ストレージブロック\",\n  \"block.refinedstorage.4096k_fluid_storage_block\": \"4096千流体ストレージブロック\",\n  \"block.refinedstorage.creative_fluid_storage_block\": \"クリエイティブ流体ストレージブロック\",\n  \"block.refinedstorage.security_manager\": \"セキュリティマネージャー\",\n  \"block.refinedstorage.quartz_enriched_iron_block\": \"クォーツ濃縮鉄ブロック\",\n  \"block.refinedstorage.storage_monitor\": \"ストレージモニター\",\n  \"block.refinedstorage.portable_grid\": \"携帯グリッド\",\n  \"block.refinedstorage.creative_portable_grid\": \"クリエイティブ携帯グリッド\",\n  \"block.refinedstorage.portable_grid.tooltip\": \"スニークで設置可能\",\n  \"block.refinedstorage.crafter_manager\": \"クラフターマネージャー\",\n\n  \"item.refinedstorage.1k_storage_disk\": \"1千ストレージディスク\",\n  \"item.refinedstorage.4k_storage_disk\": \"4千ストレージディスク\",\n  \"item.refinedstorage.16k_storage_disk\": \"16千ストレージディスク\",\n  \"item.refinedstorage.64k_storage_disk\": \"64千ストレージディスク\",\n  \"item.refinedstorage.creative_storage_disk\": \"クリエイティブストレージディスク\",\n  \"item.refinedstorage.64k_fluid_storage_disk\": \"64千流体ストレージディスク\",\n  \"item.refinedstorage.256k_fluid_storage_disk\": \"256千流体ストレージディスク\",\n  \"item.refinedstorage.1024k_fluid_storage_disk\": \"1024千流体ストレージディスク\",\n  \"item.refinedstorage.4096k_fluid_storage_disk\": \"4096千流体ストレージディスク\",\n  \"item.refinedstorage.creative_fluid_storage_disk\": \"クリエイティブ流体ストレージディスク\",\n  \"item.refinedstorage.wireless_grid\": \"ワイヤレスグリッド\",\n  \"item.refinedstorage.creative_wireless_grid\": \"クリエイティブワイヤレスグリッド\",\n  \"item.refinedstorage.wireless_fluid_grid\": \"ワイヤレス流体グリッド\",\n  \"item.refinedstorage.creative_wireless_fluid_grid\": \"クリエイティブワイヤレス流体グリッド\",\n  \"item.refinedstorage.wireless_crafting_monitor\": \"ワイヤレスクラフトモニター\",\n  \"item.refinedstorage.creative_wireless_crafting_monitor\": \"クリエイティブワイヤレスクラフトモニター\",\n  \"item.refinedstorage.quartz_enriched_iron\": \"クォーツ濃縮鉄\",\n  \"item.refinedstorage.construction_core\": \"コンストラクションコア\",\n  \"item.refinedstorage.destruction_core\": \"デストラクションコア\",\n  \"item.refinedstorage.silicon\": \"シリコン\",\n  \"item.refinedstorage.raw_basic_processor\": \"生の基本プロセッサ\",\n  \"item.refinedstorage.raw_improved_processor\": \"生の改良プロセッサ\",\n  \"item.refinedstorage.raw_advanced_processor\": \"生の発展プロセッサ\",\n  \"item.refinedstorage.basic_processor\": \"基本プロセッサ\",\n  \"item.refinedstorage.improved_processor\": \"改良プロセッサ\",\n  \"item.refinedstorage.advanced_processor\": \"発展プロセッサ\",\n  \"item.refinedstorage.1k_storage_part\": \"1千ストレージパーツ\",\n  \"item.refinedstorage.4k_storage_part\": \"4千ストレージパーツ\",\n  \"item.refinedstorage.16k_storage_part\": \"16千ストレージパーツ\",\n  \"item.refinedstorage.64k_storage_part\": \"64千ストレージパーツ\",\n  \"item.refinedstorage.64k_fluid_storage_part\": \"64千流体ストレージパーツ\",\n  \"item.refinedstorage.256k_fluid_storage_part\": \"256千流体ストレージパーツ\",\n  \"item.refinedstorage.1024k_fluid_storage_part\": \"1024千流体ストレージパーツ\",\n  \"item.refinedstorage.4096k_fluid_storage_part\": \"4096千流体ストレージパーツ\",\n  \"item.refinedstorage.pattern\": \"パターン\",\n  \"item.refinedstorage.upgrade\": \"アップグレード\",\n  \"item.refinedstorage.range_upgrade\": \"レンジアップグレード\",\n  \"item.refinedstorage.speed_upgrade\": \"スピードアップグレード\",\n  \"item.refinedstorage.crafting_upgrade\": \"クラフティングアップグレード\",\n  \"item.refinedstorage.stack_upgrade\": \"スタックアップグレード\",\n  \"item.refinedstorage.silk_touch_upgrade\": \"シルクタッチアップグレード\",\n  \"item.refinedstorage.fortune_1_upgrade\": \"幸運アップグレード\",\n  \"item.refinedstorage.fortune_2_upgrade\": \"幸運アップグレード\",\n  \"item.refinedstorage.fortune_3_upgrade\": \"幸運アップグレード\",\n  \"item.refinedstorage.regulator_upgrade\": \"レギュレータアップグレード\",\n  \"item.refinedstorage.storage_housing\": \"ストレージハウジング\",\n  \"item.refinedstorage.filter\": \"フィルター\",\n  \"item.refinedstorage.network_card\": \"ネットワークカード\",\n  \"item.refinedstorage.wrench\": \"レンチ\",\n  \"item.refinedstorage.security_card\": \"セキュリティカード\",\n  \"item.refinedstorage.security_card.owner\": \"所有者: %s\",\n  \"item.refinedstorage.processor_binding\": \"プロセッサ接合材\",\n  \"commands.refinedstorage.disk.create.error.disk_not_found\": \"ディスク%sが見つかりません\",\n  \"commands.refinedstorage.disk.create.success\": \"ディスク%sを%sに割り当てました\",\n  \"advancements.refinedstorage.controlling.description\": \"コントローラーを作る\",\n  \"advancements.refinedstorage.connecting\": \"接続\",\n  \"advancements.refinedstorage.connecting.description\": \"装置を隣接させて設置する他、ケーブルを使用することもできます\",\n  \"advancements.refinedstorage.conditional_connecting\": \"条件付きの接続\",\n  \"advancements.refinedstorage.conditional_connecting.description\": \"ネットワーク信号をレッドストーンで接続・遮断するリレーを作る\",\n  \"advancements.refinedstorage.drives\": \"ドライブ\",\n  \"advancements.refinedstorage.drives.description\": \"ディスクの保管を可能にするディスクドライブを作る\",\n  \"advancements.refinedstorage.manipulating_disks\": \"ディスク操作\",\n  \"advancements.refinedstorage.manipulating_disks.description\": \"ディスクマニピュレータを使用してディスクの中身を簡単に変更する\",\n  \"advancements.refinedstorage.storing_items\": \"アイテムを貯蔵\",\n  \"advancements.refinedstorage.storing_items.description\": \"ストレージディスクを作成してディスクドライブに搭載する\",\n  \"advancements.refinedstorage.viewing_items\": \"アイテムを確認\",\n  \"advancements.refinedstorage.viewing_items.description\": \"グリッドを作成してアイテムのストレージにアクセスする\",\n  \"advancements.refinedstorage.portable_storage\": \"携帯ストレージ\",\n  \"advancements.refinedstorage.portable_storage.description\": \"ネットワーク内でなくてもディスク内のアイテムや流体にアクセスできる携帯グリッドを作る\",\n  \"advancements.refinedstorage.upgrading_your_grid\": \"グリッドのアップグレード\",\n  \"advancements.refinedstorage.upgrading_your_grid.description\": \"グリッドを製作グリッドにアップグレードするとクラフトが可能になります\",\n  \"advancements.refinedstorage.storing_fluids\": \"流体を貯蔵\",\n  \"advancements.refinedstorage.storing_fluids.description\": \"流体ストレージディスクを作成してディスクドライブに搭載する\",\n  \"advancements.refinedstorage.viewing_fluids\": \"流体を確認\",\n  \"advancements.refinedstorage.viewing_fluids.description\": \"流体グリッドを作成して流体ストレージにアクセスする\",\n  \"advancements.refinedstorage.better_than_a_barrel\": \"バレルよりも良い\",\n  \"advancements.refinedstorage.better_than_a_barrel.description\": \"ネットワーク内のアイテムを表示し、搬入出を行うストレージモニターを作る\",\n  \"advancements.refinedstorage.autocrafting\": \"自動クラフト\",\n  \"advancements.refinedstorage.autocrafting.description\": \"クラフターを作る\",\n  \"advancements.refinedstorage.pattern_creation\": \"パターンを作成\",\n  \"advancements.refinedstorage.pattern_creation.description\": \"パターングリッドとパターンを使用してパターンを作る\",\n  \"advancements.refinedstorage.monitoring\": \"モニタリング\",\n  \"advancements.refinedstorage.monitoring.description\": \"クラフトモニターを使用して自動クラフトの状況をチェックする\",\n  \"advancements.refinedstorage.managing_patterns\": \"パターンの管理\",\n  \"advancements.refinedstorage.managing_patterns.description\": \"クラフターマネージャーを使用してより良い方法でパターンを管理する\",\n  \"advancements.refinedstorage.importing\": \"搬入\",\n  \"advancements.refinedstorage.importing.description\": \"インポーターを使用してアイテムや流体をストレージネットワークに取り込む\",\n  \"advancements.refinedstorage.destruction\": \"破壊\",\n  \"advancements.refinedstorage.destruction.description\": \"デストラクターを使用してアイテムや流体をストレージネットワークに取り込む\",\n  \"advancements.refinedstorage.exporting\": \"搬出\",\n  \"advancements.refinedstorage.exporting.description\": \"エクスポーターを使用してネットワークからブロックや流体を取り出す\",\n  \"advancements.refinedstorage.construction\": \"構築\",\n  \"advancements.refinedstorage.construction.description\": \"コンストラクターを使用してネットワークからブロックや流体を取り出す\",\n  \"advancements.refinedstorage.security\": \"セキュリティ\",\n  \"advancements.refinedstorage.security.description\": \"セキュリティマネージャーとセキュリティカードを使用してあなたのネットワークを保護する\",\n  \"advancements.refinedstorage.wireless\": \"ワイヤレス\",\n  \"advancements.refinedstorage.wireless.description\": \"ワイヤレス送信機を使用してネットワーク信号を送出する\",\n  \"advancements.refinedstorage.wireless_items\": \"ワイヤレスアイテム\",\n  \"advancements.refinedstorage.wireless_items.description\": \"ワイヤレスグリッドを使用してワイヤレスでアイテムのストレージにアクセスする\",\n  \"advancements.refinedstorage.wireless_fluids\": \"ワイヤレス流体\",\n  \"advancements.refinedstorage.wireless_fluids.description\": \"ワイヤレス流体グリッドを使用してワイヤレスで流体ストレージにアクセスする\",\n  \"advancements.refinedstorage.wireless_monitoring\": \"ワイヤレスモニタリング\",\n  \"advancements.refinedstorage.wireless_monitoring.description\": \"ワイヤレスクラフトモニターを使用して自動クラフトの状況をワイヤレスでチェックする\",\n  \"advancements.refinedstorage.no_cables_required\": \"ケーブル不要\",\n  \"advancements.refinedstorage.no_cables_required.description\": \"ネットワーク送信機と受信機、ネットワークカードを使用してケーブルを使用せずにネットワークに装置を追加する\",\n  \"advancements.refinedstorage.upgrading\": \"アップグレード\",\n  \"advancements.refinedstorage.upgrading.description\": \"様々な装置を改善するアップグレードを作る\",\n  \"advancements.refinedstorage.crafting_on_demand\": \"クラフティング・オンデマンド\",\n  \"advancements.refinedstorage.crafting_on_demand.description\": \"インターフェースやエクスポーター、コンストラクターにクラフティングアップグレードを搭載してアイテムやブロックをオンデマンドで作る\",\n  \"advancements.refinedstorage.detecting\": \"検知\",\n  \"advancements.refinedstorage.detecting.description\": \"検出器を使用してネットワーク内のアイテムや流体を検出する\",\n  \"advancements.refinedstorage.interface_to_the_world\": \"世界への接点\",\n  \"advancements.refinedstorage.interface_to_the_world.description\": \"インターフェースでアイテムの搬入出を同時に行う\",\n  \"advancements.refinedstorage.storing_externally\": \"外部保管\",\n  \"advancements.refinedstorage.storing_externally.description\": \"拡張ストレージを利用してチェストのような外部のブロックからネットワークにストレージを供給する\"\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/lang/ko_kr.json",
    "content": "{\n  \"itemGroup.refinedstorage\": \"리파인드 스토리지\",\n  \"itemGroup.refinedstorage.covers\": \"리파인드 스토리지 커버즈\",\n\n  \"key.refinedstorage.focusSearchBar\": \"그리드 검색\",\n  \"key.refinedstorage.clearGridCraftingMatrix\": \"그리드 제작 매트릭스 지우기\",\n  \"key.refinedstorage.openWirelessGrid\": \"무선 그리드 열기\",\n  \"key.refinedstorage.openWirelessFluidGrid\": \"무선 액체 그리드 열기\",\n  \"key.refinedstorage.openPortableGrid\": \"휴대용 그리드 열기\",\n  \"key.refinedstorage.openWirelessCraftingMonitor\": \"무선 제작 모니터 열기\",\n\n  \"gui.refinedstorage.controller\": \"콘트롤러\",\n  \"gui.refinedstorage.creative_controller\": \"크리에이티브 콘트롤러\",\n  \"gui.refinedstorage.grid\": \"그리드\",\n  \"gui.refinedstorage.grid.craft\": \"제작\",\n  \"gui.refinedstorage.crafting_grid\": \"제작 그리드\",\n  \"gui.refinedstorage.pattern_grid\": \"패턴 그리드\",\n  \"gui.refinedstorage.grid.pattern_create\": \"패턴 제작\",\n  \"gui.refinedstorage.fluid_grid\": \"액체 그리드\",\n  \"gui.refinedstorage.portable_grid\": \"휴대용 그리드\",\n  \"gui.refinedstorage.item_amount\": \"아이템 양\",\n  \"gui.refinedstorage.fluid_amount\": \"액량(mB)\",\n  \"gui.refinedstorage.disk_drive\": \"디스크 드라이브\",\n  \"gui.refinedstorage.disk_drive.disks\": \"디스크\",\n  \"gui.refinedstorage.disk_manipulator\": \"디스크 조작기\",\n  \"gui.refinedstorage.disk_manipulator.in\": \"입력\",\n  \"gui.refinedstorage.disk_manipulator.out\": \"출력\",\n  \"gui.refinedstorage.external_storage\": \"외부 저장공간\",\n  \"gui.refinedstorage.importer\": \"입력기\",\n  \"gui.refinedstorage.exporter\": \"출력기\",\n  \"gui.refinedstorage.detector\": \"감지기\",\n  \"gui.refinedstorage.destructor\": \"파괴기\",\n  \"gui.refinedstorage.constructor\": \"설치기\",\n  \"gui.refinedstorage.relay\": \"중계기\",\n  \"gui.refinedstorage.interface.import\": \"인터페이스 입력\",\n  \"gui.refinedstorage.interface.export\": \"인터페이스 출력\",\n  \"gui.refinedstorage.crafting_monitor\": \"제작 모니터\",\n  \"gui.refinedstorage.wireless_crafting_monitor\": \"무선 제작 모니터\",\n  \"gui.refinedstorage.crafting_monitor.tooltip.requested\": \"%d 요청됨\",\n  \"gui.refinedstorage.crafting_monitor.stored\": \"저장: %d\",\n  \"gui.refinedstorage.crafting_monitor.missing\": \"부족: %d\",\n  \"gui.refinedstorage.crafting_monitor.processing\": \"처리: %d\",\n  \"gui.refinedstorage.crafting_monitor.scheduled\": \"예정: %d\",\n  \"gui.refinedstorage.crafting_monitor.crafting\": \"제작: %d\",\n  \"gui.refinedstorage.crafting_monitor.machine_does_not_accept_item\": \"기계가 아이템을 허용하지 않습니다.\",\n  \"gui.refinedstorage.crafting_monitor.machine_does_not_accept_fluid\": \"기계가 액체를 허용하지 않습니다.\",\n  \"gui.refinedstorage.crafting_monitor.machine_none\": \"기계를 찾을 수 없습니다.\",\n  \"gui.refinedstorage.crafting_monitor.crafter_is_locked\": \"제작기가 잠겼습니다.\",\n  \"gui.refinedstorage.wireless_transmitter\": \"무선 송신기\",\n  \"gui.refinedstorage.wireless_transmitter.distance\": \"%d블럭\",\n  \"gui.refinedstorage.crafter\": \"제작기\",\n  \"gui.refinedstorage.filter\": \"필터\",\n  \"gui.refinedstorage.filter.compare_nbt\": \"NBT\",\n  \"gui.refinedstorage.filter.mod_filter\": \"모드 필터\",\n  \"gui.refinedstorage.network_transmitter\": \"네트워크 송신기\",\n  \"gui.refinedstorage.network_transmitter.distance\": \"%d블럭\",\n  \"gui.refinedstorage.network_transmitter.missing_card\": \"부족한 네트워크 카드\",\n  \"gui.refinedstorage.fluid_interface\": \"액체 인터페이스\",\n  \"gui.refinedstorage.fluid_interface.in\": \"입력\",\n  \"gui.refinedstorage.fluid_interface.out\": \"출력\",\n  \"gui.refinedstorage.crafting_preview\": \"제작 미리보기\",\n  \"gui.refinedstorage.crafting_preview.to_craft\": \"제작할 아이템: %d\",\n  \"gui.refinedstorage.crafting_preview.available\": \"사용 가능: %d\",\n  \"gui.refinedstorage.crafting_preview.missing\": \"부족: %d\",\n  \"gui.refinedstorage.crafting_preview.error\": \"요청에 실패했습니다.\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.0\": \"제작 재료 중 하나는 결국 \",\n  \"gui.refinedstorage.crafting_preview.error.recursive.1\": \"스스로가 필요하게 되었습니다.\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.2\": \"패턴을 제거하거나 제작 시 \",\n  \"gui.refinedstorage.crafting_preview.error.recursive.3\": \"패턴이 사용되지 않도록 해야 합니다.\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.4\": \"불쾌감을 주는 패턴:\",\n  \"gui.refinedstorage.crafting_preview.error.too_complex.0\": \"제작 작업 계산이 너무 복잡하여 \",\n  \"gui.refinedstorage.crafting_preview.error.too_complex.1\": \"서버 부담을 피하기 위해 중지되었습니다.\",\n  \"gui.refinedstorage.security_manager\": \"보안 관리자\",\n  \"gui.refinedstorage.security_manager.configure\": \"설정\",\n  \"gui.refinedstorage.security_manager.permission.0\": \"삽입\",\n  \"gui.refinedstorage.security_manager.permission.0.tooltip\": \"네트워크에 아이템이나 액체를 삽입하기\",\n  \"gui.refinedstorage.security_manager.permission.1\": \"추출\",\n  \"gui.refinedstorage.security_manager.permission.1.tooltip\": \"네트워크에서 아이템이나 액체를 추출하기\",\n  \"gui.refinedstorage.security_manager.permission.2\": \"자동 제작하기\",\n  \"gui.refinedstorage.security_manager.permission.2.tooltip\": \"자동 제작 시작, 중지 및 현재 작업 보기\",\n  \"gui.refinedstorage.security_manager.permission.3\": \"수정\",\n  \"gui.refinedstorage.security_manager.permission.3.tooltip\": \"네트워크 상의 GUI 열기\",\n  \"gui.refinedstorage.security_manager.permission.4\": \"조작\",\n  \"gui.refinedstorage.security_manager.permission.4.tooltip\": \"네트워크에 장치를 추가하거나 제거하기\",\n  \"gui.refinedstorage.security_manager.permission.5\": \"보안\",\n  \"gui.refinedstorage.security_manager.permission.5.tooltip\": \"보안 옵션 조정하기\",\n  \"gui.refinedstorage.storage_monitor\": \"저장 모니터\",\n  \"gui.refinedstorage.crafter_manager\": \"제작기 관리자\",\n  \"gui.refinedstorage.alternatives\": \"대체\",\n  \"gui.refinedstorage.alternatives.apply\": \"적용\",\n  \"gui.refinedstorage.jei.transfer.autocrafting_available\": \"자동 제작 사용 가능\",\n  \"gui.refinedstorage.jei.transfer.request_autocrafting\": \"CTRL + 클릭하여 자동 제작 요청\",\n  \"gui.refinedstorage.jei.transfer.request_autocrafting_mac\": \"CMD + 클릭하여 자동 제작 요청\",\n  \"misc.refinedstorage.energy_stored\": \"%d / %d FE\",\n  \"misc.refinedstorage.energy_usage\": \"사용: %d FE/t\",\n  \"misc.refinedstorage.energy_usage_minimal\": \"%d FE/t\",\n  \"misc.refinedstorage.storage.stored\": \"저장량: %s\",\n  \"misc.refinedstorage.storage.stored_capacity\": \"저쟝량: %s / %s\",\n  \"misc.refinedstorage.storage.stored_minimal\": \"%s\",\n  \"misc.refinedstorage.storage.stored_capacity_minimal\": \"%s / %s\",\n  \"misc.refinedstorage.storage.full\": \"%d%% 가득 참\",\n  \"misc.refinedstorage.network_item.tooltip\": \"%d, %d, %d로 연결됨\",\n  \"misc.refinedstorage.network_item.out_of_range\": \"근방에 무선 송신기가 없습니다.\",\n  \"misc.refinedstorage.network_item.not_found\": \"콘트롤러를 찾을 수 없습니다.\",\n  \"misc.refinedstorage.network_item.shortcut_not_found\": \"인벤토리에 %s이(가) 없습니다.\",\n  \"misc.refinedstorage.network_item.shortcut_duplicate\": \"인벤토리에 두 개 이상의 %s이(가) 있습니다.\",\n  \"misc.refinedstorage.network_item.out_of_energy\": \"%s의 에너지가 부족합니다.\",\n\n  \"misc.refinedstorage.network_card.tooltip\": \"%d, %d, %d로 연결됨\",\n\n  \"misc.refinedstorage.pattern.inputs\": \"입력\",\n  \"misc.refinedstorage.pattern.outputs\": \"출력\",\n  \"misc.refinedstorage.pattern.invalid\": \"잘못된 패턴\",\n  \"misc.refinedstorage.pattern.exact\": \"정확한 모드 사용\",\n  \"misc.refinedstorage.pattern.allowed_item_tag\": \"%s에 대해 %s의 아이템을 사용합니다.\",\n  \"misc.refinedstorage.pattern.allowed_fluid_tag\": \"%s에 대해 %s의 액체를 사용합니다.\",\n\n  \"misc.refinedstorage.pattern.error.processing_no_outputs\": \"처리 패턴에 출력이 없습니다.\",\n  \"misc.refinedstorage.pattern.error.no_output\": \"제작법에 출력이 없습니다.\",\n  \"misc.refinedstorage.pattern.error.recipe_does_not_exist\": \"제작법이 존재하지 않습니다.\",\n  \"misc.refinedstorage.pattern.error.tag_no_longer_applicable\": \"%s 태그를 %s에 더 이상 적용할 수 없습니다.\",\n  \"misc.refinedstorage.security.no_permission\": \"해당 작업을 실행할 권한이 없습니다.\",\n  \"misc.refinedstorage.start\": \"시작\",\n  \"misc.refinedstorage.clear\": \"초기화\",\n  \"misc.refinedstorage.set\": \"설정\",\n  \"misc.refinedstorage.cancel_all\": \"모두 취소\",\n  \"misc.refinedstorage.priority\": \"우선 순위\",\n  \"misc.refinedstorage.exact\": \"정확성\",\n  \"misc.refinedstorage.processing\": \"처리\",\n  \"misc.refinedstorage.fluidmode\": \"액체\",\n  \"misc.refinedstorage.total\": \"%s 합계\",\n  \"misc.refinedstorage.last_modified.just_now\": \"%s에 의해 방금 전에 최종 수정됨\",\n  \"misc.refinedstorage.last_modified.second\": \"%s초 전 %d에 의해 마지막으로 수정됨\",\n  \"misc.refinedstorage.last_modified.seconds\": \"%s초 전 %d에 의해 마지막으로 수정됨\",\n  \"misc.refinedstorage.last_modified.minute\": \"%s분 전 %d에 의해 마지막으로 수정됨\",\n  \"misc.refinedstorage.last_modified.minutes\": \"%s분 전 %d에 의해 마지막으로 수정됨\",\n  \"misc.refinedstorage.last_modified.hour\": \"%s시간 전 %d에 의해 마지막으로 수정됨\",\n  \"misc.refinedstorage.last_modified.hours\": \"%s시간 전 %d에 의해 마지막으로 수정됨\",\n  \"misc.refinedstorage.last_modified.day\": \"%s일 전 %d에 의해 마지막으로 수정됨\",\n  \"misc.refinedstorage.last_modified.days\": \"%s일 전 %d에 의해 마지막으로 수정됨\",\n  \"misc.refinedstorage.last_modified.week\": \"%s주 전 %d에 의해 마지막으로 수정됨\",\n  \"misc.refinedstorage.last_modified.weeks\": \"%s주 전 %d에 의해 마지막으로 수정됨\",\n  \"misc.refinedstorage.last_modified.year\": \"%s년 전 %d에 의해 마지막으로 수정됨\",\n  \"misc.refinedstorage.last_modified.years\": \"%s년 전 %d에 의해 마지막으로 수정됨\",\n\n  \"sidebutton.refinedstorage.exact_mode\": \"정확한 모드\",\n  \"sidebutton.refinedstorage.exact_mode.on\": \"켜짐\",\n  \"sidebutton.refinedstorage.exact_mode.off\": \"꺼짐\",\n\n  \"sidebutton.refinedstorage.redstone_mode\": \"레드스톤 모드\",\n  \"sidebutton.refinedstorage.redstone_mode.0\": \"신호와 상관 없이 작동\",\n  \"sidebutton.refinedstorage.redstone_mode.1\": \"신호를 받을 때 작동\",\n  \"sidebutton.refinedstorage.redstone_mode.2\": \"신호를 받지 않을 때 작동\",\n  \n  \"sidebutton.refinedstorage.crafter_mode\": \"제작기 모드\",\n  \"sidebutton.refinedstorage.crafter_mode.0\": \"레드스톤 신호 무시\",\n  \"sidebutton.refinedstorage.crafter_mode.1\": \"레드스톤 신호가 자동 제작의 잠금을 해제합니다.\",\n  \"sidebutton.refinedstorage.crafter_mode.2\": \"레드스톤 신호가 자동 제작을 잠급니다.\",\n  \"sidebutton.refinedstorage.crafter_mode.3\": \"레드스톤 펄스가 다음 세트를 삽입합니다.\",\n\n  \"sidebutton.refinedstorage.grid.view_type\": \"표시\",\n  \"sidebutton.refinedstorage.grid.view_type.0\": \"일반\",\n  \"sidebutton.refinedstorage.grid.view_type.1\": \"제작 가능 아이템 숨김\",\n  \"sidebutton.refinedstorage.grid.view_type.2\": \"제작 가능 아이템만 표시\",\n  \"sidebutton.refinedstorage.grid.sorting.direction\": \"정렬\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.0\": \"오름차순\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.1\": \"내림차순\",\n  \"sidebutton.refinedstorage.grid.sorting.type\": \"정렬 기준\",\n  \"sidebutton.refinedstorage.grid.sorting.type.0\": \"수량\",\n  \"sidebutton.refinedstorage.grid.sorting.type.1\": \"이름\",\n  \"sidebutton.refinedstorage.grid.sorting.type.2\": \"ID\",\n  \"sidebutton.refinedstorage.grid.sorting.type.3\": \"인벤토리트윅스\",\n  \"sidebutton.refinedstorage.grid.sorting.type.4\": \"최근 수정\",\n  \"sidebutton.refinedstorage.grid.search_box_mode\": \"검색 모드\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.0\": \"일반\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.1\": \"일반 (자동 선택됨)\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.2\": \"JEI 통합\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.3\": \"JEI 통합 (자동 선택됨)\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.4\": \"JEI 통합 (양방향)\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.5\": \"JEI 통합 (양방향 자동 선택됨)\",\n  \"sidebutton.refinedstorage.grid.size\": \"크기\",\n  \"sidebutton.refinedstorage.grid.size.0\": \"맞춤\",\n  \"sidebutton.refinedstorage.grid.size.1\": \"작음\",\n  \"sidebutton.refinedstorage.grid.size.2\": \"중간\",\n  \"sidebutton.refinedstorage.grid.size.3\": \"큼\",\n\n  \"sidebutton.refinedstorage.mode\": \"모드\",\n  \"sidebutton.refinedstorage.mode.whitelist\": \"화이트리스트\",\n  \"sidebutton.refinedstorage.mode.blacklist\": \"블랙리스트\",\n\n  \"sidebutton.refinedstorage.iomode\": \"입출력 모드\",\n  \"sidebutton.refinedstorage.iomode.insert\": \"네트워크로 입력\",\n  \"sidebutton.refinedstorage.iomode.extract\": \"네트워크에서 출력\",\n\n  \"sidebutton.refinedstorage.type\": \"종류\",\n  \"sidebutton.refinedstorage.type.0\": \"아이템\",\n  \"sidebutton.refinedstorage.type.1\": \"액체\",\n\n  \"sidebutton.refinedstorage.detector.mode\": \"모드\",\n  \"sidebutton.refinedstorage.detector.mode.0\": \"수량 이하일 때 신호 출력\",\n  \"sidebutton.refinedstorage.detector.mode.1\": \"수량과 일치할 때 신호 출력\",\n  \"sidebutton.refinedstorage.detector.mode.2\": \"수량 이상일 때 신호 출력\",\n  \"sidebutton.refinedstorage.constructor.drop\": \"블럭을 설치하지 않고 떨어트림\",\n  \"sidebutton.refinedstorage.destructor.pickup\": \"블럭을 파괴하지 않고 주움\",\n  \"sidebutton.refinedstorage.access_type\": \"액세스 종류\",\n  \"sidebutton.refinedstorage.access_type.0\": \"입출력\",\n  \"sidebutton.refinedstorage.access_type.1\": \"입력\",\n  \"sidebutton.refinedstorage.access_type.2\": \"출력\",\n  \"block.refinedstorage.controller\": \"콘트롤러\",\n  \"block.refinedstorage.creative_controller\": \"크리에이티브 콘트롤러\",\n  \"block.refinedstorage.cable\": \"케이블\",\n  \"block.refinedstorage.grid\": \"그리드\",\n  \"block.refinedstorage.crafting_grid\": \"제작 그리드\",\n  \"block.refinedstorage.pattern_grid\": \"패턴 그리드\",\n  \"block.refinedstorage.fluid_grid\": \"액체 그리드\",\n  \"block.refinedstorage.disk_drive\": \"디스크 드라이브\",\n  \"block.refinedstorage.disk_manipulator\": \"디스크 조작기\",\n  \"block.refinedstorage.external_storage\": \"외부 저장공간\",\n  \"block.refinedstorage.importer\": \"입력기\",\n  \"block.refinedstorage.exporter\": \"출력기\",\n  \"block.refinedstorage.detector\": \"감지기\",\n  \"block.refinedstorage.machine_casing\": \"기계 케이싱\",\n  \"block.refinedstorage.destructor\": \"파괴기\",\n  \"block.refinedstorage.constructor\": \"설치기\",\n  \"block.refinedstorage.1k_storage_block\": \"1k 저장공간\",\n  \"block.refinedstorage.4k_storage_block\": \"4k 저장공간\",\n  \"block.refinedstorage.16k_storage_block\": \"16k 저장공간\",\n  \"block.refinedstorage.64k_storage_block\": \"64k 저장공간\",\n  \"block.refinedstorage.creative_storage_block\": \"크리에이티브 저장공간\",\n  \"block.refinedstorage.relay\": \"중계기\",\n  \"block.refinedstorage.interface\": \"인터페이스\",\n  \"block.refinedstorage.crafting_monitor\": \"제작 모니터\",\n  \"block.refinedstorage.wireless_transmitter\": \"무선 송신기\",\n  \"block.refinedstorage.crafter\": \"제작기\",\n  \"block.refinedstorage.network_receiver\": \"네트워크 수신기\",\n  \"block.refinedstorage.network_transmitter\": \"네트워크 송신기\",\n  \"block.refinedstorage.fluid_interface\": \"액체 인터페이스\",\n  \"block.refinedstorage.64k_fluid_storage_block\": \"64k 액체 저장공간\",\n  \"block.refinedstorage.256k_fluid_storage_block\": \"256k 액체 저장공간\",\n  \"block.refinedstorage.1024k_fluid_storage_block\": \"1024k 액체 저장공간\",\n  \"block.refinedstorage.4096k_fluid_storage_block\": \"4096k 액체 저장공간\",\n  \"block.refinedstorage.creative_fluid_storage_block\": \"크리에이티브 액체 저장공간\",\n  \"block.refinedstorage.security_manager\": \"보안 관리자\",\n  \"block.refinedstorage.quartz_enriched_iron_block\": \"석영 강화 철 블럭\",\n  \"block.refinedstorage.storage_monitor\": \"저장 모니터\",\n  \"block.refinedstorage.portable_grid\": \"휴대용 그리드\",\n  \"block.refinedstorage.creative_portable_grid\": \"크리에이티브 휴대용 그리드\",\n  \"block.refinedstorage.portable_grid.tooltip\": \"웅크리기로 설치할 수 있습니다.\",\n  \"block.refinedstorage.crafter_manager\": \"제작기 관리자\",\n  \"item.refinedstorage.1k_storage_disk\": \"1k 저장 디스크\",\n  \"item.refinedstorage.4k_storage_disk\": \"4k 저장 디스크\",\n  \"item.refinedstorage.16k_storage_disk\": \"16k 저장 디스크\",\n  \"item.refinedstorage.64k_storage_disk\": \"64k 저장 디스크\",\n  \"item.refinedstorage.creative_storage_disk\": \"크리에이티브 저장 디스크\",\n  \"item.refinedstorage.64k_fluid_storage_disk\": \"64k 액체 저장 디스크\",\n  \"item.refinedstorage.256k_fluid_storage_disk\": \"256k 액체 저장 디스크\",\n  \"item.refinedstorage.1024k_fluid_storage_disk\": \"1024k 액체 저장 디스크\",\n  \"item.refinedstorage.4096k_fluid_storage_disk\": \"4096k 액체 저장 디스크\",\n  \"item.refinedstorage.creative_fluid_storage_disk\": \"크리에이티브 액체 저장 디스크\",\n  \"item.refinedstorage.wireless_grid\": \"무선 그리드\",\n  \"item.refinedstorage.creative_wireless_grid\": \"크리에이티브 무선 그리드\",\n  \"item.refinedstorage.wireless_fluid_grid\": \"무선 액체 그리드\",\n  \"item.refinedstorage.creative_wireless_fluid_grid\": \"크리에이티브 무선 액체 그리드\",\n  \"item.refinedstorage.wireless_crafting_monitor\": \"무선 제작 모니터\",\n  \"item.refinedstorage.creative_wireless_crafting_monitor\": \"크리에이티브 무선 제작 모니터\",\n  \"item.refinedstorage.quartz_enriched_iron\": \"석영 강화 철\",\n  \"item.refinedstorage.construction_core\": \"형성 코어\",\n  \"item.refinedstorage.destruction_core\": \"파괴 코어\",\n  \"item.refinedstorage.silicon\": \"실리콘\",\n  \"item.refinedstorage.raw_basic_processor\": \"처리되지 않은 기본 프로세서\",\n  \"item.refinedstorage.raw_improved_processor\": \"처리되지 않은 강화 프로세서\",\n  \"item.refinedstorage.raw_advanced_processor\": \"처리되지 않은 고급 프로세서\",\n  \"item.refinedstorage.basic_processor\": \"기본 프로세서\",\n  \"item.refinedstorage.improved_processor\": \"강화 프로세서\",\n  \"item.refinedstorage.advanced_processor\": \"고급 프로세서\",\n  \"item.refinedstorage.1k_storage_part\": \"1k 저장 파트\",\n  \"item.refinedstorage.4k_storage_part\": \"4k 저장 파트\",\n  \"item.refinedstorage.16k_storage_part\": \"16k 저장 파트\",\n  \"item.refinedstorage.64k_storage_part\": \"64k 저장 파트\",\n  \"item.refinedstorage.64k_fluid_storage_part\": \"64k 액체 저장 파트\",\n  \"item.refinedstorage.256k_fluid_storage_part\": \"256k 액체 저장 파트\",\n  \"item.refinedstorage.1024k_fluid_storage_part\": \"1024k 액체 저장 파트\",\n  \"item.refinedstorage.4096k_fluid_storage_part\": \"4096k 액체 저장 파트\",\n  \"item.refinedstorage.pattern\": \"패턴\",\n  \"item.refinedstorage.upgrade\": \"업그레이드\",\n  \"item.refinedstorage.range_upgrade\": \"범위 업그레이드\",\n  \"item.refinedstorage.speed_upgrade\": \"속도 업그레이드\",\n  \"item.refinedstorage.crafting_upgrade\": \"제작 업그레이드\",\n  \"item.refinedstorage.stack_upgrade\": \"세트 업그레이드\",\n  \"item.refinedstorage.silk_touch_upgrade\": \"섬세한 손길 업그레이드\",\n  \"item.refinedstorage.fortune_1_upgrade\": \"행운 업그레이드\",\n  \"item.refinedstorage.fortune_2_upgrade\": \"행운 업그레이드\",\n  \"item.refinedstorage.fortune_3_upgrade\": \"행운 업그레이드\",\n  \"item.refinedstorage.regulator_upgrade\": \"조절기 업그레이드\",\n  \"item.refinedstorage.storage_housing\": \"저장공간 하우징\",\n  \"item.refinedstorage.filter\": \"필터\",\n  \"item.refinedstorage.network_card\": \"네트워크 카드\",\n  \"item.refinedstorage.wrench\": \"렌치\",\n  \"item.refinedstorage.security_card\": \"보안 카드\",\n  \"item.refinedstorage.security_card.owner\": \"플레이어: %s\",\n  \"item.refinedstorage.processor_binding\": \"프로세서 바인딩\",\n  \"item.refinedstorage.cover\": \"커버\",\n  \"item.refinedstorage.hollow_cover\": \"빈 커버\",\n  \"commands.refinedstorage.disk.create.error.disk_not_found\": \"%s 디스크를 찾을 수 없습니다.\",\n  \"commands.refinedstorage.disk.create.success\": \"%s 디스크에 %s을(를) 부여했습니다.\",\n  \"commands.refinedstorage.network.list.pos\": \"X: %d, Y: %d, Z: %d에서의 네트워크\",\n  \"commands.refinedstorage.network.list.tick_times\": \"평균 틱 시간: %s ms. 평균 TPS: %s\",\n  \"commands.refinedstorage.network.list.autocrafting_tasks\": \"%s 작업\",\n  \"commands.refinedstorage.network.list.nodes\": \"%s 노드\",\n  \"commands.refinedstorage.network.list.energy_usage\": \"에너지 사용: %s\",\n  \"commands.refinedstorage.network.get.error.not_found\": \"네트워크를 찾지 못했습니다.\",\n  \"commands.refinedstorage.network.autocrafting.get.error.not_found\": \"작업를 찾지 못했습니다.\",\n  \"commands.refinedstorage.network.autocrafting.cancel.single\": \"작업 %d개를 취소했습니다.\",\n  \"commands.refinedstorage.network.autocrafting.cancel.multiple\": \"작업 %d개를 취소했습니다.\",\n  \"advancements.refinedstorage.controlling.description\": \"콘트롤러를 제작합니다.\",\n  \"advancements.refinedstorage.connecting\": \"연결\",\n  \"advancements.refinedstorage.connecting.description\": \"모든 장치를 나란히 배치하여 연결하거나 케이블을 사용할 수 있습니다.\",\n  \"advancements.refinedstorage.conditional_connecting\": \"조건부 연결\",\n  \"advancements.refinedstorage.conditional_connecting.description\": \"네트워크 신호가 레드스톤으로 전달될 수 있는지 제어하기 위해 중계기를 제작합니다.\",\n  \"advancements.refinedstorage.drives\": \"드라이브\",\n  \"advancements.refinedstorage.drives.description\": \"디스크를 저장할 수 있도록 디스크 드라이브를 제작합니다.\",\n  \"advancements.refinedstorage.manipulating_disks\": \"디스크 조작\",\n  \"advancements.refinedstorage.manipulating_disks.description\": \"디스크 조작기를 사용하여 디스크 내용을 쉽게 수정합니다.\",\n  \"advancements.refinedstorage.storing_items\": \"아이템 정렬\",\n  \"advancements.refinedstorage.storing_items.description\": \"저장 디스크를 제작하여 디스크 드라이브에 넣습니다.\",\n  \"advancements.refinedstorage.viewing_items\": \"아이템 보기\",\n  \"advancements.refinedstorage.viewing_items.description\": \"그리드를 제작하여 아이템 저장공간과 상호 작용합니다.\",\n  \"advancements.refinedstorage.portable_storage\": \"휴대용 저장공간\",\n  \"advancements.refinedstorage.portable_storage.description\": \"휴대용 그리드를 제작하여 네트워크에 있지 않고 디스크의 아이템 및 액체에 접근할 수 있습니다.\",\n  \"advancements.refinedstorage.upgrading_your_grid\": \"그리드를 업그레이드하기\",\n  \"advancements.refinedstorage.upgrading_your_grid.description\": \"그리드를 제작 그리드로 업그레이드하여 그리드에서 제작 기능을 얻으십시오.\",\n  \"advancements.refinedstorage.storing_fluids\": \"액체 저장\",\n  \"advancements.refinedstorage.storing_fluids.description\": \"액체 저장 디스크를 제작하여 디스크 드라이브에 넣습니다.\",\n  \"advancements.refinedstorage.viewing_fluids\": \"액체 보기\",\n  \"advancements.refinedstorage.viewing_fluids.description\": \"액체 저장공간과 상호 작용하도록 액체 그리드를 제작합니다.\",\n  \"advancements.refinedstorage.better_than_a_barrel\": \"통보다 좋다!\",\n  \"advancements.refinedstorage.better_than_a_barrel.description\": \"저장 모니터를 제작하여 네트워크의 아이템을 보거나 삽입 또는 추출합니다.\",\n  \"advancements.refinedstorage.autocrafting\": \"자동 제작\",\n  \"advancements.refinedstorage.autocrafting.description\": \"제작기를 제작합니다.\",\n  \"advancements.refinedstorage.pattern_creation\": \"패턴 제작\",\n  \"advancements.refinedstorage.pattern_creation.description\": \"패턴 그리드 및 패턴을 사용하여 패턴을 작성합니다.\",\n  \"advancements.refinedstorage.monitoring\": \"감시\",\n  \"advancements.refinedstorage.monitoring.description\": \"제작 모니터로 제작 작업의 상태를 확인합니다.\",\n  \"advancements.refinedstorage.managing_patterns\": \"패턴 관리\",\n  \"advancements.refinedstorage.managing_patterns.description\": \"제작기 관리자를 제작하여 패턴을 보다 효율적으로 관리할 수 있습니다.\",\n  \"advancements.refinedstorage.importing\": \"입력\",\n  \"advancements.refinedstorage.importing.description\": \"입력기를 사용하여 아이템 또는 액체를 저장공간 네트워크로 가져옵니다.\",\n  \"advancements.refinedstorage.destruction\": \"파괴\",\n  \"advancements.refinedstorage.destruction.description\": \"파괴기를 사용하여 블록이나 액체를 저장공간 네트워크로 가져옵니다.\",\n  \"advancements.refinedstorage.exporting\": \"출력\",\n  \"advancements.refinedstorage.exporting.description\": \"출력기를 사용하여 블록이나 액체를 저장공간 네트워크로 가져옵니다.\",\n  \"advancements.refinedstorage.construction\": \"설치\",\n  \"advancements.refinedstorage.construction.description\": \"설치기를 사용하여 저장공간 네트워크에서 블록이나 액체를 얻습니다.\",\n  \"advancements.refinedstorage.security\": \"보안\",\n  \"advancements.refinedstorage.security.description\": \"보안 관리자 및 보안 카드를 사용하여 네트워크를 보호하십시오.\",\n  \"advancements.refinedstorage.wireless\": \"무선\",\n  \"advancements.refinedstorage.wireless.description\": \"무선 송신기로 네트워크 신호를 전송합니다.\",\n  \"advancements.refinedstorage.wireless_items\": \"무선 아이템\",\n  \"advancements.refinedstorage.wireless_items.description\": \"무선 그리드를 통해 아이템 저장공간과 무선으로 상호작용하십시오.\",\n  \"advancements.refinedstorage.wireless_fluids\": \"무선 액체\",\n  \"advancements.refinedstorage.wireless_fluids.description\": \"무선 액체 그리드로 액체 저장공간과 무선으로 상호작용하십시오.\",\n  \"advancements.refinedstorage.wireless_monitoring\": \"무선 감시\",\n  \"advancements.refinedstorage.wireless_monitoring.description\": \"무선 제작 모니터로 무선으로 제작 작업의 상태를 확인하십시오.\",\n  \"advancements.refinedstorage.no_cables_required\": \"케이블을 요구하지 않습니다.\",\n  \"advancements.refinedstorage.no_cables_required.description\": \"네트워크 송신기, 네트워크 수신기 및 네트워크 카드를 사용하여 케이블을 사용하지 않고도 네트워크에 추가 구성요소를 추가할 수 있습니다.\",\n  \"advancements.refinedstorage.upgrading\": \"업그레이드\",\n  \"advancements.refinedstorage.upgrading.description\": \"다양한 장치를 개선하기 위해 업그레이드를 제작합니다.\",\n  \"advancements.refinedstorage.crafting_on_demand\": \"주문형 제작\",\n  \"advancements.refinedstorage.crafting_on_demand.description\": \"인터페이스, 출력기 또는 설치기에서 제작 업그레이드를 사용하여 주문형 아이템 및 블록을 제작합니다.\",\n  \"advancements.refinedstorage.detecting\": \"탐지\",\n  \"advancements.refinedstorage.detecting.description\": \"감지기를 사용하여 네트워크의 아이템 또는 액체를 탐지합니다.\",\n  \"advancements.refinedstorage.interface_to_the_world\": \"월드에 대한 인터페이스\",\n  \"advancements.refinedstorage.interface_to_the_world.description\": \"인터페이스로 아이템을 동시에 내보내고 가져옵니다.\",\n  \"advancements.refinedstorage.storing_externally\": \"외부로 저장\",\n  \"advancements.refinedstorage.storing_externally.description\": \"외부 저장공간을 사용하여 네트워크에 상자와 같은 외부 블록의 저장공간을 제공합니다.\"\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/lang/nl_nl.json",
    "content": "{\n  \"itemGroup.refinedstorage\": \"Refined Storage\",\n\n  \"gui.refinedstorage.controller\": \"Controller\",\n  \"gui.refinedstorage.creative_controller\": \"Creative Controller\",\n  \"gui.refinedstorage.grid\": \"Rooster\",\n  \"gui.refinedstorage.grid.craft\": \"Craft\",\n  \"gui.refinedstorage.grid.pattern_create\": \"Patroon maken\",\n  \"gui.refinedstorage.wireless_grid\": \"Draadloos rooster\",\n  \"gui.refinedstorage.fluid_grid\": \"Vloeistof rooster\",\n  \"gui.refinedstorage.disk_drive\": \"Schijf\",\n  \"gui.refinedstorage.external_storage\": \"Externe opslag\",\n  \"gui.refinedstorage.importer\": \"Importeur\",\n  \"gui.refinedstorage.exporter\": \"Exporteur\",\n  \"gui.refinedstorage.detector\": \"Detector\",\n  \"gui.refinedstorage.destructor\": \"Destructor\",\n  \"gui.refinedstorage.constructor\": \"Constructor\",\n  \"gui.refinedstorage.relay\": \"Relais\",\n  \"gui.refinedstorage.interface.import\": \"Interface Import\",\n  \"gui.refinedstorage.interface.export\": \"Interface Export\",\n  \"gui.refinedstorage.crafting_monitor\": \"Crafting Monitor\",\n  \"gui.refinedstorage.crafting_monitor.machine_none\": \"Geen machine gevonden\",\n  \"gui.refinedstorage.wireless_transmitter\": \"Draadloze zender\",\n  \"gui.refinedstorage.wireless_transmitter.distance\": \"%d blokken\",\n  \"gui.refinedstorage.crafter\": \"Crafter\",\n  \"gui.refinedstorage.filter\": \"Filter\",\n  \"gui.refinedstorage.filter.compare_nbt\": \"NBT\",\n  \"gui.refinedstorage.network_transmitter\": \"Netwerkzender\",\n  \"gui.refinedstorage.network_transmitter.distance\": \"%d blokken\",\n  \"gui.refinedstorage.network_transmitter.missing_card\": \"Geen netwerkkaart\",\n  \"gui.refinedstorage.fluid_interface\": \"Vloeistof interface\",\n  \"gui.refinedstorage.fluid_interface.in\": \"In\",\n  \"gui.refinedstorage.fluid_interface.out\": \"Uit\",\n\n  \"misc.refinedstorage.energy_stored\": \"%d / %d FE\",\n  \"misc.refinedstorage.energy_usage\": \"Vebruik: %d FE/t\",\n  \"misc.refinedstorage.energy_usage_minimal\": \"%d FE/t\",\n\n  \"misc.refinedstorage.storage.stored\": \"Opgeslagen: %s\",\n  \"misc.refinedstorage.storage.stored_capacity\": \"Opgeslagen: %s / %s\",\n  \"misc.refinedstorage.storage.stored_minimal\": \"%s\",\n  \"misc.refinedstorage.storage.stored_capacity_minimal\": \"%s / %s\",\n  \"misc.refinedstorage.storage.full\": \"%d%% vol\",\n\n  \"misc.refinedstorage.network_item.tooltip\": \"Gelinkt aan %d, %d, %d.\",\n  \"misc.refinedstorage.network_item.out_of_range\": \"Er is geen draadloze zender binnen bereik.\",\n  \"misc.refinedstorage.network_item.not_found\": \"Controller niet gevonden.\",\n\n  \"misc.refinedstorage.network_card.tooltip\": \"Gelinkt aan %d, %d, %d in %s.\",\n\n  \"misc.refinedstorage.pattern.inputs\": \"Inputs\",\n  \"misc.refinedstorage.pattern.outputs\": \"Outputs\",\n  \"misc.refinedstorage.pattern.invalid\": \"Ongeldig patroon\",\n\n  \"misc.refinedstorage.start\": \"Start\",\n  \"misc.refinedstorage.clear\": \"Legen\",\n  \"misc.refinedstorage.cancel_all\": \"Annuleer alles\",\n  \"misc.refinedstorage.priority\": \"Prioriteit\",\n\n  \"sidebutton.refinedstorage.redstone_mode\": \"Redstone Mode\",\n  \"sidebutton.refinedstorage.redstone_mode.0\": \"Redstone negeren\",\n  \"sidebutton.refinedstorage.redstone_mode.1\": \"Alleen werken met redstone signaal\",\n  \"sidebutton.refinedstorage.redstone_mode.2\": \"Alleen werken zonder redstone signaal\",\n\n  \"sidebutton.refinedstorage.grid.view_type\": \"Weergave\",\n  \"sidebutton.refinedstorage.grid.view_type.0\": \"Normaal\",\n  \"sidebutton.refinedstorage.grid.view_type.1\": \"Geen craftables\",\n  \"sidebutton.refinedstorage.grid.view_type.2\": \"Alleen craftables\",\n  \"sidebutton.refinedstorage.grid.sorting.direction\": \"Sorteer richting\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.0\": \"Oplopend\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.1\": \"Aflopend\",\n  \"sidebutton.refinedstorage.grid.sorting.type\": \"Sorteer type\",\n  \"sidebutton.refinedstorage.grid.sorting.type.0\": \"Hoeveelheid\",\n  \"sidebutton.refinedstorage.grid.sorting.type.1\": \"Naam\",\n  \"sidebutton.refinedstorage.grid.search_box_mode\": \"Zoekbalkmodus\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.0\": \"Normaal\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.1\": \"Normaal (autogeselecteerd)\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.2\": \"JEI gesynchronizeerd\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.3\": \"JEI gesynchronizeerd (autogeselecteerd)\",\n\n  \"sidebutton.refinedstorage.mode\": \"Mode\",\n  \"sidebutton.refinedstorage.mode.whitelist\": \"Whitelist\",\n  \"sidebutton.refinedstorage.mode.blacklist\": \"Blacklist\",\n\n  \"sidebutton.refinedstorage.iomode\": \"IO Mode\",\n  \"sidebutton.refinedstorage.iomode.insert\": \"In netwerk steken\",\n  \"sidebutton.refinedstorage.iomode.extract\": \"Uit netwerk halen\",\n\n  \"sidebutton.refinedstorage.type\": \"Type\",\n  \"sidebutton.refinedstorage.type.0\": \"Items\",\n  \"sidebutton.refinedstorage.type.1\": \"Vloeistoffen\",\n\n  \"sidebutton.refinedstorage.detector.mode\": \"Mode\",\n  \"sidebutton.refinedstorage.detector.mode.0\": \"Redstone signaal aan wanneer onder het aantal\",\n  \"sidebutton.refinedstorage.detector.mode.1\": \"Redstone signaal aan wanneer op het aantal\",\n  \"sidebutton.refinedstorage.detector.mode.2\": \"Redstone signaal aan wanneer boven het aantal\",\n\n  \"block.refinedstorage.controller\": \"Controller\",\n  \"block.refinedstorage.creative_controller\": \"Creative Controller\",\n  \"block.refinedstorage.cable\": \"Kabel\",\n  \"block.refinedstorage.grid\": \"Rooster\",\n  \"block.refinedstorage.crafting_grid\": \"Crafting rooster\",\n  \"block.refinedstorage.pattern_grid\": \"Patroon rooster\",\n  \"block.refinedstorage.fluid_grid\": \"Vloeistof rooster\",\n  \"block.refinedstorage.disk_drive\": \"Schijf\",\n  \"block.refinedstorage.disk_manipulator\": \"Schijf manipulator\",\n  \"block.refinedstorage.external_storage\": \"Externe opslag\",\n  \"block.refinedstorage.importer\": \"Importeur\",\n  \"block.refinedstorage.exporter\": \"Exporteur\",\n  \"block.refinedstorage.detector\": \"Detector\",\n  \"block.refinedstorage.machine_casing\": \"Machine-omhulsel\",\n  \"block.refinedstorage.destructor\": \"Destructor\",\n  \"block.refinedstorage.constructor\": \"Constructor\",\n  \"block.refinedstorage.1k_storage_block\": \"1k opslagblok\",\n  \"block.refinedstorage.4k_storage_block\": \"4k opslagblok\",\n  \"block.refinedstorage.16k_storage_block\": \"16k opslagblok\",\n  \"block.refinedstorage.64k_storage_block\": \"64k opslagblok\",\n  \"block.refinedstorage.creative_storage_block\": \"Creative opslagblok\",\n  \"block.refinedstorage.relay\": \"Relais\",\n  \"block.refinedstorage.interface\": \"Interface\",\n  \"block.refinedstorage.crafting_monitor\": \"Crafting Monitor\",\n  \"block.refinedstorage.wireless_transmitter\": \"Draadloze zender\",\n  \"block.refinedstorage.crafter\": \"Crafter\",\n  \"block.refinedstorage.network_receiver\": \"Netwerkontvanger\",\n  \"block.refinedstorage.network_transmitter\": \"Netwerkzender\",\n  \"block.refinedstorage.fluid_interface\": \"Vloeistof interface\",\n  \"block.refinedstorage.64k_fluid_storage_block\": \"64k vloeistof opslagblok\",\n  \"block.refinedstorage.256k_fluid_storage_block\": \"256k vloeistof opslagblok\",\n  \"block.refinedstorage.1024k_fluid_storage_block\": \"1024k vloeistof opslagblok\",\n  \"block.refinedstorage.4096k_fluid_storage_block\": \"4096k vloeistof opslagblok\",\n  \"block.refinedstorage.creative_fluid_storage_block\": \"Creative vloeistof opslagblok\",\n\n  \"item.refinedstorage.1k_storage_disk\": \"1k opslagschijf\",\n  \"item.refinedstorage.4k_storage_disk\": \"4k opslagschijf\",\n  \"item.refinedstorage.16k_storage_disk\": \"16k opslagschijf\",\n  \"item.refinedstorage.64k_storage_disk\": \"64k opslagschijf\",\n  \"item.refinedstorage.creative_storage_disk\": \"Creative opslagschijf\",\n  \"item.refinedstorage.64k_fluid_storage_disk\": \"64k vloeistof opslagschijf\",\n  \"item.refinedstorage.256k_fluid_storage_disk\": \"256k vloeistof opslagschijf\",\n  \"item.refinedstorage.1024k_fluid_storage_disk\": \"1024k vloeistof opslagschijf\",\n  \"item.refinedstorage.4096k_fluid_storage_disk\": \"4096k vloeistof opslagschijf\",\n  \"item.refinedstorage.creative_fluid_storage_disk\": \"Creative vloeistof opslagschijf\",\n  \"item.refinedstorage.wireless_grid\": \"Draadloos rooster\",\n  \"item.refinedstorage.creative_wireless_grid\": \"Creative draadloos rooster\",\n  \"item.refinedstorage.quartz_enriched_iron\": \"Quartz verrijkte ijzerstaaf\",\n  \"item.refinedstorage.construction_core\": \"Constructiekern\",\n  \"item.refinedstorage.destruction_core\": \"Destructiekern\",\n  \"item.refinedstorage.silicon\": \"Siliconen\",\n  \"item.refinedstorage.basic_processor\": \"Basis processor\",\n  \"item.refinedstorage.improved_processor\": \"Verbeterde processor\",\n  \"item.refinedstorage.advanced_processor\": \"Geavanceerde processor\",\n  \"item.refinedstorage.1k_storage_part\": \"1k opslagdeel\",\n  \"item.refinedstorage.4k_storage_part\": \"4k opslagdeel\",\n  \"item.refinedstorage.16k_storage_part\": \"16k opslagdeel\",\n  \"item.refinedstorage.64k_storage_part\": \"64k opslagdeel\",\n  \"item.refinedstorage.64k_fluid_storage_part\": \"64k vloeistof opslagdeel\",\n  \"item.refinedstorage.256k_fluid_storage_part\": \"256k vloeistof opslagdeel\",\n  \"item.refinedstorage.1024k_fluid_storage_part\": \"1024k vloeistof opslagdeel\",\n  \"item.refinedstorage.4096k_fluid_storage_part\": \"4096k vloeistof opslagdeel\",\n  \"item.refinedstorage.pattern\": \"Patroon\",\n  \"item.refinedstorage.upgrade\": \"Upgrade\",\n  \"item.refinedstorage.range_upgrade\": \"Afstand upgrade\",\n  \"item.refinedstorage.speed_upgrade\": \"Snelheid upgrade\",\n  \"item.refinedstorage.crafting_upgrade\": \"Crafting upgrade\",\n  \"item.refinedstorage.stack_upgrade\": \"Stack upgrade\",\n  \"item.refinedstorage.storage_housing\": \"Opslagomhulsel\",\n  \"item.refinedstorage.filter\": \"Filter\",\n  \"item.refinedstorage.network_card\": \"Netwerkkaart\"\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/lang/pl_pl.json",
    "content": "{\n    \"itemGroup.refinedstorage\": \"Refined Storage\",\n    \"itemGroup.refinedstorage.covers\": \"Fasady z Refined Storage\",\n\n    \"key.refinedstorage.focusSearchBar\": \"Przenieś kursor do paska wyszukiwania\",\n    \"key.refinedstorage.clearGridCraftingMatrix\": \"Wyczyść siatkę konstruowania w terminalu\",\n    \"key.refinedstorage.openWirelessGrid\": \"Otwórz bezprzewodowy terminal\",\n    \"key.refinedstorage.openWirelessFluidGrid\": \"Otwórz bezprzewodowy terminal cieczy\",\n    \"key.refinedstorage.openPortableGrid\": \"Otwórz przenośny terminal\",\n    \"key.refinedstorage.openWirelessCraftingMonitor\": \"Otwórz bezprzewodowy monitor konstruowania\",\n\n    \"gui.refinedstorage.controller\": \"Kontroler\",\n    \"gui.refinedstorage.creative_controller\": \"Kreatywny kontroler\",\n    \"gui.refinedstorage.grid\": \"Terminal\",\n    \"gui.refinedstorage.grid.craft\": \"Wytwórz\",\n    \"gui.refinedstorage.crafting_grid\": \"Terminal konstruowania\",\n    \"gui.refinedstorage.pattern_grid\": \"Terminal szablonów\",\n    \"gui.refinedstorage.grid.pattern_create\": \"Stwórz\",\n    \"gui.refinedstorage.fluid_grid\": \"Terminal cieczy\",\n    \"gui.refinedstorage.portable_grid\": \"Przenośny terminal\",\n    \"gui.refinedstorage.item_amount\": \"Ilość przedmiotów\",\n    \"gui.refinedstorage.fluid_amount\": \"Ilość płynów w mW\",\n    \"gui.refinedstorage.disk_drive\": \"Napęd dyskowy\",\n    \"gui.refinedstorage.disk_drive.disks\": \"Dyski\",\n    \"gui.refinedstorage.disk_manipulator\": \"Manipulator dysków\",\n    \"gui.refinedstorage.disk_manipulator.in\": \"Wejście\",\n    \"gui.refinedstorage.disk_manipulator.out\": \"Wyjście\",\n    \"gui.refinedstorage.external_storage\": \"Zewnętrzny magazyn\",\n    \"gui.refinedstorage.importer\": \"Importer\",\n    \"gui.refinedstorage.exporter\": \"Eksporter\",\n    \"gui.refinedstorage.detector\": \"Detektor\",\n    \"gui.refinedstorage.destructor\": \"Destruktor\",\n    \"gui.refinedstorage.constructor\": \"Construktor\",\n    \"gui.refinedstorage.relay\": \"Przekaźnik\",\n    \"gui.refinedstorage.interface.import\": \"Importowanie do interfejsu\",\n    \"gui.refinedstorage.interface.export\": \"Eksportowanie z interfejsu\",\n    \"gui.refinedstorage.crafting_monitor\": \"Monitor konstruowania\",\n    \"gui.refinedstorage.wireless_crafting_monitor\": \"Bezprzewodowy monitor konstruowania\",\n    \"gui.refinedstorage.crafting_monitor.tooltip.requested\": \"%d zakończone\",\n    \"gui.refinedstorage.crafting_monitor.stored\": \"Zmagazynowane: %d\",\n    \"gui.refinedstorage.crafting_monitor.missing\": \"Brakujące: %d\",\n    \"gui.refinedstorage.crafting_monitor.processing\": \"Przetwarzane: %d\",\n    \"gui.refinedstorage.crafting_monitor.scheduled\": \"Zaplanowane: %d\",\n    \"gui.refinedstorage.crafting_monitor.crafting\": \"Wytwarzane: %d\",\n    \"gui.refinedstorage.crafting_monitor.machine_does_not_accept_item\": \"Maszyna nie przyjmuje przedmiotu\",\n    \"gui.refinedstorage.crafting_monitor.machine_does_not_accept_fluid\": \"Maszyna nie przyjmuje cieczy\",\n    \"gui.refinedstorage.crafting_monitor.machine_none\": \"Nie znaleziono maszyny\",\n    \"gui.refinedstorage.crafting_monitor.crafter_is_locked\": \"Przetwarzacz receptur jest zablokowany\",\n    \"gui.refinedstorage.wireless_transmitter\": \"Nadajnik bezprzewodowy\",\n    \"gui.refinedstorage.wireless_transmitter.distance\": \"%d bloków/bloki\",\n    \"gui.refinedstorage.crafter\": \"Przetwarzacz receptur\",\n    \"gui.refinedstorage.filter\": \"Filtr\",\n    \"gui.refinedstorage.filter.compare_nbt\": \"NBT\",\n    \"gui.refinedstorage.filter.mod_filter\": \"Filtr modów\",\n    \"gui.refinedstorage.network_transmitter\": \"Nadajnik sieci\",\n    \"gui.refinedstorage.network_transmitter.distance\": \"%d bloków/bloki\",\n    \"gui.refinedstorage.network_transmitter.missing_card\": \"Brakuje karty sieciowej\",\n    \"gui.refinedstorage.fluid_interface\": \"Interfejs płynów\",\n    \"gui.refinedstorage.fluid_interface.in\": \"Wejście\",\n    \"gui.refinedstorage.fluid_interface.out\": \"Wyjście\",\n    \"gui.refinedstorage.crafting_preview\": \"Podgląd receptury\",\n    \"gui.refinedstorage.crafting_preview.to_craft\": \"Do wytworzenia: %d\",\n    \"gui.refinedstorage.crafting_preview.available\": \"Dostępne: %d\",\n    \"gui.refinedstorage.crafting_preview.missing\": \"Brakujące: %d\",\n    \"gui.refinedstorage.crafting_preview.error\": \"Żądanie nie wykonane\",\n    \"gui.refinedstorage.crafting_preview.error.recursive.0\": \"Jeden ze składników potrzebował samego\",\n    \"gui.refinedstorage.crafting_preview.error.recursive.1\": \"siebie.\",\n    \"gui.refinedstorage.crafting_preview.error.recursive.2\": \"Musisz usunąć szablon lub upewnić się,\",\n    \"gui.refinedstorage.crafting_preview.error.recursive.3\": \"że szablon nie jest używany w trakcie konstruowania.\",\n    \"gui.refinedstorage.crafting_preview.error.recursive.4\": \"Problemowy szablon:\",\n    \"gui.refinedstorage.crafting_preview.error.too_complex.0\": \"Zadanie konstruowania było zbyt skomplikowane\",\n    \"gui.refinedstorage.crafting_preview.error.too_complex.1\": \"i zostało zakończone, by nie nadwyrężyć serwera.\",\n    \"gui.refinedstorage.security_manager\": \"Menadżer bezpieczeństwa\",\n    \"gui.refinedstorage.security_manager.configure\": \"Konfiguruj\",\n    \"gui.refinedstorage.security_manager.permission.0\": \"Wkładanie\",\n    \"gui.refinedstorage.security_manager.permission.0.tooltip\": \"Wkładanie przedmiotów lub cieczy do sieci\",\n    \"gui.refinedstorage.security_manager.permission.1\": \"Zabieranie\",\n    \"gui.refinedstorage.security_manager.permission.1.tooltip\": \"Zabieranie przedmiotów lub cieczy z sieci\",\n    \"gui.refinedstorage.security_manager.permission.2\": \"Auto-wytwarzanie\",\n    \"gui.refinedstorage.security_manager.permission.2.tooltip\": \"Rozpoczynanie, anulowanie i przeglądanie zadań konstruowania\",\n    \"gui.refinedstorage.security_manager.permission.3\": \"Modyfikowanie\",\n    \"gui.refinedstorage.security_manager.permission.3.tooltip\": \"Otwieranie i modyfikowanie bloków\",\n    \"gui.refinedstorage.security_manager.permission.4\": \"Budowanie\",\n    \"gui.refinedstorage.security_manager.permission.4.tooltip\": \"Dodawanie lub usuwanie urządzeń z sieci\",\n    \"gui.refinedstorage.security_manager.permission.5\": \"Bezpieczeństwo\",\n    \"gui.refinedstorage.security_manager.permission.5.tooltip\": \"Możliwość zmiany opcji bezpieczeństwa\",\n    \"gui.refinedstorage.storage_monitor\": \"Monitor przechowywania\",\n    \"gui.refinedstorage.crafter_manager\": \"Menadżer przetwarzaczy receptur\",\n    \"gui.refinedstorage.alternatives\": \"Alternatywy\",\n    \"gui.refinedstorage.alternatives.apply\": \"Zastosuj\",\n    \"gui.refinedstorage.jei.transfer.autocrafting_available\": \"Auto-wytwarzanie dostępne\",\n    \"gui.refinedstorage.jei.transfer.request_autocrafting\": \"CTRL + KLIKNIJ aby zażądać wytworzenia\",\n    \"gui.refinedstorage.jei.transfer.request_autocrafting_mac\": \"CMD + KLIKNIJ aby zażądać wytworzenia\",\n    \"misc.refinedstorage.energy_stored\": \"%d / %d FE\",\n    \"misc.refinedstorage.energy_usage\": \"Zużycie: %d FE/t\",\n    \"misc.refinedstorage.energy_usage_minimal\": \"%d FE/t\",\n    \"misc.refinedstorage.storage.stored\": \"Zmagazynowane: %s\",\n    \"misc.refinedstorage.storage.stored_capacity\": \"Zmagazynowane: %s / %s\",\n    \"misc.refinedstorage.storage.stored_minimal\": \"%s\",\n    \"misc.refinedstorage.storage.stored_capacity_minimal\": \"%s / %s\",\n    \"misc.refinedstorage.storage.full\": \"Pełne w %d%%\",\n    \"misc.refinedstorage.network_item.tooltip\": \"Połączone z %d, %d, %d.\",\n    \"misc.refinedstorage.network_item.out_of_range\": \"Brak nadajnika bezprzewodowego w zasięgu.\",\n    \"misc.refinedstorage.network_item.not_found\": \"Sieć nie znaleziona.\",\n    \"misc.refinedstorage.network_item.shortcut_not_found\": \"Brak przedmiotu \\\"%s\\\" w Twoim ekwipunku.\",\n    \"misc.refinedstorage.network_item.shortcut_duplicate\": \"Jest więcej niż jeden przedmiot \\\"%s\\\" w Twoim ekwipunku.\",\n    \"misc.refinedstorage.network_item.out_of_energy\": \"W przedmiocie \\\"%s\\\" skończyła się energia.\",\n\n    \"misc.refinedstorage.network_card.tooltip\": \"Połączone z %d, %d, %d w wymiarze %s.\",\n\n    \"misc.refinedstorage.pattern.inputs\": \"Przedmioty wejściowe\",\n    \"misc.refinedstorage.pattern.outputs\": \"Przedmioty wyjściowe\",\n    \"misc.refinedstorage.pattern.invalid\": \"Nieprawidłowy szablon\",\n    \"misc.refinedstorage.pattern.exact\": \"Jest w trybie dokładnym\",\n    \"misc.refinedstorage.pattern.allowed_item_tag\": \"Używa przedmiotów z %s dla %s\",\n    \"misc.refinedstorage.pattern.allowed_fluid_tag\": \"Używa cieczy z %s dla %s\",\n\n    \"misc.refinedstorage.pattern.error.processing_no_outputs\": \"Szablon przetwarzania nie posiada żadnych przedmiotów wyjściowych\",\n    \"misc.refinedstorage.pattern.error.no_output\": \"Receptura nie ma żadnych przedmiotów wyjściowych\",\n    \"misc.refinedstorage.pattern.error.recipe_does_not_exist\": \"Receptura nie istnieje\",\n    \"misc.refinedstorage.pattern.error.tag_no_longer_applicable\": \"Tag %s nie jest aplikowalny do %s\",\n\n    \"misc.refinedstorage.security.no_permission\": \"Nie masz zezwolenia na wykonanie tej czynności.\",\n\n    \"misc.refinedstorage.start\": \"Start\",\n    \"misc.refinedstorage.clear\": \"Wyczyść\",\n    \"misc.refinedstorage.set\": \"Ustaw\",\n    \"misc.refinedstorage.cancel_all\": \"Anuluj wszystko\",\n    \"misc.refinedstorage.priority\": \"Priorytet\",\n    \"misc.refinedstorage.exact\": \"Dokładny\",\n    \"misc.refinedstorage.processing\": \"Przetwarzanie\",\n\n    \"misc.refinedstorage.total\": \"%s całości\",\n\n    \"misc.refinedstorage.last_modified.just_now\": \"Ostatnio modyfikowany przed chwilą przez gracza %s\",\n    \"misc.refinedstorage.last_modified.second\": \"Ostatnio modyfikowany %d sekundę temu przez gracza %s\",\n    \"misc.refinedstorage.last_modified.seconds\": \"Ostatnio modyfikowany %d sekund(y) temu przez gracza %s\",\n    \"misc.refinedstorage.last_modified.minute\": \"Ostatnio modyfikowany %d minutę temu przez gracza %s\",\n    \"misc.refinedstorage.last_modified.minutes\": \"Ostatnio modyfikowany %d minut(y) temu przez gracza %s\",\n    \"misc.refinedstorage.last_modified.hour\": \"Ostatnio modyfikowany %d godzinę temu przez gracza %s\",\n    \"misc.refinedstorage.last_modified.hours\": \"Ostatnio modyfikowany %d godzin(y) temu przez gracza %s\\n\",\n    \"misc.refinedstorage.last_modified.day\": \"Ostatnio modyfikowany %d dzień temu przez gracza %s\",\n    \"misc.refinedstorage.last_modified.days\": \"Ostatnio modyfikowany %d dni temu przez gracza %s\",\n    \"misc.refinedstorage.last_modified.week\": \"Ostatnio modyfikowany %d tydzień temu przez gracza %s\",\n    \"misc.refinedstorage.last_modified.weeks\": \"Ostatnio modyfikowany %d tygodni(e) temu przez gracza %s\",\n    \"misc.refinedstorage.last_modified.year\": \"Ostatnio modyfikowany %d rok temu przez gracza %s\",\n    \"misc.refinedstorage.last_modified.years\": \"Ostatnio modyfikowany %d lat(a) temu przez gracza %s\",\n\n    \"sidebutton.refinedstorage.exact_mode\": \"Tryb dokładny\",\n    \"sidebutton.refinedstorage.exact_mode.on\": \"Wł.\",\n    \"sidebutton.refinedstorage.exact_mode.off\": \"Wył.\",\n\n    \"sidebutton.refinedstorage.redstone_mode\": \"Tryb redstone\",\n    \"sidebutton.refinedstorage.redstone_mode.0\": \"Ignoruj sygnał redstone\",\n    \"sidebutton.refinedstorage.redstone_mode.1\": \"Działaj tylko z sygnałem redstone\",\n    \"sidebutton.refinedstorage.redstone_mode.2\": \"Działaj tylko bez sygnału redstone\",\n\n    \"sidebutton.refinedstorage.crafter_mode\": \"Tryb przetwarzacza receptur\",\n    \"sidebutton.refinedstorage.crafter_mode.0\": \"Ignoruj sygnał redstone\",\n    \"sidebutton.refinedstorage.crafter_mode.1\": \"Sygnał redstone odblokowuje auto-wytwarzanie\",\n    \"sidebutton.refinedstorage.crafter_mode.2\": \"Sygnał redstone blokuje auto-wytwarzanie\",\n    \"sidebutton.refinedstorage.crafter_mode.3\": \"Puls redstone dodaje następny zestaw\",\n\n    \"sidebutton.refinedstorage.grid.view_type\": \"Widok\",\n    \"sidebutton.refinedstorage.grid.view_type.0\": \"Normalny\",\n    \"sidebutton.refinedstorage.grid.view_type.1\": \"Bez przedm. auto-wytwarzalnych\",\n    \"sidebutton.refinedstorage.grid.view_type.2\": \"Tylko przedm. auto-wytwarzalne\",\n    \"sidebutton.refinedstorage.grid.sorting.direction\": \"Kierunek sortowania\",\n    \"sidebutton.refinedstorage.grid.sorting.direction.0\": \"Rosnący\",\n    \"sidebutton.refinedstorage.grid.sorting.direction.1\": \"Malejący\",\n    \"sidebutton.refinedstorage.grid.sorting.type\": \"Tryb sortowania\",\n    \"sidebutton.refinedstorage.grid.sorting.type.0\": \"Ilość\",\n    \"sidebutton.refinedstorage.grid.sorting.type.1\": \"Nazwa\",\n    \"sidebutton.refinedstorage.grid.sorting.type.2\": \"ID\",\n    \"sidebutton.refinedstorage.grid.sorting.type.3\": \"InventoryTweaks\",\n    \"sidebutton.refinedstorage.grid.sorting.type.4\": \"Ostatnio modyfikowany\",\n    \"sidebutton.refinedstorage.grid.search_box_mode\": \"Tryb paska wyszukiwania\",\n    \"sidebutton.refinedstorage.grid.search_box_mode.0\": \"Normalny\",\n    \"sidebutton.refinedstorage.grid.search_box_mode.1\": \"Normalny (automatycznie wybrany)\",\n    \"sidebutton.refinedstorage.grid.search_box_mode.2\": \"Synchronizowany z JEI\",\n    \"sidebutton.refinedstorage.grid.search_box_mode.3\": \"Synchronizowany z JEI (automatycznie wybrany)\",\n    \"sidebutton.refinedstorage.grid.search_box_mode.4\": \"Synchronizowany z JEI (dwukierunkowo)\",\n    \"sidebutton.refinedstorage.grid.search_box_mode.5\": \"Synchronizowany z JEI (dwukierunkowo, automatycznie wybrany)\",\n    \"sidebutton.refinedstorage.grid.size\": \"Rozmiar\",\n    \"sidebutton.refinedstorage.grid.size.0\": \"Rozciągnij\",\n    \"sidebutton.refinedstorage.grid.size.1\": \"Mały\",\n    \"sidebutton.refinedstorage.grid.size.2\": \"Średni\",\n    \"sidebutton.refinedstorage.grid.size.3\": \"Duży\",\n\n    \"sidebutton.refinedstorage.mode\": \"Tryb\",\n    \"sidebutton.refinedstorage.mode.whitelist\": \"Biała lista\",\n    \"sidebutton.refinedstorage.mode.blacklist\": \"Czarna lista\",\n\n    \"sidebutton.refinedstorage.iomode\": \"Tryb we.wy.\",\n    \"sidebutton.refinedstorage.iomode.insert\": \"Wkładaj do sieci\",\n    \"sidebutton.refinedstorage.iomode.extract\": \"Zabieraj z sieci\",\n\n    \"sidebutton.refinedstorage.type\": \"Typ\",\n    \"sidebutton.refinedstorage.type.0\": \"Przedmioty\",\n    \"sidebutton.refinedstorage.type.1\": \"Ciecze\",\n\n    \"sidebutton.refinedstorage.detector.mode\": \"Tryb\",\n    \"sidebutton.refinedstorage.detector.mode.0\": \"Emituje sygnał kiedy poniżej ilości\",\n    \"sidebutton.refinedstorage.detector.mode.1\": \"Emituje sygnał kiedy równy ilości\",\n    \"sidebutton.refinedstorage.detector.mode.2\": \"Emituje sygnał kiedy powyżej ilości\",\n    \"sidebutton.refinedstorage.constructor.drop\": \"Upuszczaj przedmioty zamiast stawiać\",\n    \"sidebutton.refinedstorage.destructor.pickup\": \"Podnoś przedmioty zamiast niszczyć\",\n    \"sidebutton.refinedstorage.access_type\": \"Tryb dostępu\",\n    \"sidebutton.refinedstorage.access_type.0\": \"Wkładanie i zabieranie\",\n    \"sidebutton.refinedstorage.access_type.1\": \"Tylko wkładanie\",\n    \"sidebutton.refinedstorage.access_type.2\": \"Tylko zabieranie\",\n\n    \"block.refinedstorage.controller\": \"Kontroler\",\n    \"block.refinedstorage.creative_controller\": \"Kreatywny kontroler\",\n    \"block.refinedstorage.cable\": \"Kabel\",\n    \"block.refinedstorage.grid\": \"Terminal\",\n    \"block.refinedstorage.crafting_grid\": \"Terminal konstruowania\",\n    \"block.refinedstorage.pattern_grid\": \"Terminal szablonów\",\n    \"block.refinedstorage.fluid_grid\": \"Terminal płynów\",\n    \"block.refinedstorage.disk_drive\": \"Napęd dyskowy\",\n    \"block.refinedstorage.disk_manipulator\": \"Manipulator dysków\",\n    \"block.refinedstorage.external_storage\": \"Zewnętrzny magazyn\",\n    \"block.refinedstorage.importer\": \"Importer\",\n    \"block.refinedstorage.exporter\": \"Eksporter\",\n    \"block.refinedstorage.detector\": \"Detektor\",\n    \"block.refinedstorage.machine_casing\": \"Obudowa maszyn\",\n    \"block.refinedstorage.destructor\": \"Destruktor\",\n    \"block.refinedstorage.constructor\": \"Konstruktor\",\n    \"block.refinedstorage.1k_storage_block\": \"Blok przechowywania 1k\",\n    \"block.refinedstorage.4k_storage_block\": \"Blok przechowywania 4k\",\n    \"block.refinedstorage.16k_storage_block\": \"Blok przechowywania 16k\",\n    \"block.refinedstorage.64k_storage_block\": \"Blok przechowywania 64k\",\n    \"block.refinedstorage.creative_storage_block\": \"Kreatywny blok przechowywania\",\n    \"block.refinedstorage.relay\": \"Przekaźnik\",\n    \"block.refinedstorage.interface\": \"Interfejs\",\n    \"block.refinedstorage.crafting_monitor\": \"Monitor konstruowania\",\n    \"block.refinedstorage.wireless_transmitter\": \"Nadajnik bezprzewodowy\",\n    \"block.refinedstorage.crafter\": \"Przetwarzacz receptur\",\n    \"block.refinedstorage.network_receiver\": \"Odbiornik sieci\",\n    \"block.refinedstorage.network_transmitter\": \"Nadajnik sieci\",\n    \"block.refinedstorage.fluid_interface\": \"Interfejs płynów\",\n    \"block.refinedstorage.64k_fluid_storage_block\": \"Blok przechowywania cieczy 64k\",\n    \"block.refinedstorage.256k_fluid_storage_block\": \"Blok przechowywania cieczy 256k\",\n    \"block.refinedstorage.1024k_fluid_storage_block\": \"Blok przechowywania cieczy 1024k\",\n    \"block.refinedstorage.4096k_fluid_storage_block\": \"Blok przechowywania cieczy 4096k\",\n    \"block.refinedstorage.creative_fluid_storage_block\": \"Kreatywny blok przechowywania cieczy\",\n    \"block.refinedstorage.security_manager\": \"Menadżer bezpieczeństwa\",\n    \"block.refinedstorage.quartz_enriched_iron_block\": \"Blok żelaza kwarcowego\",\n    \"block.refinedstorage.storage_monitor\": \"Monitor przechowywania\",\n    \"block.refinedstorage.portable_grid\": \"Przenośny terminal\",\n    \"block.refinedstorage.creative_portable_grid\": \"Kreatywny przenośny terminal\",\n    \"block.refinedstorage.portable_grid.tooltip\": \"Skradaj się aby postawić.\",\n    \"block.refinedstorage.crafter_manager\": \"Menadżer przetwarzaczy receptur\",\n    \"item.refinedstorage.1k_storage_disk\": \"Dysk przechowywania 1k\",\n    \"item.refinedstorage.4k_storage_disk\": \"Dysk przechowywania 4k\",\n    \"item.refinedstorage.16k_storage_disk\": \"Dysk przechowywania 16k\",\n    \"item.refinedstorage.64k_storage_disk\": \"Dysk przechowywania 64k\",\n    \"item.refinedstorage.creative_storage_disk\": \"Kreatywny dysk przechowywania\",\n    \"item.refinedstorage.64k_fluid_storage_disk\": \"Dysk przechowywania cieczy 64k\",\n    \"item.refinedstorage.256k_fluid_storage_disk\": \"Dysk przechowywania cieczy 256k\",\n    \"item.refinedstorage.1024k_fluid_storage_disk\": \"Dysk przechowywania cieczy 1024k\",\n    \"item.refinedstorage.4096k_fluid_storage_disk\": \"Dysk przechowywania cieczy 4096k\",\n    \"item.refinedstorage.creative_fluid_storage_disk\": \"Kreatywny dysk przechowywania cieczy\",\n    \"item.refinedstorage.wireless_grid\": \"Bezprzewodowy terminal\",\n    \"item.refinedstorage.creative_wireless_grid\": \"Kreatywny bezprzewodowy terminal\",\n    \"item.refinedstorage.wireless_fluid_grid\": \"Bezprzewodowy terminal cieczy\",\n    \"item.refinedstorage.creative_wireless_fluid_grid\": \"Kreatywny bezprzewodowy terminal cieczy\",\n    \"item.refinedstorage.wireless_crafting_monitor\": \"Bezprzewodowy monitor konstruowania\",\n    \"item.refinedstorage.creative_wireless_crafting_monitor\": \"Kreatywny bezprzewodowy monitor konstruowania\",\n    \"item.refinedstorage.quartz_enriched_iron\": \"Żelazo kwarcowe\",\n    \"item.refinedstorage.construction_core\": \"Rdzeń konstrukcji\",\n    \"item.refinedstorage.destruction_core\": \"Rdzeń destrukcji\",\n    \"item.refinedstorage.silicon\": \"Silikon\",\n    \"item.refinedstorage.raw_basic_processor\": \"Surowy podstawowy procesor\",\n    \"item.refinedstorage.raw_improved_processor\": \"Surowy ulepszony procesor\",\n    \"item.refinedstorage.raw_advanced_processor\": \"Surowy zaawansowany procesor\",\n    \"item.refinedstorage.basic_processor\": \"Podstawowy procesor\",\n    \"item.refinedstorage.improved_processor\": \"Ulepszony procesor\",\n    \"item.refinedstorage.advanced_processor\": \"Zaawansowany procesor\",\n    \"item.refinedstorage.1k_storage_part\": \"Pamięć przechowywania 1k\",\n    \"item.refinedstorage.4k_storage_part\": \"Pamięć przechowywania 4k\",\n    \"item.refinedstorage.16k_storage_part\": \"Pamięć przechowywania 16k\",\n    \"item.refinedstorage.64k_storage_part\": \"Pamięć przechowywania 64k\",\n    \"item.refinedstorage.64k_fluid_storage_part\": \"Pamięć przechowywania cieczy 64k\",\n    \"item.refinedstorage.256k_fluid_storage_part\": \"Pamięć przechowywania cieczy 256k\",\n    \"item.refinedstorage.1024k_fluid_storage_part\": \"Pamięć przechowywania cieczy 1024k\",\n    \"item.refinedstorage.4096k_fluid_storage_part\": \"Pamięć przechowywania cieczy 4096k\",\n    \"item.refinedstorage.pattern\": \"Szablon\",\n    \"item.refinedstorage.upgrade\": \"Ulepszenie\",\n    \"item.refinedstorage.range_upgrade\": \"Ulepszenie zasięgu\",\n    \"item.refinedstorage.speed_upgrade\": \"Ulepszenie szybkości\",\n    \"item.refinedstorage.crafting_upgrade\": \"Ulepszenie konstruowania\",\n    \"item.refinedstorage.stack_upgrade\": \"Ulepszenie stosu\",\n    \"item.refinedstorage.silk_touch_upgrade\": \"Ulepszenie jedwabnego dotyku\",\n    \"item.refinedstorage.fortune_1_upgrade\": \"Ulepszenie fortuny\",\n    \"item.refinedstorage.fortune_2_upgrade\": \"Ulepszenie fortuny\",\n    \"item.refinedstorage.fortune_3_upgrade\": \"Ulepszenie fortuny\",\n    \"item.refinedstorage.regulator_upgrade\": \"Ulepszenie regulacyjne\",\n    \"item.refinedstorage.storage_housing\": \"Obudowa dysku\",\n    \"item.refinedstorage.filter\": \"Filtr\",\n    \"item.refinedstorage.network_card\": \"Karta sieciowa\",\n    \"item.refinedstorage.wrench\": \"Klucz\",\n    \"item.refinedstorage.security_card\": \"Karta bezpieczeństwa\",\n    \"item.refinedstorage.security_card.owner\": \"Przypisana do: %s\",\n    \"item.refinedstorage.processor_binding\": \"Spoiwo procesora\",\n    \"commands.refinedstorage.disk.create.error.disk_not_found\": \"NIe znaleziono dysku %s.\",\n    \"commands.refinedstorage.disk.create.success\": \"Z powodzeniem oddano dysk %s dla %s.\",\n    \"commands.refinedstorage.network.list.pos\": \"Lokalizacja sieci X: %d, Y: %d, Z: %d\",\n    \"commands.refinedstorage.network.list.tick_times\": \"Mediana czasu ticku: %s ms. Mediana TPS: %s\",\n    \"commands.refinedstorage.network.list.autocrafting_tasks\": \"%s zadań\",\n    \"commands.refinedstorage.network.list.nodes\": \"%s instancji\",\n    \"commands.refinedstorage.network.list.energy_usage\": \"Zużycie energii: %s\",\n    \"commands.refinedstorage.network.get.error.not_found\": \"Nie znaleziono sieci.\",\n    \"commands.refinedstorage.network.autocrafting.get.error.not_found\": \"Nie znaleziono zadania.\",\n    \"commands.refinedstorage.network.autocrafting.cancel.single\": \"Anulowano %s zadanie.\",\n    \"commands.refinedstorage.network.autocrafting.cancel.multiple\": \"Anulowano %s zadania/zadań.\",\n    \"advancements.refinedstorage.controlling.description\": \"Wytwórz kontroler\",\n    \"advancements.refinedstorage.connecting\": \"Połączenie\",\n    \"advancements.refinedstorage.connecting.description\": \"Możesz ustawić wszystkie urządzenia obok siebie aby je połączyć, lub użyć kabla.\",\n    \"advancements.refinedstorage.conditional_connecting\": \"Sterowanie połączeniem\",\n    \"advancements.refinedstorage.conditional_connecting.description\": \"Wytwórz przekaźnik, aby kontrolować z pomocą redstone, połączenie w sieci\",\n    \"advancements.refinedstorage.drives\": \"Dyski\",\n    \"advancements.refinedstorage.drives.description\": \"Wytwórz napęd dyskowy aby móc przechowywać dyski\",\n    \"advancements.refinedstorage.manipulating_disks\": \"Manipulowanie dyskami\",\n    \"advancements.refinedstorage.manipulating_disks.description\": \"Użyj manipulatora dysków aby łatwo modyfikować zawartość dysków\",\n    \"advancements.refinedstorage.storing_items\": \"Przechowywanie przedmiotów\",\n    \"advancements.refinedstorage.storing_items.description\": \"Wytwórz dysk przechowywania i wsadź go do napędy dyskowego\",\n    \"advancements.refinedstorage.viewing_items\": \"Przeglądanie przedmiotów\",\n    \"advancements.refinedstorage.viewing_items.description\": \"Wytwórz terminal, aby mieć dostęp do zmagazynowanych przedmiotów\",\n    \"advancements.refinedstorage.portable_storage\": \"Przenośne przechowywanie\",\n    \"advancements.refinedstorage.portable_storage.description\": \"Wytwórz przenośny terminal, aby mieć dostęp do zmagazynowanych przedmiotów bez bezpośredniego połączenia z siecią\",\n    \"advancements.refinedstorage.upgrading_your_grid\": \"Ulepszanie terminala\",\n    \"advancements.refinedstorage.upgrading_your_grid.description\": \"Ulepsz swój terminal do terminalu konstruowania, aby mieć dostęp do siatki konstruowania bezpośrednio w terminalu\",\n    \"advancements.refinedstorage.storing_fluids\": \"Przechowywanie cieczy\",\n    \"advancements.refinedstorage.storing_fluids.description\": \"Wytwórz dysk przechowywania cieczy i wsadź go do napędy dyskowego\",\n    \"advancements.refinedstorage.viewing_fluids\": \"Przeglądanie cieczy\",\n    \"advancements.refinedstorage.viewing_fluids.description\": \"Wytwórz terminal cieczy, aby mieć dostęp do zmagazynowanych płynów\",\n    \"advancements.refinedstorage.better_than_a_barrel\": \"Lepsze niż beczka\",\n    \"advancements.refinedstorage.better_than_a_barrel.description\": \"Wytwórz monitor przechowywania, aby łatwo zarządzać pojedynczym przedmiotem\",\n    \"advancements.refinedstorage.autocrafting\": \"Auto-wytwarzanie\",\n    \"advancements.refinedstorage.autocrafting.description\": \"Wytwórz przetwarzacz receptur\",\n    \"advancements.refinedstorage.pattern_creation\": \"Tworzenie szablonów\",\n    \"advancements.refinedstorage.pattern_creation.description\": \"Konfiguruj szablony z użyciem terminala szablonów\",\n    \"advancements.refinedstorage.monitoring\": \"Monitorowanie\",\n    \"advancements.refinedstorage.monitoring.description\": \"Sprawdź status Twoich zadań konstruowania z pomocą monitora konstruowania\",\n    \"advancements.refinedstorage.managing_patterns\": \"Zarządzanie szablonami\",\n    \"advancements.refinedstorage.managing_patterns.description\": \"Wytwórz menadżer przetwarzaczy receptur, aby łatwiej zarządzać szablonami\",\n    \"advancements.refinedstorage.importing\": \"Importowanie\",\n    \"advancements.refinedstorage.importing.description\": \"Automatycznie importuj przedmioty lub ciecze do sieci z pomocą importera\",\n    \"advancements.refinedstorage.destruction\": \"Niszczenie\",\n    \"advancements.refinedstorage.destruction.description\": \"Automatycznie niszcz bloki lub podnoś ciecze i importuj je do sieci z pomocą destruktora\",\n    \"advancements.refinedstorage.exporting\": \"Eksportowanie\",\n    \"advancements.refinedstorage.exporting.description\": \"Automatycznie eksportuj przedmioty lub ciecze z sieci z pomocą eksportera\",\n    \"advancements.refinedstorage.construction\": \"Konstrukcja\",\n    \"advancements.refinedstorage.construction.description\": \"Automatycznie stawiaj bloki lub ciecze i importuj je do sieci z pomocą destruktora\",\n    \"advancements.refinedstorage.security\": \"Bezpieczeństwo\",\n    \"advancements.refinedstorage.security.description\": \"Zabezpiecz swoją sieć z pomocą menadżera i karty bezpieczeństwa\",\n    \"advancements.refinedstorage.wireless\": \"Bezprzewodowo\",\n    \"advancements.refinedstorage.wireless.description\": \"Nadawaj bezprzewodowy sygnał sieci z pomocą nadajnika bezprzewodowego\",\n    \"advancements.refinedstorage.wireless_items\": \"Bezprzewodowe przedmioty\",\n    \"advancements.refinedstorage.wireless_items.description\": \"Komunikuj się z siecią bezprzewodowo z pomocą bezprzewodowego terminala\",\n    \"advancements.refinedstorage.wireless_fluids\": \"Bezprzewodowe ciecze\",\n    \"advancements.refinedstorage.wireless_fluids.description\": \"Komunikuj się z siecią bezprzewodowo z pomocą bezprzewodowego terminala cieczy\",\n    \"advancements.refinedstorage.wireless_monitoring\": \"Bezprzewodowe monitorowanie\",\n    \"advancements.refinedstorage.wireless_monitoring.description\": \"Sprawdzaj status Twoich zadań konstruowania bezprzewodowo z pomocą bezprzewodowego monitora konstruowania\",\n    \"advancements.refinedstorage.no_cables_required\": \"Kable są niepotrzebne\",\n    \"advancements.refinedstorage.no_cables_required.description\": \"Dodaj więcej komponentów do Twojej sieci bez użycia kabli, ale z pomocą nadajnika i odbiornika sieciowego, oraz karty sieciowej\",\n    \"advancements.refinedstorage.upgrading\": \"Ulepszanie\",\n    \"advancements.refinedstorage.upgrading.description\": \"Wytwórz ulepszenie aby polepszyć działanie różnych urządzeń\",\n    \"advancements.refinedstorage.crafting_on_demand\": \"Konstruowanie na żądanie\",\n    \"advancements.refinedstorage.crafting_on_demand.description\": \"Użyj ulepszenia konstruowania w interfejsie, eksporterze lub konstruktorze aby wytwarzać przedmioty na ich żądanie\",\n    \"advancements.refinedstorage.detecting\": \"Detekcja\",\n    \"advancements.refinedstorage.detecting.description\": \"Wykrywaj przedmioty lub ciecze w sieci z pomocą Detektora\",\n    \"advancements.refinedstorage.interface_to_the_world\": \"Interfejs świata\",\n    \"advancements.refinedstorage.interface_to_the_world.description\": \"Eksportuj i importuj przedmioty w tym samym czasie z pomocą interfejsu\",\n    \"advancements.refinedstorage.storing_externally\": \"Zewnętrzne przechowywanie\",\n    \"advancements.refinedstorage.storing_externally.description\": \"Użyj zewnętrznego magazynu aby dać sieci dostęp do innego bloku przechowującego przedmioty lub ciecze, jak na przykład skrzynia\"\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/lang/pt_br.json",
    "content": "{\n  \"itemGroup.refinedstorage\": \"Refined Storage\",\n\n  \"key.refinedstorage.focusSearchBar\": \"Ir para a barra de pesquisa da grade.\",\n\n  \"gui.refinedstorage.controller\": \"Controlador\",\n  \"gui.refinedstorage.creative_controller\": \"Controlador (modo criativo)\",\n  \"gui.refinedstorage.grid\": \"Grade\",\n  \"gui.refinedstorage.grid.craft\": \"Fabricar\",\n  \"gui.refinedstorage.crafting_grid\": \"Grade de fabricações\",\n  \"gui.refinedstorage.pattern_grid\": \"Grade de padrões\",\n  \"gui.refinedstorage.grid.pattern_create\": \"Criar padrão\",\n  \"gui.refinedstorage.fluid_grid\": \"Grade de fluidos\",\n  \"gui.refinedstorage.portable_grid\": \"Grade portátil\",\n  \"gui.refinedstorage.disk_drive\": \"Drive\",\n  \"gui.refinedstorage.disk_drive.disks\": \"Discos\",\n  \"gui.refinedstorage.external_storage\": \"Armazenamento externo\",\n  \"gui.refinedstorage.importer\": \"Importador\",\n  \"gui.refinedstorage.exporter\": \"Exportador\",\n  \"gui.refinedstorage.detector\": \"Detector\",\n  \"gui.refinedstorage.destructor\": \"Destruidor\",\n  \"gui.refinedstorage.constructor\": \"Construtor\",\n  \"gui.refinedstorage.relay\": \"Retransmissor\",\n  \"gui.refinedstorage.interface.import\": \"Interface de importação\",\n  \"gui.refinedstorage.interface.export\": \"Interface de exportação\",\n  \"gui.refinedstorage.crafting_monitor\": \"Monitor de fabricações\",\n  \"gui.refinedstorage.wireless_crafting_monitor\": \"Monitor de fabricações sem fio\",\n  \"gui.refinedstorage.crafting_monitor.machine_none\": \"Nenhuma máquina encontrada\",\n  \"gui.refinedstorage.wireless_transmitter\": \"Transmissor sem fio\",\n  \"gui.refinedstorage.wireless_transmitter.distance\": \"%d blocos\",\n  \"gui.refinedstorage.crafter\": \"Fabricador\",\n  \"gui.refinedstorage.filter\": \"Filtro\",\n  \"gui.refinedstorage.filter.compare_nbt\": \"NBT\",\n  \"gui.refinedstorage.filter.mod_filter\": \"Filtrar mod\",\n  \"gui.refinedstorage.network_transmitter\": \"Transmissor de rede\",\n  \"gui.refinedstorage.network_transmitter.distance\": \"%d blocos\",\n  \"gui.refinedstorage.network_transmitter.missing_card\": \"Ausência de cartão de rede\",\n  \"gui.refinedstorage.fluid_interface\": \"Interface de fluidos\",\n  \"gui.refinedstorage.fluid_interface.in\": \"Entrada\",\n  \"gui.refinedstorage.fluid_interface.out\": \"Saída\",\n  \"gui.refinedstorage.crafting_preview\": \"Pré-visualização da fabricação\",\n  \"gui.refinedstorage.crafting_preview.to_craft\": \"Para fabricar: %d\",\n  \"gui.refinedstorage.crafting_preview.available\": \"Disponível: %d\",\n  \"gui.refinedstorage.crafting_preview.missing\": \"Ausência de: %d\",\n  \"gui.refinedstorage.crafting_preview.circular\": \"Dependência circular!\",\n  \"gui.refinedstorage.crafting_preview.loop\": \"Loop em processamento...\",\n  \"gui.refinedstorage.security_manager\": \"Gerenciador de segurança\",\n  \"gui.refinedstorage.security_manager.configure\": \"Configurar\",\n  \"gui.refinedstorage.security_manager.permission.0\": \"Inserir\",\n  \"gui.refinedstorage.security_manager.permission.0.tooltip\": \"Inserindo itens na rede\",\n  \"gui.refinedstorage.security_manager.permission.1\": \"Extrair\",\n  \"gui.refinedstorage.security_manager.permission.1.tooltip\": \"Extraindo itens da rede\",\n  \"gui.refinedstorage.security_manager.permission.2\": \"Auto-fabricação\",\n  \"gui.refinedstorage.security_manager.permission.2.tooltip\": \"Iniciando, cancelando e visualizando tarefas de fabricação\",\n  \"gui.refinedstorage.security_manager.permission.3\": \"Modificar\",\n  \"gui.refinedstorage.security_manager.permission.3.tooltip\": \"Abrindo interfaces do bloco\",\n  \"gui.refinedstorage.security_manager.permission.4\": \"Fabricar\",\n  \"gui.refinedstorage.security_manager.permission.4.tooltip\": \"Adicionando ou removendo dispositivos para ou a partir da rede\",\n  \"gui.refinedstorage.security_manager.permission.5\": \"Segurança\",\n  \"gui.refinedstorage.security_manager.permission.5.tooltip\": \"Capacidade de alterar as opções de segurança\",\n  \"gui.refinedstorage.storage_monitor\": \"Monitor de armazenamento\",\n\n  \"misc.refinedstorage.energy_stored\": \"%d / %d RF\",\n  \"misc.refinedstorage.energy_usage\": \"Uso: %d RF/t\",\n  \"misc.refinedstorage.energy_usage_minimal\": \"%d RF/t\",\n\n  \"misc.refinedstorage.storage.stored\": \"Stored: %s\",\n  \"misc.refinedstorage.storage.stored_capacity\": \"Stored: %s / %s\",\n  \"misc.refinedstorage.storage.stored_minimal\": \"%s\",\n  \"misc.refinedstorage.storage.stored_capacity_minimal\": \"%s / %s\",\n  \"misc.refinedstorage.storage.full\": \"%d%% cheio\",\n\n  \"misc.refinedstorage.network_item.tooltip\": \"Ligado a %d, %d, %d.\",\n  \"misc.refinedstorage.network_item.out_of_range\": \"Não há transmissor sem fio no alcance.\",\n  \"misc.refinedstorage.network_item.not_found\": \"Controlador não encontrado.\",\n\n  \"misc.refinedstorage.network_card.tooltip\": \"Conectado a %d, %d, %d em %s.\",\n\n  \"misc.refinedstorage.pattern.inputs\": \"Entradas\",\n  \"misc.refinedstorage.pattern.outputs\": \"Saídas\",\n  \"misc.refinedstorage.pattern.invalid\": \"Padrão inválido\",\n\n  \"misc.refinedstorage.security.no_permission\": \"Você não possui permissão para executar essa ação.\",\n\n  \"misc.refinedstorage.start\": \"Começar\",\n  \"misc.refinedstorage.clear\": \"Limpar\",\n  \"misc.refinedstorage.set\": \"Definir\",\n  \"misc.refinedstorage.cancel_all\": \"Cancelar tudo\",\n  \"misc.refinedstorage.priority\": \"Prioridade\",\n  \"misc.refinedstorage.processing\": \"Processamento\",\n\n  \"sidebutton.refinedstorage.redstone_mode\": \"Modo de redstone\",\n  \"sidebutton.refinedstorage.redstone_mode.0\": \"Ignorar o sinal de redstone\",\n  \"sidebutton.refinedstorage.redstone_mode.1\": \"Apenas funcionar com sinal de redstone\",\n  \"sidebutton.refinedstorage.redstone_mode.2\": \"Apenas funcionar sem sinal de redstone\",\n\n  \"sidebutton.refinedstorage.grid.view_type\": \"Exibição\",\n  \"sidebutton.refinedstorage.grid.view_type.0\": \"Normal\",\n  \"sidebutton.refinedstorage.grid.view_type.1\": \"Apenas não fabricáveis\",\n  \"sidebutton.refinedstorage.grid.view_type.2\": \"Apenas fabricáveis\",\n  \"sidebutton.refinedstorage.grid.sorting.direction\": \"Direção da classificação\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.0\": \"Ascendente\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.1\": \"Descendente\",\n  \"sidebutton.refinedstorage.grid.sorting.type\": \"Tipo da classificação\",\n  \"sidebutton.refinedstorage.grid.sorting.type.0\": \"Quantidade\",\n  \"sidebutton.refinedstorage.grid.sorting.type.1\": \"Nome\",\n  \"sidebutton.refinedstorage.grid.sorting.type.2\": \"Id\",\n  \"sidebutton.refinedstorage.grid.sorting.type.3\": \"InventoryTweaks\",\n  \"sidebutton.refinedstorage.grid.search_box_mode\": \"Modo da caixa de pesquisa\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.0\": \"Normal\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.1\": \"Normal (auto-seleção)\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.2\": \"Sincronizado com JEI\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.3\": \"Sincronizado com JEI (auto-seleção)\",\n  \"sidebutton.refinedstorage.grid.size\": \"Tamanho\",\n  \"sidebutton.refinedstorage.grid.size.0\": \"Esticado\",\n  \"sidebutton.refinedstorage.grid.size.1\": \"Pequeno\",\n  \"sidebutton.refinedstorage.grid.size.2\": \"Médio\",\n  \"sidebutton.refinedstorage.grid.size.3\": \"Grande\",\n\n  \"sidebutton.refinedstorage.mode\": \"Modo\",\n  \"sidebutton.refinedstorage.mode.whitelist\": \"Lista branca\",\n  \"sidebutton.refinedstorage.mode.blacklist\": \"Lista negra\",\n\n  \"sidebutton.refinedstorage.iomode\": \"Modo IO\",\n  \"sidebutton.refinedstorage.iomode.insert\": \"Inserir na rede\",\n  \"sidebutton.refinedstorage.iomode.extract\": \"Extrair da rede\",\n\n  \"sidebutton.refinedstorage.type\": \"Tipo\",\n  \"sidebutton.refinedstorage.type.0\": \"Itens\",\n  \"sidebutton.refinedstorage.type.1\": \"Fluidos\",\n\n  \"sidebutton.refinedstorage.detector.mode\": \"Modo\",\n  \"sidebutton.refinedstorage.detector.mode.0\": \"Emite um sinal quando estiver abaixo do valor\",\n  \"sidebutton.refinedstorage.detector.mode.1\": \"Emite um sinal quando estiver no valor\",\n  \"sidebutton.refinedstorage.detector.mode.2\": \"Emite um sinal quando estiver acima do valor\",\n\n  \"sidebutton.refinedstorage.constructor.drop\": \"Soltar os blocos em vez de colocar\",\n\n  \"sidebutton.refinedstorage.destructor.pickup\": \"Pegue os itens em vez de quebrar\",\n\n  \"sidebutton.refinedstorage.access_type\": \"Tipo de acesso\",\n  \"sidebutton.refinedstorage.access_type.0\": \"Inserir e extrair\",\n  \"sidebutton.refinedstorage.access_type.1\": \"Inserir apenas\",\n  \"sidebutton.refinedstorage.access_type.2\": \"Extrair apenas\",\n\n  \"block.refinedstorage.controller\": \"Controlador\",\n  \"block.refinedstorage.creative_controller\": \"Controlador (modo criativo)\",\n  \"block.refinedstorage.cable\": \"Cabo\",\n  \"block.refinedstorage.grid\": \"Grade\",\n  \"block.refinedstorage.crafting_grid\": \"Grade de fabricações\",\n  \"block.refinedstorage.pattern_grid\": \"Grade de padrões\",\n  \"block.refinedstorage.fluid_grid\": \"Grade de fluidos\",\n  \"block.refinedstorage.disk_drive\": \"Unidade de disco\",\n  \"block.refinedstorage.disk_manipulator\": \"Manipulador de disco\",\n  \"block.refinedstorage.external_storage\": \"Armazenamento externo\",\n  \"block.refinedstorage.importer\": \"Importador\",\n  \"block.refinedstorage.exporter\": \"Exportador\",\n  \"block.refinedstorage.detector\": \"Detector\",\n  \"block.refinedstorage.machine_casing\": \"Gabinete de máquina\",\n  \"block.refinedstorage.destructor\": \"Destruidor\",\n  \"block.refinedstorage.constructor\": \"Construtor\",\n  \"block.refinedstorage.1k_storage_block\": \"Bloco de armazenamento 1k\",\n  \"block.refinedstorage.4k_storage_block\": \"Bloco de armazenamento 4k\",\n  \"block.refinedstorage.16k_storage_block\": \"Bloco de armazenamento 16k\",\n  \"block.refinedstorage.64k_storage_block\": \"Bloco de armazenamento 64k\",\n  \"block.refinedstorage.creative_storage_block\": \"Bloco de armazenamento (modo criativo)\",\n  \"block.refinedstorage.relay\": \"Retransmissor\",\n  \"block.refinedstorage.interface\": \"Interface\",\n  \"block.refinedstorage.crafting_monitor\": \"Monitor de fabricações\",\n  \"block.refinedstorage.wireless_transmitter\": \"Transmissor wireless\",\n  \"block.refinedstorage.wireless_transmitter.tooltip\": \"Precisa ser colocado em %s.\",\n  \"block.refinedstorage.crafter\": \"Fabricador\",\n  \"block.refinedstorage.network_receiver\": \"Receptor de rede\",\n  \"block.refinedstorage.network_transmitter\": \"Transmissor de rede\",\n  \"block.refinedstorage.fluid_interface\": \"Interface de fluidos\",\n  \"block.refinedstorage.64k_fluid_storage_block\": \"Bloco de armazenamento de fluidos 64k\",\n  \"block.refinedstorage.256k_fluid_storage_block\": \"Bloco de armazenamento de fluidos 256k\",\n  \"block.refinedstorage.1024k_fluid_storage_block\": \"Bloco de armazenamento de fluidos 1024k\",\n  \"block.refinedstorage.4096k_fluid_storage_block\": \"Bloco de armazenamento de fluidos 4096k\",\n  \"block.refinedstorage.creative_fluid_storage_block\": \"Bloco de armazenamento de fluidos (modo criativo)\",\n  \"block.refinedstorage.security_manager\": \"Gerenciador de segurança\",\n  \"block.refinedstorage.quartz_enriched_iron_block\": \"Bloco de ferro enriquecido com quartzo\",\n  \"block.refinedstorage.storage_monitor\": \"Monitor de armazenamento\",\n  \"block.refinedstorage.portable_grid\": \"Grade portátil\",\n  \"block.refinedstorage.creative_portable_grid\": \"Grade portátil (modo criativo)\",\n  \"block.refinedstorage.portable_grid.tooltip\": \"Esgueirar-se para colocar no mundo.\",\n\n  \"item.refinedstorage.1k_storage_disk\": \"Disco de armazenamento 1k\",\n  \"item.refinedstorage.4k_storage_disk\": \"Disco de armazenamento 4k\",\n  \"item.refinedstorage.16k_storage_disk\": \"Disco de armazenamento 16k\",\n  \"item.refinedstorage.64k_storage_disk\": \"Disco de armazenamento 64k\",\n  \"item.refinedstorage.creative_storage_disk\": \"Disco de armazenamento (modo criativo)\",\n  \"item.refinedstorage.64k_fluid_storage_disk\": \"Disco de armazenamento de fluidos 64k\",\n  \"item.refinedstorage.256k_fluid_storage_disk\": \"Disco de armazenamento de fluidos 256k\",\n  \"item.refinedstorage.1024k_fluid_storage_disk\": \"Disco de armazenamento de fluidos 1024k\",\n  \"item.refinedstorage.4096k_fluid_storage_disk\": \"Disco de armazenamento de fluidos 4096k\",\n  \"item.refinedstorage.creative_fluid_storage_disk\": \"Disco de armazenamento de fluidos (modo criativo)\",\n  \"item.refinedstorage.wireless_grid\": \"Grade sem fio\",\n  \"item.refinedstorage.creative_wireless_grid\": \"Grade sem fio (modo criativo)\",\n  \"item.refinedstorage.wireless_fluid_grid\": \"Grade de fluidos sem fio\",\n  \"item.refinedstorage.creative_wireless_fluid_grid\": \"Grade de fluidos sem fio (modo criativo)\",\n  \"item.refinedstorage.wireless_crafting_monitor\": \"Monitor de fabricações sem fio\",\n  \"item.refinedstorage.creative_wireless_crafting_monitor\": \"Monitor de fabricações sem fio (modo criativo)\",\n  \"item.refinedstorage.quartz_enriched_iron\": \"Ferro enriquecido com quartzo\",\n  \"item.refinedstorage.construction_core\": \"Núcleo de construção\",\n  \"item.refinedstorage.destruction_core\": \"Núcleo de destruição\",\n  \"item.refinedstorage.silicon\": \"Silício\",\n  \"item.refinedstorage.basic_processor\": \"Processador básico\",\n  \"item.refinedstorage.improved_processor\": \"Processador melhorado\",\n  \"item.refinedstorage.advanced_processor\": \"Processador avançado\",\n  \"item.refinedstorage.1k_storage_part\": \"Parte de armazenamento 1k\",\n  \"item.refinedstorage.4k_storage_part\": \"Parte de armazenamento 4k\",\n  \"item.refinedstorage.16k_storage_part\": \"Parte de armazenamento 16k\",\n  \"item.refinedstorage.64k_storage_part\": \"Parte de armazenamento 64k\",\n  \"item.refinedstorage.64k_fluid_storage_part\": \"Parte de armazenamento de fluidos 64k\",\n  \"item.refinedstorage.256k_fluid_storage_part\": \"Parte de armazenamento de fluidos 256k\",\n  \"item.refinedstorage.1024k_fluid_storage_part\": \"Parte de armazenamento de fluidos 1024k\",\n  \"item.refinedstorage.4096k_fluid_storage_part\": \"Parte de armazenamento de fluidos 4096k\",\n  \"item.refinedstorage.pattern\": \"Padrão\",\n  \"item.refinedstorage.upgrade\": \"Aprimoramento\",\n  \"item.refinedstorage.range_upgrade\": \"Aprimoramento de alcance\",\n  \"item.refinedstorage.speed_upgrade\": \"Aprimoramento de velocidade\",\n  \"item.refinedstorage.crafting_upgrade\": \"Aprimoramento de fabricação\",\n  \"item.refinedstorage.stack_upgrade\": \"Aprimoramento de empilhamento\",\n  \"item.refinedstorage.silk_touch_upgrade\": \"Aprimoramento de toque suave\",\n  \"item.refinedstorage.fortune_1_upgrade\": \"Aprimoramento de fortuna\",\n  \"item.refinedstorage.fortune_2_upgrade\": \"Aprimoramento de fortuna\",\n  \"item.refinedstorage.fortune_3_upgrade\": \"Aprimoramento de fortuna\",\n  \"item.refinedstorage.storage_housing\": \"Alojamento de armazenação\",\n  \"item.refinedstorage.filter\": \"Filtro\",\n  \"item.refinedstorage.wrench\": \"Chave inglesa\",\n  \"item.refinedstorage.network_card\": \"Cartão de rede\",\n  \"item.refinedstorage.security_card\": \"Cartão de segurança\",\n  \"item.refinedstorage.security_card.owner\": \"Ligado a: %s\",\n\n  \"advancements.refinedstorage.controlling.description\": \"Fabrique um controlador.\",\n  \"advancements.refinedstorage.connecting\": \"Conectando!\",\n  \"advancements.refinedstorage.connecting.description\": \"Você pode colocar todos os dispositivos próximos uns dos outros para conectá-los, ou pode usar os cabos.\",\n  \"advancements.refinedstorage.conditional_connecting\": \"Conexão condicional!\",\n  \"advancements.refinedstorage.conditional_connecting.description\": \"Fabrique um retransmissor, você pode passar o sinal de rede usando sinal de redstone.\",\n  \"advancements.refinedstorage.drives\": \"Drives!\",\n  \"advancements.refinedstorage.drives.description\": \"Fabrique uma unidade de disco para poder armazenar seus discos.\",\n  \"advancements.refinedstorage.manipulating_disks\": \"Manipulando discos!\",\n  \"advancements.refinedstorage.manipulating_disks.description\": \"Use um manipulador de disco para modificar facilmente conteúdos de discos.\",\n  \"advancements.refinedstorage.storing_items\": \"Armazenando itens!\",\n  \"advancements.refinedstorage.storing_items.description\": \"Fabrique um disco de armazenamento e coloque em sua unidade de disco.\",\n  \"advancements.refinedstorage.viewing_items\": \"Visualizando itens!\",\n  \"advancements.refinedstorage.viewing_items.description\": \"Fabrique uma grade para interagir com seu armazenamento de itens.\",\n  \"advancements.refinedstorage.portable_storage\": \"Armazenamento portátil!\",\n  \"advancements.refinedstorage.upgrading_your_grid\": \"Aprimorando sua grade!\",\n  \"advancements.refinedstorage.upgrading_your_grid.description\": \"Aprimore sua grade para uma grade de fabricações para obter habilidades de fabricar na sua grade.\",\n  \"advancements.refinedstorage.storing_fluids\": \"Armazenando fluidos!\",\n  \"advancements.refinedstorage.storing_fluids.description\": \"Fabrique um disco de armazenamento de fluidos e coloque em sua unidade de disco.\",\n  \"advancements.refinedstorage.viewing_fluids\": \"Visualizando fluidos!\",\n  \"advancements.refinedstorage.viewing_fluids.description\": \"Fabrique uma grade de fluidos para interagir com o seu armazenamento de fluidos.\",\n  \"advancements.refinedstorage.better_than_a_barrel\": \"Melhor do que um barril!\",\n  \"advancements.refinedstorage.better_than_a_barrel.description\": \"Fabrique um monitor de armazenamento para visualizar, inserir ou extrair itens de uma rede.\",\n  \"advancements.refinedstorage.autocrafting\": \"Auto-fabricação!\",\n  \"advancements.refinedstorage.autocrafting.description\": \"Fabrique um fabricador.\",\n  \"advancements.refinedstorage.pattern_creation\": \"Criação de padrões!\",\n  \"advancements.refinedstorage.pattern_creation.description\": \"Crie padrões com uma grade de padrões e um padrão.\",\n  \"advancements.refinedstorage.monitoring\": \"Monitoramento!\",\n  \"advancements.refinedstorage.monitoring.description\": \"Verifique os status das suas tarefas de fabricação com um monitor de fabricações.\",\n  \"advancements.refinedstorage.importing\": \"Importação!\",\n  \"advancements.refinedstorage.importing.description\": \"Obtenha itens ou fluidos da rede de armazenamento com um importador.\",\n  \"advancements.refinedstorage.destruction\": \"Destruição!\",\n  \"advancements.refinedstorage.destruction.description\": \"Obtenha blocos ou fluidos da rede de armazenamento com um destruidor.\",\n  \"advancements.refinedstorage.exporting\": \"Exportação!\",\n  \"advancements.refinedstorage.exporting.description\": \"Obtenha itens ou fluidos fora da rede de armazenamento com um exportador.\",\n  \"advancements.refinedstorage.construction\": \"Construção!\",\n  \"advancements.refinedstorage.construction.description\": \"Obtenha blocos ou fluidos fora da rede de armazenamento com um construtor.\",\n  \"advancements.refinedstorage.security\": \"Segurança!\",\n  \"advancements.refinedstorage.security.description\": \"Proteja sua rede com um gerente de segurança e um cartão de segurança.\",\n  \"advancements.refinedstorage.wireless\": \"Wireless!\",\n  \"advancements.refinedstorage.wireless.description\": \"Transmita um sinal de rede com um transmissor wireless.\",\n  \"advancements.refinedstorage.wireless_items\": \"Itens wireless!\",\n  \"advancements.refinedstorage.wireless_items.description\": \"Interaja com o seu armazenamento de itens wireless com uma grade wireless.\",\n  \"advancements.refinedstorage.wireless_fluids\": \"Fluidos wireless!\",\n  \"advancements.refinedstorage.wireless_fluids.description\": \"Interaja com o seu armazenamento de fluidos wireless com uma grade de fluidos wireless.\",\n  \"advancements.refinedstorage.wireless_monitoring\": \"Monitoramento wireless!\",\n  \"advancements.refinedstorage.wireless_monitoring.description\": \"Verifique o status de suas tarefas de fabricação wireless com um monitor de fabricações wireless.\",\n  \"advancements.refinedstorage.no_cables_required\": \"Não são necessários cabos!\",\n  \"advancements.refinedstorage.no_cables_required.description\": \"Adicione componentes adicionais à sua rede sem usar cabos usando um transmissor de rede, receptor de rede e cartão de rede.\",\n  \"advancements.refinedstorage.upgrading\": \"Aprimorando!\",\n  \"advancements.refinedstorage.upgrading.description\": \"Fabrique um aprimoramento.\",\n  \"advancements.refinedstorage.crafting_on_demand\": \"Fabrique sob demanda!\",\n  \"advancements.refinedstorage.crafting_on_demand.description\": \"Use um aprimoramento de fabricação em uma interface, exportador ou construtor para fabricar itens e blocos sob demanda.\",\n  \"advancements.refinedstorage.detecting\": \"Detecção!\",\n  \"advancements.refinedstorage.detecting.description\": \"Detectar itens ou fluidos da rede com o detector.\",\n  \"advancements.refinedstorage.interface_to_the_world\": \"Interface para o mundo!\",\n  \"advancements.refinedstorage.storing_externally\": \"Armazenando externamente!\",\n  \"advancements.refinedstorage.storing_externally.description\": \"Use um armazenamento externo para fornecer à rede o armazenamento de um bloco externo como um baú.\"\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/lang/ru_ru.json",
    "content": "{\n  \"itemGroup.refinedstorage\": \"Refined Storage\",\n  \"itemGroup.refinedstorage.covers\": \"Refined Storage: Фасады\",\n\n  \"key.refinedstorage.focusSearchBar\": \"Фокусировка на панели поиска\",\n  \"key.refinedstorage.clearGridCraftingMatrix\": \"Очистить сетку создания\",\n  \"key.refinedstorage.openWirelessGrid\": \"Открыть беспроводной терминал\",\n  \"key.refinedstorage.openWirelessFluidGrid\": \"Открыть жидкостный беспроводной терминал\",\n  \"key.refinedstorage.openPortableGrid\": \"Открыть переносной терминал\",\n  \"key.refinedstorage.openWirelessCraftingMonitor\": \"Открыть беспроводной монитор создания\",\n\n  \"gui.refinedstorage.controller\": \"Контроллер\",\n  \"gui.refinedstorage.creative_controller\": \"Творческий контроллер\",\n  \"gui.refinedstorage.grid\": \"Терминал\",\n  \"gui.refinedstorage.grid.craft\": \"+\",\n  \"gui.refinedstorage.crafting_grid\": \"Терминал\",\n  \"gui.refinedstorage.pattern_grid\": \"Терминал\",\n  \"gui.refinedstorage.grid.pattern_create\": \"Создать шаблон\",\n  \"gui.refinedstorage.fluid_grid\": \"Терминал\",\n  \"gui.refinedstorage.portable_grid\": \"Переносной терминал\",\n  \"gui.refinedstorage.item_amount\": \"Количество предмета\",\n  \"gui.refinedstorage.fluid_amount\": \"Количество жидкости в mB\",\n  \"gui.refinedstorage.disk_drive\": \"Дисковый привод\",\n  \"gui.refinedstorage.disk_drive.disks\": \"Диски\",\n  \"gui.refinedstorage.disk_manipulator\": \"Дисковый манипулятор\",\n  \"gui.refinedstorage.disk_manipulator.in\": \"В\",\n  \"gui.refinedstorage.disk_manipulator.out\": \"Из\",\n  \"gui.refinedstorage.external_storage\": \"Шина внешнего хранения\",\n  \"gui.refinedstorage.importer\": \"Шина импорта\",\n  \"gui.refinedstorage.exporter\": \"Шина экспорта\",\n  \"gui.refinedstorage.detector\": \"Детектор\",\n  \"gui.refinedstorage.destructor\": \"Шина разрушения\",\n  \"gui.refinedstorage.constructor\": \"Шина формирования\",\n  \"gui.refinedstorage.relay\": \"Реле\",\n  \"gui.refinedstorage.interface.import\": \"Интерфейс импорта\",\n  \"gui.refinedstorage.interface.export\": \"Интерфейс экспорта\",\n  \"gui.refinedstorage.crafting_monitor\": \"Монитор создания\",\n  \"gui.refinedstorage.wireless_crafting_monitor\": \"Беспроводной монитор создания\",\n  \"gui.refinedstorage.crafting_monitor.tooltip.requested\": \"Запросили %d\",\n  \"gui.refinedstorage.crafting_monitor.stored\": \"В наличии: %d\",\n  \"gui.refinedstorage.crafting_monitor.missing\": \"Отсутствует: %d\",\n  \"gui.refinedstorage.crafting_monitor.processing\": \"Обработка: %d\",\n  \"gui.refinedstorage.crafting_monitor.scheduled\": \"Запланировано: %d\",\n  \"gui.refinedstorage.crafting_monitor.crafting\": \"Создание: %d\",\n  \"gui.refinedstorage.crafting_monitor.machine_does_not_accept_item\": \"Механизм не принимает предмет\",\n  \"gui.refinedstorage.crafting_monitor.machine_does_not_accept_fluid\": \"Механизм не принимает жидкость\",\n  \"gui.refinedstorage.crafting_monitor.machine_none\": \"Механизм не найден\",\n  \"gui.refinedstorage.crafting_monitor.crafter_is_locked\": \"Сборщик заблокирован\",\n  \"gui.refinedstorage.wireless_transmitter\": \"Беспроводной передатчик\",\n  \"gui.refinedstorage.wireless_transmitter.distance\": \"%d блок(ов)\",\n  \"gui.refinedstorage.crafter\": \"Сборщик\",\n  \"gui.refinedstorage.filter\": \"Фильтр\",\n  \"gui.refinedstorage.filter.compare_nbt\": \"Учитывать NBT\",\n  \"gui.refinedstorage.filter.mod_filter\": \"Фильтровать по моду\",\n  \"gui.refinedstorage.network_transmitter\": \"Сетевой передатчик\",\n  \"gui.refinedstorage.network_transmitter.distance\": \"%d блок(ов)\",\n  \"gui.refinedstorage.network_transmitter.missing_card\": \"Не найдена сетевая карта\",\n  \"gui.refinedstorage.fluid_interface\": \"Жидкостный интерфейс\",\n  \"gui.refinedstorage.fluid_interface.in\": \"В\",\n  \"gui.refinedstorage.fluid_interface.out\": \"Из\",\n  \"gui.refinedstorage.crafting_preview\": \"Предварительный просмотр\",\n  \"gui.refinedstorage.crafting_preview.to_craft\": \"Создать: %d\",\n  \"gui.refinedstorage.crafting_preview.available\": \"Доступно: %d\",\n  \"gui.refinedstorage.crafting_preview.missing\": \"Отсутствует: %d\",\n  \"gui.refinedstorage.crafting_preview.error\": \"Не удаётся создать\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.0\": \"Не хватает ингридиентов, чтобы завершить\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.1\": \"создание.\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.2\": \"Вам нужно удалить шаблон или убедиться, что\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.3\": \"шаблон не используется во время автосоздания.\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.4\": \"Шаблон повреждён:\",\n  \"gui.refinedstorage.crafting_preview.error.too_complex.0\": \"Расчёт задачи по автосозданию был слишком сложным\",\n  \"gui.refinedstorage.crafting_preview.error.too_complex.1\": \"и был остановлен, чтобы избежать нагрузки на сервер.\",\n  \"gui.refinedstorage.security_manager\": \"Менеджер безопасности\",\n  \"gui.refinedstorage.security_manager.configure\": \"Настроить\",\n  \"gui.refinedstorage.security_manager.permission.0\": \"Помещать\",\n  \"gui.refinedstorage.security_manager.permission.0.tooltip\": \"Помещение предметов в сеть\",\n  \"gui.refinedstorage.security_manager.permission.1\": \"Извлекать\",\n  \"gui.refinedstorage.security_manager.permission.1.tooltip\": \"Извлечение предметов из сети\",\n  \"gui.refinedstorage.security_manager.permission.2\": \"Автосоздание\",\n  \"gui.refinedstorage.security_manager.permission.2.tooltip\": \"Запуск, отмена и просмотр задач автосоздания\",\n  \"gui.refinedstorage.security_manager.permission.3\": \"Изменять\",\n  \"gui.refinedstorage.security_manager.permission.3.tooltip\": \"Открытие блоков с интерфейсом\",\n  \"gui.refinedstorage.security_manager.permission.4\": \"Строить\",\n  \"gui.refinedstorage.security_manager.permission.4.tooltip\": \"Добавление или удаление устройств сети\",\n  \"gui.refinedstorage.security_manager.permission.5\": \"Безопасность\",\n  \"gui.refinedstorage.security_manager.permission.5.tooltip\": \"Изменение параметров безопасности\",\n  \"gui.refinedstorage.storage_monitor\": \"Монитор хранения\",\n  \"gui.refinedstorage.crafter_manager\": \"Менеджер создания\",\n  \"gui.refinedstorage.alternatives\": \"Альтернативы\",\n  \"gui.refinedstorage.alternatives.apply\": \"Применить\",\n\n  \"misc.refinedstorage.energy_stored\": \"%d / %d FE\",\n  \"misc.refinedstorage.energy_usage\": \"Используется: %d FE/тик\",\n  \"misc.refinedstorage.energy_usage_minimal\": \"%d FE/тик\",\n\n  \"misc.refinedstorage.storage.stored\": \"Запасено: %s\",\n  \"misc.refinedstorage.storage.stored_capacity\": \"Запасено: %s / %s\",\n  \"misc.refinedstorage.storage.stored_minimal\": \"%s\",\n  \"misc.refinedstorage.storage.stored_capacity_minimal\": \"%s / %s\",\n  \"misc.refinedstorage.storage.full\": \"Заполнено на %d%%\",\n\n  \"misc.refinedstorage.network_item.tooltip\": \"Связан с %d, %d, %d.\",\n  \"misc.refinedstorage.network_item.out_of_range\": \"В зоне действия нет беспроводного передатчика.\",\n  \"misc.refinedstorage.network_item.not_found\": \"Контроллер не найден.\",\n  \"misc.refinedstorage.network_item.shortcut_not_found\": \"В вашем инвентаре нет ни одного %s.\",\n  \"misc.refinedstorage.network_item.shortcut_duplicate\": \"В вашем инвентаре есть более одного %s.\",\n  \"misc.refinedstorage.network_item.out_of_energy\": \"У «%s» недостаточно энергии.\",\n\n  \"misc.refinedstorage.network_card.tooltip\": \"Связана с %d, %d, %d в %s.\",\n\n  \"misc.refinedstorage.pattern.inputs\": \"На входе:\",\n  \"misc.refinedstorage.pattern.outputs\": \"На выходе:\",\n  \"misc.refinedstorage.pattern.invalid\": \"Недопустимый шаблон\",\n  \"misc.refinedstorage.pattern.exact\": \"Использует точный режим\",\n  \"misc.refinedstorage.pattern.allowed_item_tag\": \"Использует предметы из %s для %s\",\n  \"misc.refinedstorage.pattern.allowed_fluid_tag\": \"Использует жидкости из %s для %s\",\n\n  \"misc.refinedstorage.pattern.error.processing_no_outputs\": \"Шаблон обработки не имеет «выходов»\",\n  \"misc.refinedstorage.pattern.error.no_output\": \"Рецепт не имеет «выхода»\",\n  \"misc.refinedstorage.pattern.error.recipe_does_not_exist\": \"Рецепт не существует\",\n  \"misc.refinedstorage.pattern.error.tag_no_longer_applicable\": \"Тег %s больше не применим к %s\",\n\n  \"misc.refinedstorage.security.no_permission\": \"У вас нет разрешения на выполнение этого действия.\",\n\n  \"misc.refinedstorage.start\": \"Начать\",\n  \"misc.refinedstorage.clear\": \"Очистить\",\n  \"misc.refinedstorage.set\": \"Установить\",\n  \"misc.refinedstorage.cancel_all\": \"Отменить все\",\n  \"misc.refinedstorage.priority\": \"Приоритет\",\n  \"misc.refinedstorage.exact\": \"Точно\",\n  \"misc.refinedstorage.processing\": \"Обработка\",\n  \"misc.refinedstorage.total\": \"Всего: %s\",\n\n  \"misc.refinedstorage.last_modified.just_now\": \"Последнее изменение только что %s\",\n  \"misc.refinedstorage.last_modified.second\": \"Последнее изменение %d секунду назад %s\",\n  \"misc.refinedstorage.last_modified.seconds\": \"Последнее изменение %d секунд назад %s\",\n  \"misc.refinedstorage.last_modified.minute\": \"Последнее изменение %d минуту назад %s\",\n  \"misc.refinedstorage.last_modified.minutes\": \"Последнее изменение %d минут назад %s\",\n  \"misc.refinedstorage.last_modified.hour\": \"Последнее изменение %d час назад %s\",\n  \"misc.refinedstorage.last_modified.hours\": \"Последнее изменение %d часов назад %s\",\n  \"misc.refinedstorage.last_modified.day\": \"Последнее изменение %d день назад %s\",\n  \"misc.refinedstorage.last_modified.days\": \"Последнее изменение %d дней назад %s\",\n  \"misc.refinedstorage.last_modified.week\": \"Последнее изменение %d неделю назад %s\",\n  \"misc.refinedstorage.last_modified.weeks\": \"Последнее изменение %d недель назад %s\",\n  \"misc.refinedstorage.last_modified.year\": \"Последнее изменение %d год назад %s\",\n  \"misc.refinedstorage.last_modified.years\": \"Последнее изменение %d лет назад %s\",\n\n  \"sidebutton.refinedstorage.exact_mode\": \"Точный режим\",\n  \"sidebutton.refinedstorage.exact_mode.on\": \"Вкл.\",\n  \"sidebutton.refinedstorage.exact_mode.off\": \"Выкл.\",\n\n  \"sidebutton.refinedstorage.redstone_mode\": \"Режим редстоуна\",\n  \"sidebutton.refinedstorage.redstone_mode.0\": \"Игнорировать редстоун-сигнал\",\n  \"sidebutton.refinedstorage.redstone_mode.1\": \"Работать только с редстоун-сигналом\",\n  \"sidebutton.refinedstorage.redstone_mode.2\": \"Работать только без редстоун-сигнала\",\n\n  \"sidebutton.refinedstorage.crafter_mode\": \"Режим сборщика\",\n  \"sidebutton.refinedstorage.crafter_mode.0\": \"Игнорировать редстоун-сигнал\",\n  \"sidebutton.refinedstorage.crafter_mode.1\": \"При подаче редстоун-сигнала разблокирует автосоздание\",\n  \"sidebutton.refinedstorage.crafter_mode.2\": \"При подаче редстоун-сигнала блокирует автосоздание\",\n  \"sidebutton.refinedstorage.crafter_mode.3\": \"При подаче редстоун-импульса поставляет следующий набор\",\n\n  \"sidebutton.refinedstorage.grid.view_type\": \"Отображение\",\n  \"sidebutton.refinedstorage.grid.view_type.0\": \"Обычное\",\n  \"sidebutton.refinedstorage.grid.view_type.1\": \"Без шаблонов\",\n  \"sidebutton.refinedstorage.grid.view_type.2\": \"Только шаблоны\",\n  \"sidebutton.refinedstorage.grid.sorting.direction\": \"Порядок сортировки\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.0\": \"По возрастанию\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.1\": \"По убыванию\",\n  \"sidebutton.refinedstorage.grid.sorting.type\": \"Сортировка по\",\n  \"sidebutton.refinedstorage.grid.sorting.type.0\": \"Количеству\",\n  \"sidebutton.refinedstorage.grid.sorting.type.1\": \"Названию\",\n  \"sidebutton.refinedstorage.grid.sorting.type.2\": \"ID\",\n  \"sidebutton.refinedstorage.grid.sorting.type.3\": \"Inventory Tweaks\",\n  \"sidebutton.refinedstorage.grid.sorting.type.4\": \"Последнему изменению\",\n  \"sidebutton.refinedstorage.grid.search_box_mode\": \"Режим панели поиска\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.0\": \"Обычный\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.1\": \"Обычный (автовыбор)\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.2\": \"Синхронизированный с JEI\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.3\": \"Синхронизированный с JEI (автовыбор)\",\n  \"sidebutton.refinedstorage.grid.size\": \"Размер\",\n  \"sidebutton.refinedstorage.grid.size.0\": \"Вытянутый\",\n  \"sidebutton.refinedstorage.grid.size.1\": \"Маленький\",\n  \"sidebutton.refinedstorage.grid.size.2\": \"Средний\",\n  \"sidebutton.refinedstorage.grid.size.3\": \"Большой\",\n\n  \"sidebutton.refinedstorage.mode\": \"Режим\",\n  \"sidebutton.refinedstorage.mode.whitelist\": \"Белый список\",\n  \"sidebutton.refinedstorage.mode.blacklist\": \"Чёрный список\",\n\n  \"sidebutton.refinedstorage.iomode\": \"Режим ввода/вывода\",\n  \"sidebutton.refinedstorage.iomode.insert\": \"Помещать в сеть\",\n  \"sidebutton.refinedstorage.iomode.extract\": \"Извлекать из сети\",\n\n  \"sidebutton.refinedstorage.type\": \"Тип\",\n  \"sidebutton.refinedstorage.type.0\": \"Предметы\",\n  \"sidebutton.refinedstorage.type.1\": \"Жидкости\",\n\n  \"sidebutton.refinedstorage.detector.mode\": \"Режим\",\n  \"sidebutton.refinedstorage.detector.mode.0\": \"Излучать сигнал, если количество меньше\",\n  \"sidebutton.refinedstorage.detector.mode.1\": \"Излучать сигнал, если количество равно\",\n  \"sidebutton.refinedstorage.detector.mode.2\": \"Излучать сигнал, если количество больше\",\n\n  \"sidebutton.refinedstorage.constructor.drop\": \"Выбрасывать блоки вместо размещения\",\n\n  \"sidebutton.refinedstorage.destructor.pickup\": \"Подбирать предметы, а не ломать\",\n\n  \"sidebutton.refinedstorage.access_type\": \"Тип доступа\",\n  \"sidebutton.refinedstorage.access_type.0\": \"Помещать и извлекать\",\n  \"sidebutton.refinedstorage.access_type.1\": \"Только помещать\",\n  \"sidebutton.refinedstorage.access_type.2\": \"Только извлекать\",\n\n  \"block.refinedstorage.controller\": \"Контроллер\",\n  \"block.refinedstorage.creative_controller\": \"Творческий контроллер\",\n  \"block.refinedstorage.cable\": \"Кабель\",\n  \"block.refinedstorage.grid\": \"Терминал\",\n  \"block.refinedstorage.crafting_grid\": \"Терминал создания\",\n  \"block.refinedstorage.pattern_grid\": \"Терминал с кодировщиком шаблонов\",\n  \"block.refinedstorage.fluid_grid\": \"Жидкостный терминал\",\n  \"block.refinedstorage.disk_drive\": \"Дисковый привод\",\n  \"block.refinedstorage.disk_manipulator\": \"Дисковый манипулятор\",\n  \"block.refinedstorage.external_storage\": \"Шина внешнего хранения\",\n  \"block.refinedstorage.importer\": \"Шина импорта\",\n  \"block.refinedstorage.exporter\": \"Шина экспорта\",\n  \"block.refinedstorage.detector\": \"Детектор\",\n  \"block.refinedstorage.machine_casing\": \"Корпус механизма\",\n  \"block.refinedstorage.destructor\": \"Шина разрушения\",\n  \"block.refinedstorage.constructor\": \"Шина формирования\",\n  \"block.refinedstorage.1k_storage_block\": \"Блок хранения 1k\",\n  \"block.refinedstorage.4k_storage_block\": \"Блок хранения 4k\",\n  \"block.refinedstorage.16k_storage_block\": \"Блок хранения 16k\",\n  \"block.refinedstorage.64k_storage_block\": \"Блок хранения 64k\",\n  \"block.refinedstorage.creative_storage_block\": \"Творческий блок хранения\",\n  \"block.refinedstorage.relay\": \"Реле\",\n  \"block.refinedstorage.interface\": \"Интерфейс\",\n  \"block.refinedstorage.crafting_monitor\": \"Монитор создания\",\n  \"block.refinedstorage.wireless_transmitter\": \"Беспроводной передатчик\",\n  \"block.refinedstorage.wireless_transmitter.tooltip\": \"Необходимо поставить на %s.\",\n  \"block.refinedstorage.crafter\": \"Сборщик\",\n  \"block.refinedstorage.network_receiver\": \"Сетевой приёмник\",\n  \"block.refinedstorage.network_transmitter\": \"Сетевой передатчик\",\n  \"block.refinedstorage.fluid_interface\": \"Жидкостный интерфейс\",\n  \"block.refinedstorage.64k_fluid_storage_block\": \"Блок хранения жидкости 64k\",\n  \"block.refinedstorage.256k_fluid_storage_block\": \"Блок хранения жидкости 256k\",\n  \"block.refinedstorage.1024k_fluid_storage_block\": \"Блок хранения жидкости 1024k\",\n  \"block.refinedstorage.4096k_fluid_storage_block\": \"Блок хранения жидкости 4096k\",\n  \"block.refinedstorage.creative_fluid_storage_block\": \"Творческий блок хранения жидкости\",\n  \"block.refinedstorage.security_manager\": \"Менеджер безопасности\",\n  \"block.refinedstorage.quartz_enriched_iron_block\": \"Блок обогащённого кварцем железа\",\n  \"block.refinedstorage.storage_monitor\": \"Монитор хранения\",\n  \"block.refinedstorage.portable_grid\": \"Переносной терминал\",\n  \"block.refinedstorage.creative_portable_grid\": \"Творческий переносной терминал\",\n  \"block.refinedstorage.portable_grid.tooltip\": \"Нужно красться, чтобы поставить в мире.\",\n  \"block.refinedstorage.crafter_manager\": \"Менеджер создания\",\n\n  \"item.refinedstorage.1k_storage_disk\": \"Диск хранения 1k\",\n  \"item.refinedstorage.4k_storage_disk\": \"Диск хранения 4k\",\n  \"item.refinedstorage.16k_storage_disk\": \"Диск хранения 16k\",\n  \"item.refinedstorage.64k_storage_disk\": \"Диск хранения 64k\",\n  \"item.refinedstorage.creative_storage_disk\": \"Творческий диск хранения\",\n  \"item.refinedstorage.64k_fluid_storage_disk\": \"Диск хранения жидкости 64k\",\n  \"item.refinedstorage.256k_fluid_storage_disk\": \"Диск хранения жидкости 256k\",\n  \"item.refinedstorage.1024k_fluid_storage_disk\": \"Диск хранения жидкости 1024k\",\n  \"item.refinedstorage.4096k_fluid_storage_disk\": \"Диск хранения жидкости 4096k\",\n  \"item.refinedstorage.creative_fluid_storage_disk\": \"Творческий диск хранения жидкости\",\n  \"item.refinedstorage.wireless_grid\": \"Беспроводной терминал\",\n  \"item.refinedstorage.creative_wireless_grid\": \"Творческий беспроводной терминал\",\n  \"item.refinedstorage.wireless_fluid_grid\": \"Беспроводной жидкостный терминал\",\n  \"item.refinedstorage.creative_wireless_fluid_grid\": \"Творческий беспроводной жидкостный терминал\",\n  \"item.refinedstorage.wireless_crafting_monitor\": \"Беспроводной монитор создания\",\n  \"item.refinedstorage.creative_wireless_crafting_monitor\": \"Творческий беспроводной монитор создания\",\n  \"item.refinedstorage.quartz_enriched_iron\": \"Обогащённое кварцем железо\",\n  \"item.refinedstorage.construction_core\": \"Ядро формирования\",\n  \"item.refinedstorage.destruction_core\": \"Ядро разрушения\",\n  \"item.refinedstorage.silicon\": \"Кремний\",\n  \"item.refinedstorage.raw_basic_processor\": \"Необработанный базовый процессор\",\n  \"item.refinedstorage.raw_improved_processor\": \"Необработанный улучшенный процессор\",\n  \"item.refinedstorage.raw_advanced_processor\": \"Необработанный продвинутый процессор\",\n  \"item.refinedstorage.basic_processor\": \"Базовый процессор\",\n  \"item.refinedstorage.improved_processor\": \"Улучшенный процессор\",\n  \"item.refinedstorage.advanced_processor\": \"Продвинутый процессор\",\n  \"item.refinedstorage.1k_storage_part\": \"Компонент хранения 1k\",\n  \"item.refinedstorage.4k_storage_part\": \"Компонент хранения 4k\",\n  \"item.refinedstorage.16k_storage_part\": \"Компонент хранения 16k\",\n  \"item.refinedstorage.64k_storage_part\": \"Компонент хранения 64k\",\n  \"item.refinedstorage.64k_fluid_storage_part\": \"Жидкостный компонент хранения 64k\",\n  \"item.refinedstorage.256k_fluid_storage_part\": \"Жидкостный компонент хранения 256k\",\n  \"item.refinedstorage.1024k_fluid_storage_part\": \"Жидкостный компонент хранения 1024k\",\n  \"item.refinedstorage.4096k_fluid_storage_part\": \"Жидкостный компонент хранения 4096k\",\n  \"item.refinedstorage.pattern\": \"Шаблон\",\n  \"item.refinedstorage.upgrade\": \"Корпус улучшения\",\n  \"item.refinedstorage.range_upgrade\": \"Улучшение «Радиус»\",\n  \"item.refinedstorage.speed_upgrade\": \"Улучшение «Скорость»\",\n  \"item.refinedstorage.crafting_upgrade\": \"Улучшение «Создание»\",\n  \"item.refinedstorage.stack_upgrade\": \"Улучшение «Стопка»\",\n  \"item.refinedstorage.silk_touch_upgrade\": \"Улучшение «Шёлковое касание»\",\n  \"item.refinedstorage.fortune_1_upgrade\": \"Улучшение «Удача»\",\n  \"item.refinedstorage.fortune_2_upgrade\": \"Улучшение «Удача»\",\n  \"item.refinedstorage.fortune_3_upgrade\": \"Улучшение «Удача»\",\n  \"item.refinedstorage.regulator_upgrade\": \"Улучшение «Регулятор»\",\n  \"item.refinedstorage.storage_housing\": \"Корпус диска\",\n  \"item.refinedstorage.filter\": \"Фильтр\",\n  \"item.refinedstorage.network_card\": \"Сетевая карта\",\n  \"item.refinedstorage.wrench\": \"Гаечный ключ\",\n  \"item.refinedstorage.security_card\": \"Карта безопасности\",\n  \"item.refinedstorage.security_card.owner\": \"Привязана к %s\",\n  \"item.refinedstorage.processor_binding\": \"Связующий процессорный компонент\",\n  \"commands.refinedstorage.disk.create.error.disk_not_found\": \"Диск %s не был найден.\",\n  \"commands.refinedstorage.disk.create.success\": \"Диск %s успешно выдан %s.\",\n  \"advancements.refinedstorage.controlling.description\": \"Создайте контроллер\",\n  \"advancements.refinedstorage.connecting\": \"Соединение\",\n  \"advancements.refinedstorage.connecting.description\": \"Вы можете разместить все устройства вплотную друг с другом или использовать кабели, чтобы соединить их\",\n  \"advancements.refinedstorage.conditional_connecting\": \"Условное соединение\",\n  \"advancements.refinedstorage.conditional_connecting.description\": \"Создайте реле, которое позволяет соединять или разъединять сетевой сигнал с помощью редстоуна\",\n  \"advancements.refinedstorage.drives\": \"Приводы\",\n  \"advancements.refinedstorage.drives.description\": \"Создайте дисковый привод, чтобы иметь возможность хранить свои диски\",\n  \"advancements.refinedstorage.manipulating_disks\": \"Управление дисками\",\n  \"advancements.refinedstorage.manipulating_disks.description\": \"Используйте дисковый манипулятор, чтобы легко изменять содержимое дисков\",\n  \"advancements.refinedstorage.storing_items\": \"Хранение предметов\",\n  \"advancements.refinedstorage.storing_items.description\": \"Создайте диск хранения и поместите его в дисковый привод\",\n  \"advancements.refinedstorage.viewing_items\": \"Просмотр предметов\",\n  \"advancements.refinedstorage.viewing_items.description\": \"Создайте терминал для доступа к вашему хранилищу предметов\",\n  \"advancements.refinedstorage.portable_storage\": \"Портативное хранение\",\n  \"advancements.refinedstorage.portable_storage.description\": \"Создайте переносной терминал для доступа к предметам и жидкостям на дисках, без подключения к сети\",\n  \"advancements.refinedstorage.upgrading_your_grid\": \"Обновите свой терминал\",\n  \"advancements.refinedstorage.upgrading_your_grid.description\": \"Улучшите ваш терминал до терминала создания, чтобы получить возможность создавать прямо в нём\",\n  \"advancements.refinedstorage.storing_fluids\": \"Хранение жидкостей\",\n  \"advancements.refinedstorage.storing_fluids.description\": \"Создайте диск хранения жидкости и поместите его в дисковый привод\",\n  \"advancements.refinedstorage.viewing_fluids\": \"Просмотр жидкостей\",\n  \"advancements.refinedstorage.viewing_fluids.description\": \"Создайте жидкостный терминал для доступа к вашему хранилищу жидкостей\",\n  \"advancements.refinedstorage.better_than_a_barrel\": \"Лучше, чем бочка\",\n  \"advancements.refinedstorage.better_than_a_barrel.description\": \"Создайте монитор хранения, чтобы просматривать предметы сети и вручную помещать или извлекать их\",\n  \"advancements.refinedstorage.autocrafting\": \"Автосоздание\",\n  \"advancements.refinedstorage.autocrafting.description\": \"Создайте сборщик\",\n  \"advancements.refinedstorage.pattern_creation\": \"Создание шаблонов\",\n  \"advancements.refinedstorage.pattern_creation.description\": \"Создайте шаблоны с помощью терминала с кодировщиком шаблонов\",\n  \"advancements.refinedstorage.monitoring\": \"Мониторинг\",\n  \"advancements.refinedstorage.monitoring.description\": \"Проверьте прогресс автосоздания с помощью монитора создания\",\n  \"advancements.refinedstorage.managing_patterns\": \"Управление шаблонами\",\n  \"advancements.refinedstorage.managing_patterns.description\": \"Создайте менеджер создания, чтобы лучше управлять своими шаблонами\",\n  \"advancements.refinedstorage.importing\": \"Импорт\",\n  \"advancements.refinedstorage.importing.description\": \"Используйте шину импорта для ввода предметов или жидкостей в сеть\",\n  \"advancements.refinedstorage.destruction\": \"Разрушение\",\n  \"advancements.refinedstorage.destruction.description\": \"Используйте шину разрушения для сбора блоков или жидкостей в сеть\",\n  \"advancements.refinedstorage.exporting\": \"Экспорт\",\n  \"advancements.refinedstorage.exporting.description\": \"Используйте шину экспорта для вывода предметов или жидкостей из сети\",\n  \"advancements.refinedstorage.construction\": \"Строительство\",\n  \"advancements.refinedstorage.construction.description\": \"Используйте шину формирования для размещения предметов или жидкостей из сети\",\n  \"advancements.refinedstorage.security\": \"Безопасность\",\n  \"advancements.refinedstorage.security.description\": \"Защитите свою сеть с помощью менеджера безопасности и карты безопасности\",\n  \"advancements.refinedstorage.wireless\": \"Беспроводной\",\n  \"advancements.refinedstorage.wireless.description\": \"Передайте сетевой сигнал с помощью беспроводного передатчика\",\n  \"advancements.refinedstorage.wireless_items\": \"Беспроводная передача предметов\",\n  \"advancements.refinedstorage.wireless_items.description\": \"Используйте беспроводной терминал для удалённого доступа к вашим предметам сети\",\n  \"advancements.refinedstorage.wireless_fluids\": \"Беспроводная передача жидкостей\",\n  \"advancements.refinedstorage.wireless_fluids.description\": \"Используйте беспроводной жидкостный терминал для удалённого доступа к вашим жидкостям сети\",\n  \"advancements.refinedstorage.wireless_monitoring\": \"Беспроводной мониторинг\",\n  \"advancements.refinedstorage.wireless_monitoring.description\": \"Проверьте прогресс автосоздания с помощью беспроводного монитора создания\",\n  \"advancements.refinedstorage.no_cables_required\": \"Кабели не требуются!\",\n  \"advancements.refinedstorage.no_cables_required.description\": \"Используйте сетевой передатчик, сетевой приёмник и сетевую карту, чтобы добавить дополнительные устройства в сеть без использования кабелей\",\n  \"advancements.refinedstorage.upgrading\": \"Модернизация!\",\n  \"advancements.refinedstorage.upgrading.description\": \"Создайте улучшения для различных устройств\",\n  \"advancements.refinedstorage.crafting_on_demand\": \"Создание по запросу\",\n  \"advancements.refinedstorage.crafting_on_demand.description\": \"Используйте улучшение «Создание» в интерфейсе, шине экспорта или шине формирования для создания предметов по запросу\",\n  \"advancements.refinedstorage.detecting\": \"Обнаружение\",\n  \"advancements.refinedstorage.detecting.description\": \"Используйте детектор, чтобы обнаружить предметы или жидкости в сети\",\n  \"advancements.refinedstorage.interface_to_the_world\": \"Интерфейс к миру\",\n  \"advancements.refinedstorage.interface_to_the_world.description\": \"Экспортируйте и импортируйте предметы одновременно с помощью интерфейса\",\n  \"advancements.refinedstorage.storing_externally\": \"Внешнее хранение\",\n  \"advancements.refinedstorage.storing_externally.description\": \"Используйте шину внешнего хранения для подключения к сети внешнего хранилища, например сундука\"\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/lang/zh_cn.json",
    "content": "{\n    \"itemGroup.refinedstorage\": \"Refined Storage\",\n    \"itemGroup.refinedstorage.covers\": \"Refined Storage 伪装板\",\n    \"key.refinedstorage.focusSearchBar\": \"跳转终端搜索条\",\n    \"key.refinedstorage.clearGridCraftingMatrix\": \"清空合成网格\",\n    \"key.refinedstorage.openWirelessGrid\": \"打开无线面板\",\n    \"key.refinedstorage.openWirelessFluidGrid\": \"打开无线流体面板\",\n    \"key.refinedstorage.openPortableGrid\": \"打开便携面板\",\n    \"key.refinedstorage.openWirelessCraftingMonitor\": \"打开无线合成监控面板\",\n\n    \"gui.refinedstorage.controller\": \"控制器\",\n    \"gui.refinedstorage.creative_controller\": \"创造控制器\",\n    \"gui.refinedstorage.grid\": \"终端\",\n    \"gui.refinedstorage.grid.craft\": \"合成\",\n    \"gui.refinedstorage.crafting_grid\": \"合成终端\",\n    \"gui.refinedstorage.pattern_grid\": \"模板终端\",\n    \"gui.refinedstorage.grid.pattern_create\": \"写入磁盘\",\n    \"gui.refinedstorage.fluid_grid\": \"流体终端\",\n    \"gui.refinedstorage.item_amount\": \"物品数量\",\n    \"gui.refinedstorage.fluid_amount\": \"流体量以mB为单位\",\n    \"gui.refinedstorage.disk_drive\": \"驱动器\",\n    \"gui.refinedstorage.disk_drive.disks\": \"磁盘\",\n    \"gui.refinedstorage.external_storage\": \"外部存储总线\",\n    \"gui.refinedstorage.importer\": \"输入总线\",\n    \"gui.refinedstorage.exporter\": \"输出总线\",\n    \"gui.refinedstorage.detector\": \"网络物品检测器\",\n    \"gui.refinedstorage.destructor\": \"破坏面板\",\n    \"gui.refinedstorage.constructor\": \"成型面板\",\n    \"gui.refinedstorage.relay\": \"继电器\",\n    \"gui.refinedstorage.interface.import\": \"输入端\",\n    \"gui.refinedstorage.interface.export\": \"输出端\",\n    \"gui.refinedstorage.crafting_monitor\": \"合成监控处理器\",\n    \"gui.refinedstorage.wireless_crafting_monitor\": \"无线合成监控处理器\",\n    \"gui.refinedstorage.crafting_monitor.tooltip.requested\": \"需要 %d\",\n    \"gui.refinedstorage.crafting_monitor.stored\": \"已存储: %d\",\n    \"gui.refinedstorage.crafting_monitor.missing\": \"缺失: %d\",\n    \"gui.refinedstorage.crafting_monitor.processing\": \"处理中: %d\",\n    \"gui.refinedstorage.crafting_monitor.scheduled\": \"已调度: %d\",\n    \"gui.refinedstorage.crafting_monitor.crafting\": \"合成中: %d\",\n    \"gui.refinedstorage.crafting_monitor.machine_does_not_accept_item\": \"机器不接受物品\",\n    \"gui.refinedstorage.crafting_monitor.machine_does_not_accept_fluid\": \"机器不接受流体\",\n    \"gui.refinedstorage.crafting_monitor.machine_none\": \"找不到机器\",\n    \"gui.refinedstorage.crafting_monitor.crafter_is_locked\": \"合成被锁定\",\n    \"gui.refinedstorage.wireless_transmitter\": \"无线访问点\",\n    \"gui.refinedstorage.wireless_transmitter.distance\": \"%d 方块\",\n    \"gui.refinedstorage.crafter\": \"装配室\",\n    \"gui.refinedstorage.filter\": \"终端过滤\",\n    \"gui.refinedstorage.filter.compare_damage\": \"耐久\",\n    \"gui.refinedstorage.filter.compare_nbt\": \"NBT\",\n    \"gui.refinedstorage.filter.mod_filter\": \"Mod过滤\",\n    \"gui.refinedstorage.network_transmitter\": \"网络变送器\",\n    \"gui.refinedstorage.network_transmitter.distance\": \"%d 个方块\",\n    \"gui.refinedstorage.network_transmitter.dimension\": \"维度 %d\",\n    \"gui.refinedstorage.network_transmitter.missing_card\": \"缺失网卡\",\n    \"gui.refinedstorage.fluid_interface\": \"流体面板\",\n    \"gui.refinedstorage.fluid_interface.in\": \"输入\",\n    \"gui.refinedstorage.fluid_interface.out\": \"输出\",\n    \"gui.refinedstorage.crafting_preview\": \"合成预览\",\n    \"gui.refinedstorage.crafting_preview.to_craft\": \"制作：%d\",\n    \"gui.refinedstorage.crafting_preview.available\": \"可用：%d\",\n    \"gui.refinedstorage.crafting_preview.missing\": \"缺失：%d\",\n    \"gui.refinedstorage.crafting_preview.error\": \"请求失败\",\n    \"gui.refinedstorage.crafting_preview.error.recursive.0\": \"其中一种制作成分最终需要\",\n    \"gui.refinedstorage.crafting_preview.error.recursive.1\": \"自己.\",\n    \"gui.refinedstorage.crafting_preview.error.recursive.2\": \"您需要删除该模式或确保\",\n    \"gui.refinedstorage.crafting_preview.error.recursive.3\": \"在制作过程中不使用模式.\",\n    \"gui.refinedstorage.crafting_preview.error.recursive.4\": \"违规模式:\",\n    \"gui.refinedstorage.crafting_preview.error.too_complex.0\": \"制作任务计算过于复杂，\",\n    \"gui.refinedstorage.crafting_preview.error.too_complex.1\": \"并且已停止以缓解服务器压力。\",\n    \"gui.refinedstorage.reader\": \"读取器\",\n    \"gui.refinedstorage.writer\": \"写入器\",\n    \"gui.refinedstorage.security_manager\": \"权限管理器\",\n    \"gui.refinedstorage.security_manager.configure\": \"配置\",\n    \"gui.refinedstorage.security_manager.permission.0\": \"输入\",\n    \"gui.refinedstorage.security_manager.permission.0.tooltip\": \"向网络中输入物品\",\n    \"gui.refinedstorage.security_manager.permission.1\": \"输出\",\n    \"gui.refinedstorage.security_manager.permission.1.tooltip\": \"从网络中输出物品\",\n    \"gui.refinedstorage.security_manager.permission.2\": \"自动合成\",\n    \"gui.refinedstorage.security_manager.permission.2.tooltip\": \"开始、取消、预览合成任务\",\n    \"gui.refinedstorage.security_manager.permission.3\": \"修改\",\n    \"gui.refinedstorage.security_manager.permission.3.tooltip\": \"打开方块的GUI\",\n    \"gui.refinedstorage.security_manager.permission.4\": \"操纵\",\n    \"gui.refinedstorage.security_manager.permission.4.tooltip\": \"向网络中添加、移除设备\",\n    \"gui.refinedstorage.security_manager.permission.5\": \"安全\",\n    \"gui.refinedstorage.security_manager.permission.5.tooltip\": \"改变安全选项\",\n    \"gui.refinedstorage.storage_monitor\": \"存储监控器\",\n    \"gui.refinedstorage.portable_grid\": \"便携式终端\",\n    \"gui.refinedstorage.crafter_manager\": \"合成管理器\",\n\n    \"misc.refinedstorage.energy_stored\": \"%d / %d FE\",\n    \"misc.refinedstorage.energy_usage\": \"使用: %d FE/t\",\n    \"misc.refinedstorage.energy_usage_minimal\": \"%d FE/t\",\n\n    \"misc.refinedstorage.storage.stored\": \"已存储: %s\",\n    \"misc.refinedstorage.storage.stored_capacity\": \"已存储: %s / %s\",\n    \"misc.refinedstorage.storage.stored_minimal\": \"%s\",\n    \"misc.refinedstorage.storage.stored_capacity_minimal\": \"%s / %s\",\n    \"misc.refinedstorage.storage.full\": \"%d%% 已使用\",\n\n    \"misc.refinedstorage.network_item.tooltip\": \"连接到 %d, %d, %d.\",\n    \"misc.refinedstorage.network_item.out_of_range\": \"在范围内没有可以接入的无线访问点.\",\n    \"misc.refinedstorage.network_item.not_found\": \"没找到控制器.\",\n\n    \"misc.refinedstorage.network_card.tooltip\": \"连接到 %d, %d, %d.\",\n\n    \"misc.refinedstorage.pattern.inputs\": \"输入\",\n    \"misc.refinedstorage.pattern.outputs\": \"输出\",\n    \"misc.refinedstorage.pattern.invalid\": \"无效模式\",\n    \"misc.refinedstorage.pattern.oredict\": \"使用矿物辞典\",\n\n    \"misc.refinedstorage.security.no_permission\": \"你没有权限进行此操作\",\n\n    \"misc.refinedstorage.start\": \"开始\",\n    \"misc.refinedstorage.clear\": \"清除\",\n    \"misc.refinedstorage.set\": \"设置\",\n    \"misc.refinedstorage.cancel_all\": \"取消所有\",\n    \"misc.refinedstorage.priority\": \"优先级\",\n    \"misc.refinedstorage.oredict\": \"矿物辞典\",\n    \"misc.refinedstorage.processing\": \"进行中\",\n\n    \"misc.refinedstorage.reader_writer.redstone\": \"红石强度：%d\",\n\n    \"misc.refinedstorage.total\": \"总共 %s\",\n\n    \"misc.refinedstorage.last_modified.just_now\": \"刚刚被 %s 操作\",\n    \"misc.refinedstorage.last_modified.second\": \"%d 秒前被 %s 操作\",\n    \"misc.refinedstorage.last_modified.seconds\": \"%d 秒前被 %s 操作\",\n    \"misc.refinedstorage.last_modified.minute\": \"%d 分钟前被 %s 操作\",\n    \"misc.refinedstorage.last_modified.minutes\": \"%d 分钟前被 %s 操作\",\n    \"misc.refinedstorage.last_modified.hour\": \"%d 小时前被 %s 操作\",\n    \"misc.refinedstorage.last_modified.hours\": \"%d 小时前被 %s 操作\",\n    \"misc.refinedstorage.last_modified.day\": \"%d 天前被 %s 操作\",\n    \"misc.refinedstorage.last_modified.days\": \"%d 天前被 %s 操作\",\n    \"misc.refinedstorage.last_modified.week\": \"%d 周前被 %s 操作\",\n    \"misc.refinedstorage.last_modified.weeks\": \"%d 周前被 %s 操作\",\n    \"misc.refinedstorage.last_modified.year\": \"%d 年前被 %s 操作\",\n    \"misc.refinedstorage.last_modified.years\": \"%d 年前被 %s 操作\",\n\n    \"sidebutton.refinedstorage.compare.1\": \"耐久匹配\",\n    \"sidebutton.refinedstorage.compare.2\": \"NBT匹配\",\n\n    \"sidebutton.refinedstorage.redstone_mode\": \"红石模式\",\n    \"sidebutton.refinedstorage.redstone_mode.0\": \"忽略红石信号\",\n    \"sidebutton.refinedstorage.redstone_mode.1\": \"有红石信号时工作\",\n    \"sidebutton.refinedstorage.redstone_mode.2\": \"无红石信号时工作\",\n\n    \"sidebutton.refinedstorage.crafter_mode\": \"合成模式\",\n    \"sidebutton.refinedstorage.crafter_mode.0\": \"无视红石信号\",\n    \"sidebutton.refinedstorage.crafter_mode.1\": \"红石信号解锁自动合成\",\n    \"sidebutton.refinedstorage.crafter_mode.2\": \"红石信号锁定自动合成\",\n    \"sidebutton.refinedstorage.crafter_mode.3\": \"红石脉冲插入下一组\",\n\n    \"sidebutton.refinedstorage.grid.view_type\": \"显示\",\n    \"sidebutton.refinedstorage.grid.view_type.0\": \"默认\",\n    \"sidebutton.refinedstorage.grid.view_type.1\": \"隐藏合成\",\n    \"sidebutton.refinedstorage.grid.view_type.2\": \"只有合成\",\n    \"sidebutton.refinedstorage.grid.sorting.direction\": \"排序方式\",\n    \"sidebutton.refinedstorage.grid.sorting.direction.0\": \"上升\",\n    \"sidebutton.refinedstorage.grid.sorting.direction.1\": \"下降\",\n    \"sidebutton.refinedstorage.grid.sorting.type\": \"排序按\",\n    \"sidebutton.refinedstorage.grid.sorting.type.0\": \"数量\",\n    \"sidebutton.refinedstorage.grid.sorting.type.1\": \"名字\",\n    \"sidebutton.refinedstorage.grid.sorting.type.2\": \"ID\",\n    \"sidebutton.refinedstorage.grid.sorting.type.3\": \"InventoryTweaks\",\n    \"sidebutton.refinedstorage.grid.sorting.type.4\": \"最后修改时间\",\n    \"sidebutton.refinedstorage.grid.search_box_mode\": \"搜索框模式\",\n    \"sidebutton.refinedstorage.grid.search_box_mode.0\": \"标准搜索\",\n    \"sidebutton.refinedstorage.grid.search_box_mode.1\": \"自动搜索\",\n    \"sidebutton.refinedstorage.grid.search_box_mode.2\": \"JEI 标准同步\",\n    \"sidebutton.refinedstorage.grid.search_box_mode.3\": \"JEI 自动同步\",\n    \"sidebutton.refinedstorage.grid.size\": \"大小\",\n    \"sidebutton.refinedstorage.grid.size.0\": \"自适应\",\n    \"sidebutton.refinedstorage.grid.size.1\": \"小\",\n    \"sidebutton.refinedstorage.grid.size.2\": \"中\",\n    \"sidebutton.refinedstorage.grid.size.3\": \"大\",\n\n    \"sidebutton.refinedstorage.mode\": \"模式\",\n    \"sidebutton.refinedstorage.mode.whitelist\": \"白名单\",\n    \"sidebutton.refinedstorage.mode.blacklist\": \"黑名单\",\n\n    \"sidebutton.refinedstorage.iomode\": \"IO模式\",\n    \"sidebutton.refinedstorage.iomode.insert\": \"输入到网络\",\n    \"sidebutton.refinedstorage.iomode.extract\": \"从网络输出\",\n\n    \"sidebutton.refinedstorage.type\": \"类型\",\n    \"sidebutton.refinedstorage.type.0\": \"物品\",\n    \"sidebutton.refinedstorage.type.1\": \"流体\",\n\n    \"sidebutton.refinedstorage.detector.mode\": \"模式\",\n    \"sidebutton.refinedstorage.detector.mode.0\": \"物品数量小于输入数量时输出信号\",\n    \"sidebutton.refinedstorage.detector.mode.1\": \"物品数量等于输入数量时输出信号\",\n    \"sidebutton.refinedstorage.detector.mode.2\": \"物品数量大于于输入数量时输出信号\",\n\n    \"sidebutton.refinedstorage.constructor.drop\": \"将物品以掉落物形式抛出\",\n\n    \"sidebutton.refinedstorage.destructor.pickup\": \"拾取物品模式\",\n\n    \"sidebutton.refinedstorage.access_type\": \"访问类型\",\n    \"sidebutton.refinedstorage.access_type.0\": \"输入输出\",\n    \"sidebutton.refinedstorage.access_type.1\": \"仅输入\",\n    \"sidebutton.refinedstorage.access_type.2\": \"仅输出\",\n\n    \"block.refinedstorage.controller\": \"控制器\",\n    \"block.refinedstorage.creative_controller\": \"创造控制器\",\n    \"block.refinedstorage.cable\": \"线缆\",\n    \"block.refinedstorage.grid\": \"终端\",\n    \"block.refinedstorage.crafting_grid\": \"合成终端\",\n    \"block.refinedstorage.pattern_grid\": \"样板终端\",\n    \"block.refinedstorage.fluid_grid\": \"流体终端\",\n    \"block.refinedstorage.disk_drive\": \"磁盘驱动器\",\n    \"block.refinedstorage.disk_manipulator\": \"磁盘操纵器\",\n    \"block.refinedstorage.external_storage\": \"外部存储总线\",\n    \"block.refinedstorage.importer\": \"输入总线\",\n    \"block.refinedstorage.exporter\": \"输出总线\",\n    \"block.refinedstorage.detector\": \"标准发信器\",\n    \"block.refinedstorage.machine_casing\": \"机器外壳\",\n    \"block.refinedstorage.destructor\": \"破坏面板\",\n    \"block.refinedstorage.constructor\": \"成型面板\",\n    \"block.refinedstorage.1k_storage_block\": \"1k 存储方块\",\n    \"block.refinedstorage.4k_storage_block\": \"4k 存储方块\",\n    \"block.refinedstorage.16k_storage_block\": \"16k 存储方块\",\n    \"block.refinedstorage.64k_storage_block\": \"64k 存储方块\",\n    \"block.refinedstorage.creative_storage_block\": \"创造存储方块\",\n    \"block.refinedstorage.relay\": \"继电器\",\n    \"block.refinedstorage.interface\": \"物品传输接口\",\n    \"block.refinedstorage.crafting_monitor\": \"合成监控处理器\",\n    \"block.refinedstorage.wireless_transmitter\": \"无线访问点\",\n    \"block.refinedstorage.wireless_transmitter.tooltip\": \"需要放置在%s上。\",\n    \"block.refinedstorage.crafter\": \"装配室\",\n    \"block.refinedstorage.network_receiver\": \"网络接收器\",\n    \"block.refinedstorage.network_transmitter\": \"网络变送器\",\n    \"block.refinedstorage.fluid_interface\": \"流体面板\",\n    \"block.refinedstorage.64k_fluid_storage_block\": \"64k 流体存储方块\",\n    \"block.refinedstorage.256k_fluid_storage_block\": \"256k 流体存储方块\",\n    \"block.refinedstorage.1024k_fluid_storage_block\": \"1024k 流体存储方块\",\n    \"block.refinedstorage.4096k_fluid_storage_block\": \"4096k 流体存储方块\",\n    \"block.refinedstorage.creative_fluid_storage_block\": \"创造流体存储方块\",\n    \"block.refinedstorage.reader\": \"读取器\",\n    \"block.refinedstorage.writer\": \"写入器\",\n    \"block.refinedstorage.security_manager\": \"权限管理器\",\n    \"block.refinedstorage.quartz_enriched_iron_block\": \"富石英块\",\n    \"block.refinedstorage.storage_monitor\": \"存储监控器\",\n    \"block.refinedstorage.portable_grid\": \"便携式终端\",\n    \"block.refinedstorage.creative_portable_grid\": \"创造便携式终端\",\n    \"block.refinedstorage.portable_grid.tooltip\": \"Shift进行放置\",\n    \"block.refinedstorage.crafter_manager\": \"合成管理器\",\n    \"item.refinedstorage.raw_basic_processor\": \"未处理基础处理器\",\n    \"item.refinedstorage.raw_improved_processor\": \"未处理进阶处理器\",\n    \"item.refinedstorage.raw_advanced_processor\": \"未处理高级处理器\",\n    \"item.refinedstorage.1k_storage_disk\": \"1k 存储磁盘\",\n    \"item.refinedstorage.4k_storage_disk\": \"4k 存储磁盘\",\n    \"item.refinedstorage.16k_storage_disk\": \"16k 存储磁盘\",\n    \"item.refinedstorage.64k_storage_disk\": \"64k 存储磁盘\",\n    \"item.refinedstorage.creative_storage_disk\": \"创造存储磁盘\",\n    \"item.refinedstorage.storage_disk.5\": \"调试用存储磁盘\",\n    \"item.refinedstorage.64k_fluid_storage_disk\": \"64k 流体存储磁盘\",\n    \"item.refinedstorage.256k_fluid_storage_disk\": \"256k 流体存储磁盘\",\n    \"item.refinedstorage.1024k_fluid_storage_disk\": \"1024k 流体存储磁盘\",\n    \"item.refinedstorage.4096k_fluid_storage_disk\": \"4096k 流体存储磁盘\",\n    \"item.refinedstorage.creative_fluid_storage_disk\": \"创造流体存储磁盘\",\n    \"item.refinedstorage.fluid_storage_disk.5\": \"调试用流体存储磁盘\",\n    \"item.refinedstorage.wireless_grid\": \"无线终端\",\n    \"item.refinedstorage.creative_wireless_grid\": \"创造无线终端\",\n    \"item.refinedstorage.wireless_fluid_grid\": \"无线流体终端\",\n    \"item.refinedstorage.creative_wireless_fluid_grid\": \"创造无线流体终端\",\n    \"item.refinedstorage.wireless_crafting_monitor\": \"无线合成监控器\",\n    \"item.refinedstorage.creative_wireless_crafting_monitor\": \"创造无线合成监控器\",\n    \"item.refinedstorage.quartz_enriched_iron\": \"富石英铁\",\n    \"item.refinedstorage.construction_core\": \"成型核心\",\n    \"item.refinedstorage.destruction_core\": \"破坏核心\",\n    \"item.refinedstorage.silicon\": \"硅\",\n    \"item.refinedstorage.basic_processor\": \"基础处理器\",\n    \"item.refinedstorage.improved_processor\": \"进阶处理器\",\n    \"item.refinedstorage.advanced_processor\": \"高级处理器\",\n    \"item.refinedstorage.1k_storage_part\": \"1k 存储元件\",\n    \"item.refinedstorage.4k_storage_part\": \"4k 存储元件\",\n    \"item.refinedstorage.16k_storage_part\": \"16k 存储元件\",\n    \"item.refinedstorage.64k_storage_part\": \"64k 存储元件\",\n    \"item.refinedstorage.64k_fluid_storage_part\": \"64k 流体存储原件\",\n    \"item.refinedstorage.256k_fluid_storage_part\": \"256k 流体存储原件\",\n    \"item.refinedstorage.1024k_fluid_storage_part\": \"1024k 流体存储原件\",\n    \"item.refinedstorage.4096k_fluid_storage_part\": \"4096k 流体存储原件\",\n    \"item.refinedstorage.pattern\": \"模板\",\n    \"item.refinedstorage.upgrade\": \"空白升级\",\n    \"item.refinedstorage.range_upgrade\": \"范围升级\",\n    \"item.refinedstorage.speed_upgrade\": \"速度升级\",\n    \"item.refinedstorage.crafting_upgrade\": \"合成升级\",\n    \"item.refinedstorage.stack_upgrade\": \"堆叠升级\",\n    \"item.refinedstorage.silk_touch_upgrade\": \"精准采集升级\",\n    \"item.refinedstorage.fortune_1_upgrade\": \"时运升级\",\n    \"item.refinedstorage.fortune_2_upgrade\": \"时运升级\",\n    \"item.refinedstorage.fortune_3_upgrade\": \"时运升级\",\n    \"item.refinedstorage.storage_housing\": \"磁盘外壳\",\n    \"item.refinedstorage.filter\": \"过滤升级\",\n    \"item.refinedstorage.network_card\": \"网卡\",\n    \"item.refinedstorage.wrench\": \"扳手\",\n    \"item.refinedstorage.security_card\": \"权限卡\",\n    \"item.refinedstorage.security_card.owner\": \"绑定至：%s\",\n    \"item.refinedstorage.cutting_tool\": \"切割工具\",\n    \"item.refinedstorage.cover\": \"伪装板\",\n    \"item.refinedstorage.hollow_cover\": \"空心伪装板\",\n    \"item.refinedstorage.processor_binding\": \"处理器粘合物\",\n    \"commands.refinedstorage.disk.create.error.disk_not_found\": \"磁盘 %s 未找到.\",\n    \"commands.refinedstorage.disk.create.success\": \"成功把磁盘 %s 给了 %s.\",\n    \"advancements.refinedstorage.controlling.description\": \"合成了控制器\",\n    \"advancements.refinedstorage.connecting\": \"连接\",\n    \"advancements.refinedstorage.connecting.description\": \"您可以将所有设备放在一起或者使用【线缆】以将它们连接起来\",\n    \"advancements.refinedstorage.conditional_connecting\": \"条件连接\",\n    \"advancements.refinedstorage.conditional_connecting.description\": \"制作一个【继电器】来控制网络信号是否可以通过红石\",\n    \"advancements.refinedstorage.drives\": \"驱动器\",\n    \"advancements.refinedstorage.drives.description\": \"制作【磁盘驱动器】以便能够存储磁盘\",\n    \"advancements.refinedstorage.manipulating_disks\": \"磁盘操纵器\",\n    \"advancements.refinedstorage.manipulating_disks.description\": \"使用【磁盘操纵器】可以轻松修改磁盘内容\",\n    \"advancements.refinedstorage.storing_items\": \"存储物品\",\n    \"advancements.refinedstorage.storing_items.description\": \"制作【存储磁盘】并将其放入【磁盘驱动器】中\",\n    \"advancements.refinedstorage.viewing_items\": \"浏览物品\",\n    \"advancements.refinedstorage.viewing_items.description\": \"制作网格以与您的物品存储进行交互\",\n    \"advancements.refinedstorage.portable_storage\": \"便携式存储\",\n    \"advancements.refinedstorage.portable_storage.description\": \"制作【便携式网格】，以便在不在网络中的情况下访问磁盘中的项目和流体\",\n    \"advancements.refinedstorage.upgrading_your_grid\": \"升级你的网络\",\n    \"advancements.refinedstorage.upgrading_your_grid.description\": \"将网络升级到合成网络以获得网络中的制作能力\",\n    \"advancements.refinedstorage.storing_fluids\": \"储存液体\",\n    \"advancements.refinedstorage.storing_fluids.description\": \"制作一个【流体存储磁盘】并将其放入【磁盘驱动器】中\",\n    \"advancements.refinedstorage.viewing_fluids\": \"浏览液体\",\n    \"advancements.refinedstorage.viewing_fluids.description\": \"制作网格以与您的液体存储进行交互\",\n    \"advancements.refinedstorage.better_than_a_barrel\": \"比桶更好\",\n    \"advancements.refinedstorage.better_than_a_barrel.description\": \"制作【存储监视器】以查看，插入或提取网络项\",\n    \"advancements.refinedstorage.autocrafting\": \"自动合成\",\n    \"advancements.refinedstorage.autocrafting.description\": \"制作一个【装配室】\",\n    \"advancements.refinedstorage.pattern_creation\": \"模式创建\",\n    \"advancements.refinedstorage.pattern_creation.description\": \"使用模式网络和模式创建模式\",\n    \"advancements.refinedstorage.monitoring\": \"监控器！\",\n    \"advancements.refinedstorage.monitoring.description\": \"使用【合成监控器】检查制作任务的状态\",\n    \"advancements.refinedstorage.managing_patterns\": \"管理模式\",\n    \"advancements.refinedstorage.managing_patterns.description\": \"制作【合成管理器】以更好的方式管理您的模式\",\n    \"advancements.refinedstorage.importing\": \"输入总线\",\n    \"advancements.refinedstorage.importing.description\": \"使用【输入总线】将物品或流体输入存储网络\",\n    \"advancements.refinedstorage.destruction\": \"破坏面板\",\n    \"advancements.refinedstorage.destruction.description\": \"使用【破坏面板】将块或流体存储到存储网络中\",\n    \"advancements.refinedstorage.exporting\": \"输出总线\",\n    \"advancements.refinedstorage.exporting.description\": \"使用【输出总线】将物品或流体输出存储网络\",\n    \"advancements.refinedstorage.construction\": \"成型面板\",\n    \"advancements.refinedstorage.construction.description\": \"使用【成型面板】将物品或流体从存储网络放置出来\",\n    \"advancements.refinedstorage.security\": \"安保\",\n    \"advancements.refinedstorage.security.description\": \"使用【安全管理器】和【安全卡】保护您的网络\",\n    \"advancements.refinedstorage.wireless\": \"无线\",\n    \"advancements.refinedstorage.wireless.description\": \"使用【无线发射器】传输网络信号\",\n    \"advancements.refinedstorage.wireless_items\": \"无线传输物品\",\n    \"advancements.refinedstorage.wireless_items.description\": \"使用【无线终端】以无线方式与您的物品存储进行交互\",\n    \"advancements.refinedstorage.wireless_fluids\": \"无线传输液体\",\n    \"advancements.refinedstorage.wireless_fluids.description\": \"使用【无线液体终端】以无线方式与您的液体存储进行交互\",\n    \"advancements.refinedstorage.wireless_monitoring\": \"无线监控器\",\n    \"advancements.refinedstorage.wireless_monitoring.description\": \"使用【无线合成监控器】以无线方式检查制作任务的状态\",\n    \"advancements.refinedstorage.no_cables_required\": \"无需电缆\",\n    \"advancements.refinedstorage.no_cables_required.description\": \"使用【网络发送器】，【网络接收器】和【网卡】，无需使用电缆即可为网络添加额外组件\",\n    \"advancements.refinedstorage.upgrading\": \"升级组件！\",\n    \"advancements.refinedstorage.upgrading.description\": \"制作升级组件以改进各种设备\",\n    \"advancements.refinedstorage.crafting_on_demand\": \"按需制作\",\n    \"advancements.refinedstorage.crafting_on_demand.description\": \"使用【合成升级】在接口、输出总线或成型面板按需合成物品或实体\",\n    \"advancements.refinedstorage.more_than_just_storage\": \"不仅仅是存储\",\n    \"advancements.refinedstorage.more_than_just_storage.description\": \"将物品，液体，能量和红石从【读取器】转移到【写入器】\",\n    \"advancements.refinedstorage.detecting\": \"检测\",\n    \"advancements.refinedstorage.detecting.description\": \"使用【检测器】检测网络中的项目或流体\",\n    \"advancements.refinedstorage.interface_to_the_world\": \"与世界的接口\",\n    \"advancements.refinedstorage.interface_to_the_world.description\": \"使用接口同时导出和导入物品\",\n    \"advancements.refinedstorage.storing_externally\": \"外部存储\",\n    \"advancements.refinedstorage.storing_externally.description\": \"使用【外部存储总线】为网络提供来自外部实体的存储\",\n    \"advancements.refinedstorage.covering\": \"伪装板\",\n    \"advancements.refinedstorage.covering.description\": \"合成【伪装板】来隐藏线缆\",\n    \"advancements.refinedstorage.hollow_covering\": \"空心伪装板\",\n    \"advancements.refinedstorage.hollow_covering.description\": \"合成【空心伪装板】来隐藏线缆并不阻碍线缆穿过\",\n    \"advancements.refinedstorage.binding\": \"粘合物\",\n    \"advancements.refinedstorage.binding.description\": \"合成【处理器粘合物】来制作各种处理器\"\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/lang/zh_tw.json",
    "content": "{\n  \"itemGroup.refinedstorage\": \"精緻存儲\",\n  \"itemGroup.refinedstorage.covers\": \"精緻存儲 偽裝板\",\n  \n  \"key.refinedstorage.focusSearchBar\": \"選取終端搜索欄\",\n  \"key.refinedstorage.clearGridCraftingMatrix\": \"清除終端合成矩陣\",\n  \"key.refinedstorage.openWirelessGrid\": \"開啟無限終端\",\n  \"key.refinedstorage.openWirelessFluidGrid\": \"開啟無線液體終端\",\n  \"key.refinedstorage.openPortableGrid\": \"開啟便攜終端\",\n  \"key.refinedstorage.openWirelessCraftingMonitor\": \"開啟無線合成監控器\",\n  \n  \"gui.refinedstorage.controller\": \"控制器\",\n  \"gui.refinedstorage.creative_controller\": \"創造控制器\",\n  \"gui.refinedstorage.grid\": \"終端\",\n  \"gui.refinedstorage.grid.craft\": \"合成\",\n  \"gui.refinedstorage.crafting_grid\": \"合成終端\",\n  \"gui.refinedstorage.pattern_grid\": \"樣板終端\",\n  \"gui.refinedstorage.grid.pattern_create\": \"創造\",\n  \"gui.refinedstorage.fluid_grid\": \"液體終端\",\n  \"gui.refinedstorage.portable_grid\": \"便攜終端\",\n  \"gui.refinedstorage.item_amount\": \"物品數量\",\n  \"gui.refinedstorage.fluid_amount\": \"液體數量以mB為單位\",\n  \"gui.refinedstorage.disk_drive\": \"磁碟驅動器\",\n  \"gui.refinedstorage.disk_drive.disks\": \"磁碟\",\n  \"gui.refinedstorage.disk_manipulator\": \"磁碟操縱器\",\n  \"gui.refinedstorage.disk_manipulator.in\": \"輸入\",\n  \"gui.refinedstorage.disk_manipulator.out\": \"輸出\",\n  \"gui.refinedstorage.external_storage\": \"存儲總線\",\n  \"gui.refinedstorage.importer\": \"輸入總線\",\n  \"gui.refinedstorage.exporter\": \"輸出總線\",\n  \"gui.refinedstorage.detector\": \"檢測器\",\n  \"gui.refinedstorage.destructor\": \"破壞面板\",\n  \"gui.refinedstorage.constructor\": \"成型面板\",\n  \"gui.refinedstorage.relay\": \"中繼器\",\n  \"gui.refinedstorage.interface.import\": \"輸入端\",\n  \"gui.refinedstorage.interface.export\": \"輸出端\",\n  \"gui.refinedstorage.crafting_monitor\": \"合成監控器\",\n  \"gui.refinedstorage.wireless_crafting_monitor\": \"無線合成監控器\",\n  \"gui.refinedstorage.crafting_monitor.tooltip.requested\": \"需要 %d\",\n  \"gui.refinedstorage.crafting_monitor.stored\": \"現存: %d\",\n  \"gui.refinedstorage.crafting_monitor.missing\": \"缺失: %d\",\n  \"gui.refinedstorage.crafting_monitor.processing\": \"處理中: %d\",\n  \"gui.refinedstorage.crafting_monitor.scheduled\": \"計劃合成: %d\",\n  \"gui.refinedstorage.crafting_monitor.crafting\": \"正在合成: %d\",\n  \"gui.refinedstorage.crafting_monitor.machine_does_not_accept_item\": \"機器不接受物品\",\n  \"gui.refinedstorage.crafting_monitor.machine_does_not_accept_fluid\": \"機器不接受液體\",\n  \"gui.refinedstorage.crafting_monitor.machine_none\": \"沒有找到機器\",\n  \"gui.refinedstorage.crafting_monitor.crafter_is_locked\": \"合成被鎖定\",\n  \"gui.refinedstorage.wireless_transmitter\": \"無線訪問點\",\n  \"gui.refinedstorage.wireless_transmitter.distance\": \"%d 方塊\",\n  \"gui.refinedstorage.crafter\": \"裝配室\",\n  \"gui.refinedstorage.filter\": \"終端過濾\",\n  \"gui.refinedstorage.filter.compare_nbt\": \"NBT\",\n  \"gui.refinedstorage.filter.mod_filter\": \"模組過濾\",\n  \"gui.refinedstorage.network_transmitter\": \"網路發送器\",\n  \"gui.refinedstorage.network_transmitter.distance\": \"%d 方塊\",\n  \"gui.refinedstorage.network_transmitter.missing_card\": \"缺失網路卡\",\n  \"gui.refinedstorage.fluid_interface\": \"液體接口\",\n  \"gui.refinedstorage.fluid_interface.in\": \"輸入\",\n  \"gui.refinedstorage.fluid_interface.out\": \"輸出\",\n  \"gui.refinedstorage.crafting_preview\": \"合成預覽\",\n  \"gui.refinedstorage.crafting_preview.to_craft\": \"合成數量: %d\",\n  \"gui.refinedstorage.crafting_preview.available\": \"可用數量: %d\",\n  \"gui.refinedstorage.crafting_preview.missing\": \"缺失: %d\",\n  \"gui.refinedstorage.crafting_preview.error\": \"請求失敗\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.0\": \"其中一種製作成分最終需要\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.1\": \"自己.\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.2\": \"你需要刪除該模式或確保\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.3\": \"在製作過程中不使用模式.\",\n  \"gui.refinedstorage.crafting_preview.error.recursive.4\": \"違規模式:\",\n  \"gui.refinedstorage.crafting_preview.error.too_complex.0\": \"製作任務計算過於複雜\",\n  \"gui.refinedstorage.crafting_preview.error.too_complex.1\": \"並且已停止以緩解伺服器壓力.\",\n  \"gui.refinedstorage.security_manager\": \"安全管理器\",\n  \"gui.refinedstorage.security_manager.configure\": \"配置\",\n  \"gui.refinedstorage.security_manager.permission.0\": \"輸入\",\n  \"gui.refinedstorage.security_manager.permission.0.tooltip\": \"輸入物品或液體至網路\",\n  \"gui.refinedstorage.security_manager.permission.1\": \"輸出\",\n  \"gui.refinedstorage.security_manager.permission.1.tooltip\": \"輸出物品或液體至網路\",\n  \"gui.refinedstorage.security_manager.permission.2\": \"自動合成\",\n  \"gui.refinedstorage.security_manager.permission.2.tooltip\": \"開始, 取消和瀏覽合成任務\",\n  \"gui.refinedstorage.security_manager.permission.3\": \"修改\",\n  \"gui.refinedstorage.security_manager.permission.3.tooltip\": \"打開方塊的GUI\",\n  \"gui.refinedstorage.security_manager.permission.4\": \"建構\",\n  \"gui.refinedstorage.security_manager.permission.4.tooltip\": \"向網路添加或移除設備\",\n  \"gui.refinedstorage.security_manager.permission.5\": \"安全\",\n  \"gui.refinedstorage.security_manager.permission.5.tooltip\": \"改變安全選項\",\n  \"gui.refinedstorage.storage_monitor\": \"存儲監控器\",\n  \"gui.refinedstorage.crafter_manager\": \"合成管理器\",\n  \"gui.refinedstorage.alternatives\": \"使用替代\",\n  \"gui.refinedstorage.alternatives.apply\": \"使用\",\n  \n  \"misc.refinedstorage.energy_stored\": \"%d / %d FE\",\n  \"misc.refinedstorage.energy_usage\": \"耗能: %d FE/t\",\n  \"misc.refinedstorage.energy_usage_minimal\": \"%d FE/t\",\n  \n  \"misc.refinedstorage.storage.stored\": \"已存儲: %s\",\n  \"misc.refinedstorage.storage.stored_capacity\": \"已存儲: %s / %s\",\n  \"misc.refinedstorage.storage.stored_minimal\": \"%s\",\n  \"misc.refinedstorage.storage.stored_capacity_minimal\": \"%s / %s\",\n  \"misc.refinedstorage.storage.full\": \"%d%% 滿\",\n  \n  \"misc.refinedstorage.network_item.tooltip\": \"連接至 %d, %d, %d.\",\n  \"misc.refinedstorage.network_item.out_of_range\": \"範圍內沒有無線訪問點.\",\n  \"misc.refinedstorage.network_item.not_found\": \"沒有找到網路.\",\n  \"misc.refinedstorage.network_item.shortcut_not_found\": \"你的庫存中沒有%s.\",\n  \"misc.refinedstorage.network_item.shortcut_duplicate\": \"你的庫存中有多個%s.\",\n  \"misc.refinedstorage.network_item.out_of_energy\": \"%s 沒電了.\",\n  \n  \"misc.refinedstorage.network_card.tooltip\": \"已在 %s 中連接至 %d, %d, %d.\",\n  \n  \"misc.refinedstorage.pattern.inputs\": \"輸入\",\n  \"misc.refinedstorage.pattern.outputs\": \"輸出\",\n  \"misc.refinedstorage.pattern.invalid\": \"無效樣板\",\n  \"misc.refinedstorage.pattern.exact\": \"使用精確模式\",\n  \"misc.refinedstorage.pattern.allowed_item_tag\": \"在%s中使用%s的物品\",\n  \"misc.refinedstorage.pattern.allowed_fluid_tag\": \"在%s中使用%s的液體\",\n  \n  \"misc.refinedstorage.pattern.error.processing_no_outputs\": \"處理中的樣板沒有輸出\",\n  \"misc.refinedstorage.pattern.error.no_output\": \"配方沒有輸出\",\n  \"misc.refinedstorage.pattern.error.recipe_does_not_exist\": \"配方不存在\",\n  \"misc.refinedstorage.pattern.error.tag_no_longer_applicable\": \"標籤%s不再適用於%s\",\n  \n  \"misc.refinedstorage.security.no_permission\": \"你沒有權限執行該操作.\",\n  \n  \"misc.refinedstorage.start\": \"開始\",\n  \"misc.refinedstorage.clear\": \"清除\",\n  \"misc.refinedstorage.set\": \"設置\",\n  \"misc.refinedstorage.cancel_all\": \"取消所有\",\n  \"misc.refinedstorage.priority\": \"優先級\",\n  \"misc.refinedstorage.exact\": \"合成模式\",\n  \"misc.refinedstorage.processing\": \"熔爐模式\",\n  \n  \"misc.refinedstorage.total\": \"總共 %s 個\",\n  \n  \"misc.refinedstorage.last_modified.just_now\": \"剛剛被 %s 操作\",\n  \"misc.refinedstorage.last_modified.second\": \"%d 秒前被 %s 操作\",\n  \"misc.refinedstorage.last_modified.seconds\": \"%d 秒前被 %s 操作\",\n  \"misc.refinedstorage.last_modified.minute\": \"%d 分前被 %s 操作\",\n  \"misc.refinedstorage.last_modified.minutes\": \"%d 分前被 %s 操作\",\n  \"misc.refinedstorage.last_modified.hour\": \"%d 小時前被 %s 操作\",\n  \"misc.refinedstorage.last_modified.hours\": \"%d 小時前被 %s 操作\",\n  \"misc.refinedstorage.last_modified.day\": \"%d 天前被 %s 操作\",\n  \"misc.refinedstorage.last_modified.days\": \"%d 天前被 %s 操作\",\n  \"misc.refinedstorage.last_modified.week\": \"%d 月前被 %s 操作\",\n  \"misc.refinedstorage.last_modified.weeks\": \"%d 月前被 %s 操作\",\n  \"misc.refinedstorage.last_modified.year\": \"%d 年前被 %s 操作\",\n  \"misc.refinedstorage.last_modified.years\": \"%d 年前被 %s 操作\",\n  \n  \"sidebutton.refinedstorage.exact_mode\": \"精確模式\",\n  \"sidebutton.refinedstorage.exact_mode.on\": \"開啟\",\n  \"sidebutton.refinedstorage.exact_mode.off\": \"關閉\",\n  \n  \"sidebutton.refinedstorage.redstone_mode\": \"紅石模式\",\n  \"sidebutton.refinedstorage.redstone_mode.0\": \"忽略紅石信號\",\n  \"sidebutton.refinedstorage.redstone_mode.1\": \"有紅石信號時工作\",\n  \"sidebutton.refinedstorage.redstone_mode.2\": \"無紅石信號時工作\",\n  \n  \"sidebutton.refinedstorage.crafter_mode\": \"合成模式\",\n  \"sidebutton.refinedstorage.crafter_mode.0\": \"忽略紅石信號\",\n  \"sidebutton.refinedstorage.crafter_mode.1\": \"紅石信號解鎖自動合成\",\n  \"sidebutton.refinedstorage.crafter_mode.2\": \"紅石信號鎖定自動合成\",\n  \"sidebutton.refinedstorage.crafter_mode.3\": \"紅石脈衝插入下一組\",\n  \n  \"sidebutton.refinedstorage.grid.view_type\": \"顯示\",\n  \"sidebutton.refinedstorage.grid.view_type.0\": \"普通\",\n  \"sidebutton.refinedstorage.grid.view_type.1\": \"隱藏合成\",\n  \"sidebutton.refinedstorage.grid.view_type.2\": \"可合成\",\n  \"sidebutton.refinedstorage.grid.sorting.direction\": \"排序方式\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.0\": \"上升\",\n  \"sidebutton.refinedstorage.grid.sorting.direction.1\": \"下降\",\n  \"sidebutton.refinedstorage.grid.sorting.type\": \"排序按\",\n  \"sidebutton.refinedstorage.grid.sorting.type.0\": \"數量\",\n  \"sidebutton.refinedstorage.grid.sorting.type.1\": \"名稱\",\n  \"sidebutton.refinedstorage.grid.sorting.type.2\": \"ID\",\n  \"sidebutton.refinedstorage.grid.sorting.type.3\": \"InventoryTweaks\",\n  \"sidebutton.refinedstorage.grid.sorting.type.4\": \"最後修改\",\n  \"sidebutton.refinedstorage.grid.search_box_mode\": \"搜索框模式\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.0\": \"標準搜索\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.1\": \"自動搜索\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.2\": \"JEI標準同步\",\n  \"sidebutton.refinedstorage.grid.search_box_mode.3\": \"JEI自動同步\",\n  \"sidebutton.refinedstorage.grid.size\": \"大小\",\n  \"sidebutton.refinedstorage.grid.size.0\": \"自動\",\n  \"sidebutton.refinedstorage.grid.size.1\": \"小\",\n  \"sidebutton.refinedstorage.grid.size.2\": \"中\",\n  \"sidebutton.refinedstorage.grid.size.3\": \"大\",\n  \n  \"sidebutton.refinedstorage.mode\": \"模式\",\n  \"sidebutton.refinedstorage.mode.whitelist\": \"白名單\",\n  \"sidebutton.refinedstorage.mode.blacklist\": \"黑名單\",\n  \n  \"sidebutton.refinedstorage.iomode\": \"IO模式\",\n  \"sidebutton.refinedstorage.iomode.insert\": \"輸入到網路\",\n  \"sidebutton.refinedstorage.iomode.extract\": \"從網路輸出\",\n  \n  \"sidebutton.refinedstorage.type\": \"項目\",\n  \"sidebutton.refinedstorage.type.0\": \"物品\",\n  \"sidebutton.refinedstorage.type.1\": \"液體\",\n  \n  \"sidebutton.refinedstorage.detector.mode\": \"模式\",\n  \"sidebutton.refinedstorage.detector.mode.0\": \"物品數量小於輸入數量時輸出信號\",\n  \"sidebutton.refinedstorage.detector.mode.1\": \"物品數量等於輸入數量時輸出信號\",\n  \"sidebutton.refinedstorage.detector.mode.2\": \"物品數量大於輸入數量時輸出信號\",\n  \n  \"sidebutton.refinedstorage.constructor.drop\": \"掉落方塊而不是放置\",\n  \n  \"sidebutton.refinedstorage.destructor.pickup\": \"撿起物品而不是破壞\",\n  \n  \"sidebutton.refinedstorage.access_type\": \"訪問類型\",\n  \"sidebutton.refinedstorage.access_type.0\": \"輸入/輸出\",\n  \"sidebutton.refinedstorage.access_type.1\": \"輸入\",\n  \"sidebutton.refinedstorage.access_type.2\": \"輸出\",\n  \n  \"block.refinedstorage.controller\": \"控制器\",\n  \"block.refinedstorage.creative_controller\": \"創造控制器\",\n  \"block.refinedstorage.cable\": \"線纜\",\n  \"block.refinedstorage.grid\": \"終端\",\n  \"block.refinedstorage.crafting_grid\": \"合成終端\",\n  \"block.refinedstorage.pattern_grid\": \"樣板終端\",\n  \"block.refinedstorage.fluid_grid\": \"液體終端\",\n  \"block.refinedstorage.disk_drive\": \"磁碟驅動器\",\n  \"block.refinedstorage.disk_manipulator\": \"磁碟操縱器\",\n  \"block.refinedstorage.external_storage\": \"存儲總線\",\n  \"block.refinedstorage.importer\": \"輸入總線\",\n  \"block.refinedstorage.exporter\": \"輸出總線\",\n  \"block.refinedstorage.detector\": \"檢測器\",\n  \"block.refinedstorage.machine_casing\": \"機械框架\",\n  \"block.refinedstorage.destructor\": \"破壞面板\",\n  \"block.refinedstorage.constructor\": \"成型面板\",\n  \"block.refinedstorage.1k_storage_block\": \"1k 存儲方塊\",\n  \"block.refinedstorage.4k_storage_block\": \"4k 存儲方塊\",\n  \"block.refinedstorage.16k_storage_block\": \"16k 存儲方塊\",\n  \"block.refinedstorage.64k_storage_block\": \"64k 存儲方塊\",\n  \"block.refinedstorage.creative_storage_block\": \"創造存儲方塊\",\n  \"block.refinedstorage.relay\": \"中繼器\",\n  \"block.refinedstorage.interface\": \"接口\",\n  \"block.refinedstorage.crafting_monitor\": \"合成監控器\",\n  \"block.refinedstorage.wireless_transmitter\": \"無線訪問點\",\n  \"block.refinedstorage.wireless_transmitter.tooltip\": \"必須放置在 %s 上.\",\n  \"block.refinedstorage.crafter\": \"裝配室\",\n  \"block.refinedstorage.network_receiver\": \"網路接收器\",\n  \"block.refinedstorage.network_transmitter\": \"網路發送器\",\n  \"block.refinedstorage.fluid_interface\": \"液體接口\",\n  \"block.refinedstorage.64k_fluid_storage_block\": \"64k 液體存儲方塊\",\n  \"block.refinedstorage.256k_fluid_storage_block\": \"256k 液體存儲方塊\",\n  \"block.refinedstorage.1024k_fluid_storage_block\": \"1024k 液體存儲方塊\",\n  \"block.refinedstorage.4096k_fluid_storage_block\": \"4096k 液體存儲方塊\",\n  \"block.refinedstorage.creative_fluid_storage_block\": \"創造液體存儲方塊\",\n  \"block.refinedstorage.security_manager\": \"安全管理器\",\n  \"block.refinedstorage.quartz_enriched_iron_block\": \"石英富鐵磚\",\n  \"block.refinedstorage.storage_monitor\": \"存儲監控器\",\n  \"block.refinedstorage.portable_grid\": \"便攜終端\",\n  \"block.refinedstorage.creative_portable_grid\": \"創造便攜終端\",\n  \"block.refinedstorage.portable_grid.tooltip\": \"Shift進行放置.\",\n  \"block.refinedstorage.crafter_manager\": \"合成管理器\",\n  \n  \"item.refinedstorage.1k_storage_disk\": \"1k 存儲磁碟\",\n  \"item.refinedstorage.4k_storage_disk\": \"4k 存儲磁碟\",\n  \"item.refinedstorage.16k_storage_disk\": \"16k 存儲磁碟\",\n  \"item.refinedstorage.64k_storage_disk\": \"64k 存儲磁碟\",\n  \"item.refinedstorage.creative_storage_disk\": \"創造存儲磁碟\",\n  \"item.refinedstorage.64k_fluid_storage_disk\": \"64k 液體存儲磁碟\",\n  \"item.refinedstorage.256k_fluid_storage_disk\": \"256k 液體存儲磁碟\",\n  \"item.refinedstorage.1024k_fluid_storage_disk\": \"1024k 液體存儲磁碟\",\n  \"item.refinedstorage.4096k_fluid_storage_disk\": \"4096k 液體存儲磁碟\",\n  \"item.refinedstorage.creative_fluid_storage_disk\": \"創造液體存儲磁碟\",\n  \"item.refinedstorage.wireless_grid\": \"無線終端\",\n  \"item.refinedstorage.creative_wireless_grid\": \"創造無線終端\",\n  \"item.refinedstorage.wireless_fluid_grid\": \"無線液體終端\",\n  \"item.refinedstorage.creative_wireless_fluid_grid\": \"創造無線液體終端\",\n  \"item.refinedstorage.wireless_crafting_monitor\": \"無線合成監控器\",\n  \"item.refinedstorage.creative_wireless_crafting_monitor\": \"創造無線合成監控器\",\n  \"item.refinedstorage.quartz_enriched_iron\": \"石英富鐵\",\n  \"item.refinedstorage.construction_core\": \"成型核心\",\n  \"item.refinedstorage.destruction_core\": \"破壞核心\",\n  \"item.refinedstorage.silicon\": \"矽\",\n  \"item.refinedstorage.raw_basic_processor\": \"未處理的基礎處理器\",\n  \"item.refinedstorage.raw_improved_processor\": \"未處理的進階處理器\",\n  \"item.refinedstorage.raw_advanced_processor\": \"未處理的高級處理器\",\n  \"item.refinedstorage.basic_processor\": \"基礎處理器\",\n  \"item.refinedstorage.improved_processor\": \"進階處理器\",\n  \"item.refinedstorage.advanced_processor\": \"高級處理器\",\n  \"item.refinedstorage.1k_storage_part\": \"1k 存儲元件\",\n  \"item.refinedstorage.4k_storage_part\": \"4k 存儲元件\",\n  \"item.refinedstorage.16k_storage_part\": \"16k 存儲元件\",\n  \"item.refinedstorage.64k_storage_part\": \"64k 存儲元件\",\n  \"item.refinedstorage.64k_fluid_storage_part\": \"64k 液體存儲元件\",\n  \"item.refinedstorage.256k_fluid_storage_part\": \"256k 液體存儲元件\",\n  \"item.refinedstorage.1024k_fluid_storage_part\": \"1024k 液體存儲元件\",\n  \"item.refinedstorage.4096k_fluid_storage_part\": \"4096k 液體存儲元件\",\n  \"item.refinedstorage.pattern\": \"樣板\",\n  \"item.refinedstorage.upgrade\": \"升級\",\n  \"item.refinedstorage.range_upgrade\": \"範圍升級\",\n  \"item.refinedstorage.speed_upgrade\": \"速度升級\",\n  \"item.refinedstorage.crafting_upgrade\": \"合成升級\",\n  \"item.refinedstorage.stack_upgrade\": \"堆疊升級\",\n  \"item.refinedstorage.silk_touch_upgrade\": \"絲綢之觸升級\",\n  \"item.refinedstorage.fortune_1_upgrade\": \"幸運升級\",\n  \"item.refinedstorage.fortune_2_upgrade\": \"幸運升級\",\n  \"item.refinedstorage.fortune_3_upgrade\": \"幸運升級\",\n  \"item.refinedstorage.regulator_upgrade\": \"調節升級\",\n  \"item.refinedstorage.storage_housing\": \"存儲外殼\",\n  \"item.refinedstorage.filter\": \"過濾器\",\n  \"item.refinedstorage.network_card\": \"網路卡\",\n  \"item.refinedstorage.wrench\": \"板手\",\n  \"item.refinedstorage.security_card\": \"安全卡\",\n  \"item.refinedstorage.security_card.owner\": \"綁定至: %s\",\n  \"item.refinedstorage.processor_binding\": \"處理器黏合物\",\n  \"commands.refinedstorage.disk.create.error.disk_not_found\": \"磁碟 %s 未找到.\",\n  \"commands.refinedstorage.disk.create.success\": \"成功把磁碟 %s 給了 %s.\",\n  \"advancements.refinedstorage.controlling.description\": \"合成一個控制器\",\n  \"advancements.refinedstorage.connecting\": \"連接\",\n  \"advancements.refinedstorage.connecting.description\": \"你可以將所有設備放在一起或者使用線纜以將它們連接起來\",\n  \"advancements.refinedstorage.conditional_connecting\": \"條件連接\",\n  \"advancements.refinedstorage.conditional_connecting.description\": \"製作一個中繼器來控制網路信號是否可以通過紅石\",\n  \"advancements.refinedstorage.drives\": \"驅動器\",\n  \"advancements.refinedstorage.drives.description\": \"製作磁碟驅動器以便能夠存儲磁碟\",\n  \"advancements.refinedstorage.manipulating_disks\": \"磁碟操縱器\",\n  \"advancements.refinedstorage.manipulating_disks.description\": \"使用磁碟操縱器可以輕鬆修改磁碟內容\",\n  \"advancements.refinedstorage.storing_items\": \"存儲物品\",\n  \"advancements.refinedstorage.storing_items.description\": \"製作存儲磁碟並將其放入磁碟驅動器中\",\n  \"advancements.refinedstorage.viewing_items\": \"瀏覽物品\",\n  \"advancements.refinedstorage.viewing_items.description\": \"製作終端與你的物品存儲進行交互\",\n  \"advancements.refinedstorage.portable_storage\": \"便攜存儲\",\n  \"advancements.refinedstorage.portable_storage.description\": \"製作便攜式終端，以便在不在網路中的情況下訪問磁碟中的物品或液體\",\n  \"advancements.refinedstorage.upgrading_your_grid\": \"升級你的終端\",\n  \"advancements.refinedstorage.upgrading_your_grid.description\": \"將終端升級到合成終端以獲得終端中的製作能力\",\n  \"advancements.refinedstorage.storing_fluids\": \"存儲液體\",\n  \"advancements.refinedstorage.storing_fluids.description\": \"製作液體存儲磁碟並將其放入磁碟驅動器中\",\n  \"advancements.refinedstorage.viewing_fluids\": \"瀏覽液體\",\n  \"advancements.refinedstorage.viewing_fluids.description\": \"製作液體終端與你的液體存儲進行交互\",\n  \"advancements.refinedstorage.better_than_a_barrel\": \"比桶更好\",\n  \"advancements.refinedstorage.better_than_a_barrel.description\": \"製作存儲監控器以查看，網路中物品的輸入或輸出\",\n  \"advancements.refinedstorage.autocrafting\": \"合成自動化\",\n  \"advancements.refinedstorage.autocrafting.description\": \"製作一個裝配室\",\n  \"advancements.refinedstorage.pattern_creation\": \"編寫樣板\",\n  \"advancements.refinedstorage.pattern_creation.description\": \"使用樣板終端和樣板編寫樣板\",\n  \"advancements.refinedstorage.monitoring\": \"監控器\",\n  \"advancements.refinedstorage.monitoring.description\": \"使用合成監控器檢查製作任務的狀態\",\n  \"advancements.refinedstorage.managing_patterns\": \"樣板管理器\",\n  \"advancements.refinedstorage.managing_patterns.description\": \"製作樣板管理器以更好的方式管理你的樣板\",\n  \"advancements.refinedstorage.importing\": \"輸入總線\",\n  \"advancements.refinedstorage.importing.description\": \"使用輸入總線將物品或流體輸入存儲網路\",\n  \"advancements.refinedstorage.destruction\": \"破壞面板\",\n  \"advancements.refinedstorage.destruction.description\": \"使用破壞面板將物品或流體輸出存儲網路\",\n  \"advancements.refinedstorage.exporting\": \"輸出總線\",\n  \"advancements.refinedstorage.exporting.description\": \"使用輸出總線將物品或流體輸出存儲網路\",\n  \"advancements.refinedstorage.construction\": \"成型面板\",\n  \"advancements.refinedstorage.construction.description\": \"使用成型面板將物品或流體輸出存儲網路\",\n  \"advancements.refinedstorage.security\": \"安全\",\n  \"advancements.refinedstorage.security.description\": \"使用安全管理器和安全卡保護你的網路\",\n  \"advancements.refinedstorage.wireless\": \"無線\",\n  \"advancements.refinedstorage.wireless.description\": \"使用無線訪問點傳輸網路信號\",\n  \"advancements.refinedstorage.wireless_items\": \"無線物品\",\n  \"advancements.refinedstorage.wireless_items.description\": \"使用無線終端以無線方式與你的物品存儲進行交互\",\n  \"advancements.refinedstorage.wireless_fluids\": \"無線液體\",\n  \"advancements.refinedstorage.wireless_fluids.description\": \"使用無線終端以無線方式與你的液體存儲進行交互\",\n  \"advancements.refinedstorage.wireless_monitoring\": \"無線監控器\",\n  \"advancements.refinedstorage.wireless_monitoring.description\": \"使用無線合成監控器以無線方式檢查製作任務的狀態\",\n  \"advancements.refinedstorage.no_cables_required\": \"無需線纜\",\n  \"advancements.refinedstorage.no_cables_required.description\": \"使用網路發送器，網路接收器和網路卡，無需使用線纜即可為網路添加額外組件\",\n  \"advancements.refinedstorage.upgrading\": \"升級組件\",\n  \"advancements.refinedstorage.upgrading.description\": \"製作升級組件以改進各種設備\",\n  \"advancements.refinedstorage.crafting_on_demand\": \"按照需求合成\",\n  \"advancements.refinedstorage.crafting_on_demand.description\": \"使用合成升級在接口、輸出總線或成型面板按照需求合成物品或方塊\",\n  \"advancements.refinedstorage.detecting\": \"檢測器\",\n  \"advancements.refinedstorage.detecting.description\": \"使用檢測器檢測網路中的物品或液體\",\n  \"advancements.refinedstorage.interface_to_the_world\": \"與世界的接口\",\n  \"advancements.refinedstorage.interface_to_the_world.description\": \"使用接口同時輸出和輸入物品\",\n  \"advancements.refinedstorage.storing_externally\": \"存儲總線\",\n  \"advancements.refinedstorage.storing_externally.description\": \"使用存儲總線總線為網路提供來自外部實體的存儲\"\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/1024k_fluid_storage_block.json",
    "content": "{\n  \"parent\": \"block/cube_all\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/1024k_fluid_storage_block\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/16k_storage_block.json",
    "content": "{\n  \"parent\": \"block/cube_all\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/16k_storage_block\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/1k_storage_block.json",
    "content": "{\n  \"parent\": \"block/cube_all\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/1k_storage_block\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/256k_fluid_storage_block.json",
    "content": "{\n  \"parent\": \"block/cube_all\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/256k_fluid_storage_block\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/4096k_fluid_storage_block.json",
    "content": "{\n  \"parent\": \"block/cube_all\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/4096k_fluid_storage_block\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/4k_storage_block.json",
    "content": "{\n  \"parent\": \"block/cube_all\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/4k_storage_block\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/64k_fluid_storage_block.json",
    "content": "{\n  \"parent\": \"block/cube_all\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/64k_fluid_storage_block\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/64k_storage_block.json",
    "content": "{\n  \"parent\": \"block/cube_all\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/64k_storage_block\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/cable_core.json",
    "content": "{\n  \"render_type\": \"cutout\",\n  \"textures\": {\n    \"cable\": \"refinedstorage:block/cable\",\n    \"particle\": \"refinedstorage:block/cable\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"Core\",\n      \"from\": [\n        6.0,\n        6.0,\n        6.0\n      ],\n      \"to\": [\n        10.0,\n        10.0,\n        10.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#cable\",\n          \"uv\": [\n            6.0,\n            6.0,\n            10.0,\n            10.0\n          ]\n        },\n        \"east\": {\n          \"texture\": \"#cable\",\n          \"uv\": [\n            6.0,\n            6.0,\n            10.0,\n            10.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#cable\",\n          \"uv\": [\n            6.0,\n            6.0,\n            10.0,\n            10.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#cable\",\n          \"uv\": [\n            6.0,\n            6.0,\n            10.0,\n            10.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#cable\",\n          \"uv\": [\n            6.0,\n            6.0,\n            10.0,\n            10.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#cable\",\n          \"uv\": [\n            6.0,\n            6.0,\n            10.0,\n            10.0\n          ]\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/cable_extension.json",
    "content": "{\n  \"render_type\": \"cutout\",\n  \"textures\": {\n    \"cable\": \"refinedstorage:block/cable\",\n    \"particle\": \"refinedstorage:block/cable\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"North\",\n      \"from\": [\n        6.0,\n        6.0,\n        0.0\n      ],\n      \"to\": [\n        10.0,\n        10.0,\n        6.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#cable\",\n          \"uv\": [\n            6.0,\n            6.0,\n            10.0,\n            10.0\n          ]\n        },\n        \"east\": {\n          \"texture\": \"#cable\",\n          \"uv\": [\n            10.0,\n            6.0,\n            16.0,\n            10.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#cable\",\n          \"uv\": [\n            6.0,\n            6.0,\n            10.0,\n            10.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#cable\",\n          \"uv\": [\n            0.0,\n            6.0,\n            6.0,\n            10.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#cable\",\n          \"uv\": [\n            6.0,\n            0.0,\n            10.0,\n            6.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#cable\",\n          \"uv\": [\n            6.0,\n            10.0,\n            10.0,\n            16.0\n          ]\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/constructor_connected.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/constructor_destructor\",\n  \"textures\": {\n    \"front\": \"refinedstorage:block/constructor/constructor\",\n    \"cutout\": \"refinedstorage:block/constructor/cutouts/connected\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/constructor_destructor.json",
    "content": "{\n  \"render_type\": \"cutout\",\n  \"textures\": {\n    \"border\": \"refinedstorage:block/cable_part_border\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"Line1\",\n      \"from\": [\n        7.0,\n        7.0,\n        2.0\n      ],\n      \"to\": [\n        9.0,\n        9.0,\n        6.0\n      ],\n      \"faces\": {\n        \"east\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            2.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            4.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            2.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            4.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            4.0\n          ]\n        }\n      }\n    },\n    {\n      \"name\": \"Line2\",\n      \"from\": [\n        2.0,\n        2.0,\n        0.0\n      ],\n      \"to\": [\n        14.0,\n        14.0,\n        2.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#front\",\n          \"uv\": [\n            0.0,\n            0.0,\n            16.0,\n            16.0\n          ]\n        },\n        \"east\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            14.0,\n            0.0,\n            16.0,\n            16.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            16.0,\n            16.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            16.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            2.0,\n            0.0,\n            14.0,\n            2.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            2.0,\n            14.0,\n            14.0,\n            16.0\n          ]\n        }\n      }\n    },\n    {\n      \"name\": \"Line3\",\n      \"from\": [\n        2.0,\n        2.0,\n        0.0\n      ],\n      \"to\": [\n        14.0,\n        14.0,\n        2.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#cutout\",\n          \"uv\": [\n            0.0,\n            0.0,\n            16.0,\n            16.0\n          ],\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/constructor_destructor_nonemissive.json",
    "content": "{\n  \"render_type\": \"cutout\",\n  \"textures\": {\n    \"border\": \"refinedstorage:block/cable_part_border\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"Line1\",\n      \"from\": [\n        7.0,\n        7.0,\n        2.0\n      ],\n      \"to\": [\n        9.0,\n        9.0,\n        6.0\n      ],\n      \"faces\": {\n        \"east\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            2.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            4.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            2.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            4.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            4.0\n          ]\n        }\n      }\n    },\n    {\n      \"name\": \"Line2\",\n      \"from\": [\n        2.0,\n        2.0,\n        0.0\n      ],\n      \"to\": [\n        14.0,\n        14.0,\n        2.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#front\",\n          \"uv\": [\n            0.0,\n            0.0,\n            16.0,\n            16.0\n          ]\n        },\n        \"east\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            14.0,\n            0.0,\n            16.0,\n            16.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            16.0,\n            16.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            16.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            2.0,\n            0.0,\n            14.0,\n            2.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            2.0,\n            14.0,\n            14.0,\n            16.0\n          ]\n        }\n      }\n    },\n    {\n      \"name\": \"Line3\",\n      \"from\": [\n        2.0,\n        2.0,\n        0.0\n      ],\n      \"to\": [\n        14.0,\n        14.0,\n        2.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#cutout\",\n          \"uv\": [\n            0.0,\n            0.0,\n            16.0,\n            16.0\n          ]\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/constructor_disconnected.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/constructor_destructor_nonemissive\",\n  \"textures\": {\n    \"front\": \"refinedstorage:block/constructor/constructor\",\n    \"cutout\": \"refinedstorage:block/constructor/cutouts/disconnected\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/controller_nearly.json",
    "content": "{\n  \"render_type\": \"cutout\",\n  \"parent\": \"block/cube\",\n  \"elements\": [\n    {\n      \"from\": [\n        0,\n        0,\n        0\n      ],\n      \"to\": [\n        16,\n        16,\n        16\n      ],\n      \"faces\": {\n        \"down\": {\n          \"texture\": \"#all\",\n          \"cullface\": \"down\"\n        },\n        \"up\": {\n          \"texture\": \"#all\",\n          \"cullface\": \"up\"\n        },\n        \"north\": {\n          \"texture\": \"#all\",\n          \"cullface\": \"north\"\n        },\n        \"south\": {\n          \"texture\": \"#all\",\n          \"cullface\": \"south\"\n        },\n        \"west\": {\n          \"texture\": \"#all\",\n          \"cullface\": \"west\"\n        },\n        \"east\": {\n          \"texture\": \"#all\",\n          \"cullface\": \"east\"\n        }\n      }\n    },\n    {\n      \"from\": [\n        0,\n        0,\n        0\n      ],\n      \"to\": [\n        16,\n        16,\n        16\n      ],\n      \"faces\": {\n        \"up\": {\n          \"texture\": \"#cutout\",\n          \"cullface\": \"up\"\n        },\n        \"down\": {\n          \"texture\": \"#cutout\",\n          \"cullface\": \"down\"\n        },\n        \"north\": {\n          \"texture\": \"#cutout\",\n          \"cullface\": \"north\"\n        },\n        \"south\": {\n          \"texture\": \"#cutout\",\n          \"cullface\": \"south\"\n        },\n        \"west\": {\n          \"texture\": \"#cutout\",\n          \"cullface\": \"west\"\n        },\n        \"east\": {\n          \"texture\": \"#cutout\",\n          \"cullface\": \"east\"\n        }\n      }\n    },\n    {\n      \"from\": [\n        0,\n        0,\n        0\n      ],\n      \"to\": [\n        16,\n        16,\n        16\n      ],\n      \"faces\": {\n        \"up\": {\n          \"texture\": \"#cutout_gray\",\n          \"cullface\": \"up\"\n        },\n        \"down\": {\n          \"texture\": \"#cutout_gray\",\n          \"cullface\": \"down\"\n        },\n        \"north\": {\n          \"texture\": \"#cutout_gray\",\n          \"cullface\": \"north\"\n        },\n        \"south\": {\n          \"texture\": \"#cutout_gray\",\n          \"cullface\": \"south\"\n        },\n        \"west\": {\n          \"texture\": \"#cutout_gray\",\n          \"cullface\": \"west\"\n        },\n        \"east\": {\n          \"texture\": \"#cutout_gray\",\n          \"cullface\": \"east\"\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/creative_fluid_storage_block.json",
    "content": "{\n  \"parent\": \"block/cube_all\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/creative_fluid_storage_block\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/creative_storage_block.json",
    "content": "{\n  \"parent\": \"block/cube_all\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/creative_storage_block\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/cube_all_cutout.json",
    "content": "{\n  \"render_type\": \"cutout\",\n  \"parent\": \"block/cube\",\n  \"elements\": [\n    {\n      \"from\": [\n        0,\n        0,\n        0\n      ],\n      \"to\": [\n        16,\n        16,\n        16\n      ],\n      \"faces\": {\n        \"down\": {\n          \"texture\": \"#all\",\n          \"cullface\": \"down\"\n        },\n        \"up\": {\n          \"texture\": \"#all\",\n          \"cullface\": \"up\"\n        },\n        \"north\": {\n          \"texture\": \"#all\",\n          \"cullface\": \"north\"\n        },\n        \"south\": {\n          \"texture\": \"#all\",\n          \"cullface\": \"south\"\n        },\n        \"west\": {\n          \"texture\": \"#all\",\n          \"cullface\": \"west\"\n        },\n        \"east\": {\n          \"texture\": \"#all\",\n          \"cullface\": \"east\"\n        }\n      }\n    },\n    {\n      \"from\": [\n        0,\n        0,\n        0\n      ],\n      \"to\": [\n        16,\n        16,\n        16\n      ],\n      \"faces\": {\n        \"up\": {\n          \"texture\": \"#cutout\",\n          \"cullface\": \"up\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"down\": {\n          \"texture\": \"#cutout\",\n          \"cullface\": \"down\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"north\": {\n          \"texture\": \"#cutout\",\n          \"cullface\": \"north\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"south\": {\n          \"texture\": \"#cutout\",\n          \"cullface\": \"south\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"west\": {\n          \"texture\": \"#cutout\",\n          \"cullface\": \"west\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"east\": {\n          \"texture\": \"#cutout\",\n          \"cullface\": \"east\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/cube_all_cutout_nonemissive.json",
    "content": "{\n  \"render_type\": \"cutout\",\n  \"parent\": \"block/cube\",\n  \"elements\": [\n    {\n      \"from\": [\n        0,\n        0,\n        0\n      ],\n      \"to\": [\n        16,\n        16,\n        16\n      ],\n      \"faces\": {\n        \"down\": {\n          \"texture\": \"#all\",\n          \"cullface\": \"down\"\n        },\n        \"up\": {\n          \"texture\": \"#all\",\n          \"cullface\": \"up\"\n        },\n        \"north\": {\n          \"texture\": \"#all\",\n          \"cullface\": \"north\"\n        },\n        \"south\": {\n          \"texture\": \"#all\",\n          \"cullface\": \"south\"\n        },\n        \"west\": {\n          \"texture\": \"#all\",\n          \"cullface\": \"west\"\n        },\n        \"east\": {\n          \"texture\": \"#all\",\n          \"cullface\": \"east\"\n        }\n      }\n    },\n    {\n      \"from\": [\n        0,\n        0,\n        0\n      ],\n      \"to\": [\n        16,\n        16,\n        16\n      ],\n      \"faces\": {\n        \"up\": {\n          \"texture\": \"#cutout\",\n          \"cullface\": \"up\"\n        },\n        \"down\": {\n          \"texture\": \"#cutout\",\n          \"cullface\": \"down\"\n        },\n        \"north\": {\n          \"texture\": \"#cutout\",\n          \"cullface\": \"north\"\n        },\n        \"south\": {\n          \"texture\": \"#cutout\",\n          \"cullface\": \"south\"\n        },\n        \"west\": {\n          \"texture\": \"#cutout\",\n          \"cullface\": \"west\"\n        },\n        \"east\": {\n          \"texture\": \"#cutout\",\n          \"cullface\": \"east\"\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/cube_cutout.json",
    "content": "{\n  \"render_type\": \"cutout\",\n  \"parent\": \"block/cube\",\n  \"elements\": [\n    {\n      \"from\": [\n        0,\n        0,\n        0\n      ],\n      \"to\": [\n        16,\n        16,\n        16\n      ],\n      \"faces\": {\n        \"down\": {\n          \"texture\": \"#down\",\n          \"cullface\": \"down\"\n        },\n        \"up\": {\n          \"texture\": \"#up\",\n          \"cullface\": \"up\"\n        },\n        \"north\": {\n          \"texture\": \"#north\",\n          \"cullface\": \"north\"\n        },\n        \"south\": {\n          \"texture\": \"#south\",\n          \"cullface\": \"south\"\n        },\n        \"west\": {\n          \"texture\": \"#west\",\n          \"cullface\": \"west\"\n        },\n        \"east\": {\n          \"texture\": \"#east\",\n          \"cullface\": \"east\"\n        }\n      }\n    },\n    {\n      \"from\": [\n        0,\n        0,\n        0\n      ],\n      \"to\": [\n        16,\n        16,\n        16\n      ],\n      \"faces\": {\n        \"up\": {\n          \"texture\": \"#cutout_up\",\n          \"cullface\": \"up\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"down\": {\n          \"texture\": \"#cutout_down\",\n          \"cullface\": \"down\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"north\": {\n          \"texture\": \"#cutout_north\",\n          \"cullface\": \"north\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"south\": {\n          \"texture\": \"#cutout_south\",\n          \"cullface\": \"south\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"west\": {\n          \"texture\": \"#cutout_west\",\n          \"cullface\": \"west\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"east\": {\n          \"texture\": \"#cutout_east\",\n          \"cullface\": \"east\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/cube_cutout_nonemissive.json",
    "content": "{\n  \"render_type\": \"cutout\",\n  \"parent\": \"block/cube\",\n  \"elements\": [\n    {\n      \"from\": [\n        0,\n        0,\n        0\n      ],\n      \"to\": [\n        16,\n        16,\n        16\n      ],\n      \"faces\": {\n        \"down\": {\n          \"texture\": \"#down\",\n          \"cullface\": \"down\"\n        },\n        \"up\": {\n          \"texture\": \"#up\",\n          \"cullface\": \"up\"\n        },\n        \"north\": {\n          \"texture\": \"#north\",\n          \"cullface\": \"north\"\n        },\n        \"south\": {\n          \"texture\": \"#south\",\n          \"cullface\": \"south\"\n        },\n        \"west\": {\n          \"texture\": \"#west\",\n          \"cullface\": \"west\"\n        },\n        \"east\": {\n          \"texture\": \"#east\",\n          \"cullface\": \"east\"\n        }\n      }\n    },\n    {\n      \"from\": [\n        0,\n        0,\n        0\n      ],\n      \"to\": [\n        16,\n        16,\n        16\n      ],\n      \"faces\": {\n        \"up\": {\n          \"texture\": \"#cutout_up\",\n          \"cullface\": \"up\"\n        },\n        \"down\": {\n          \"texture\": \"#cutout_down\",\n          \"cullface\": \"down\"\n        },\n        \"north\": {\n          \"texture\": \"#cutout_north\",\n          \"cullface\": \"north\"\n        },\n        \"south\": {\n          \"texture\": \"#cutout_south\",\n          \"cullface\": \"south\"\n        },\n        \"west\": {\n          \"texture\": \"#cutout_west\",\n          \"cullface\": \"west\"\n        },\n        \"east\": {\n          \"texture\": \"#cutout_east\",\n          \"cullface\": \"east\"\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/cube_north_cutout.json",
    "content": "{\n  \"render_type\": \"cutout\",\n  \"parent\": \"block/cube\",\n  \"elements\": [\n    {\n      \"from\": [\n        0,\n        0,\n        0\n      ],\n      \"to\": [\n        16,\n        16,\n        16\n      ],\n      \"faces\": {\n        \"down\": {\n          \"texture\": \"#down\",\n          \"cullface\": \"down\"\n        },\n        \"up\": {\n          \"texture\": \"#up\",\n          \"cullface\": \"up\"\n        },\n        \"north\": {\n          \"texture\": \"#north\",\n          \"cullface\": \"north\"\n        },\n        \"south\": {\n          \"texture\": \"#south\",\n          \"cullface\": \"south\"\n        },\n        \"west\": {\n          \"texture\": \"#west\",\n          \"cullface\": \"west\"\n        },\n        \"east\": {\n          \"texture\": \"#east\",\n          \"cullface\": \"east\"\n        }\n      }\n    },\n    {\n      \"from\": [\n        0,\n        0,\n        0\n      ],\n      \"to\": [\n        16,\n        16,\n        16\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#cutout\",\n          \"cullface\": \"north\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/cube_north_cutout_nonemissive.json",
    "content": "{\n  \"render_type\": \"cutout\",\n  \"parent\": \"block/cube\",\n  \"elements\": [\n    {\n      \"from\": [\n        0,\n        0,\n        0\n      ],\n      \"to\": [\n        16,\n        16,\n        16\n      ],\n      \"faces\": {\n        \"down\": {\n          \"texture\": \"#down\",\n          \"cullface\": \"down\"\n        },\n        \"up\": {\n          \"texture\": \"#up\",\n          \"cullface\": \"up\"\n        },\n        \"north\": {\n          \"texture\": \"#north\",\n          \"cullface\": \"north\"\n        },\n        \"south\": {\n          \"texture\": \"#south\",\n          \"cullface\": \"south\"\n        },\n        \"west\": {\n          \"texture\": \"#west\",\n          \"cullface\": \"west\"\n        },\n        \"east\": {\n          \"texture\": \"#east\",\n          \"cullface\": \"east\"\n        }\n      }\n    },\n    {\n      \"from\": [\n        0,\n        0,\n        0\n      ],\n      \"to\": [\n        16,\n        16,\n        16\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#cutout\",\n          \"cullface\": \"north\"\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/destructor_connected.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/constructor_destructor\",\n  \"textures\": {\n    \"front\": \"refinedstorage:block/destructor/destructor\",\n    \"cutout\": \"refinedstorage:block/destructor/cutouts/connected\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/destructor_disconnected.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/constructor_destructor_nonemissive\",\n  \"textures\": {\n    \"front\": \"refinedstorage:block/destructor/destructor\",\n    \"cutout\": \"refinedstorage:block/destructor/cutouts/disconnected\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/detector.json",
    "content": "{\n  \"render_type\": \"cutout\",\n  \"parent\": \"block/cube\",\n  \"textures\": {\n    \"side\": \"refinedstorage:block/detector/side\",\n    \"bottom\": \"refinedstorage:block/detector/bottom\",\n    \"top\": \"refinedstorage:block/detector/top\",\n    \"particle\": \"refinedstorage:block/detector/side\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"Handle\",\n      \"from\": [\n        7,\n        5,\n        7\n      ],\n      \"to\": [\n        9,\n        8,\n        9\n      ],\n      \"shade\": false,\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            7,\n            7,\n            9,\n            11\n          ],\n          \"texture\": \"#side\"\n        },\n        \"east\": {\n          \"uv\": [\n            7,\n            7,\n            9,\n            11\n          ],\n          \"texture\": \"#side\"\n        },\n        \"south\": {\n          \"uv\": [\n            7,\n            7,\n            9,\n            11\n          ],\n          \"texture\": \"#side\"\n        },\n        \"west\": {\n          \"uv\": [\n            7,\n            7,\n            9,\n            11\n          ],\n          \"texture\": \"#side\"\n        },\n        \"up\": {\n          \"uv\": [\n            7,\n            7,\n            9,\n            9\n          ],\n          \"texture\": \"#side\"\n        }\n      }\n    },\n    {\n      \"name\": \"Torch\",\n      \"from\": [\n        7,\n        5,\n        6\n      ],\n      \"to\": [\n        9,\n        11,\n        10\n      ],\n      \"shade\": false,\n      \"faces\": {\n        \"east\": {\n          \"uv\": [\n            6,\n            4,\n            10,\n            12\n          ],\n          \"texture\": \"#torch\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            4,\n            10,\n            12\n          ],\n          \"texture\": \"#torch\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        }\n      }\n    },\n    {\n      \"name\": \"Torch\",\n      \"from\": [\n        6,\n        5,\n        7\n      ],\n      \"to\": [\n        10,\n        11,\n        9\n      ],\n      \"shade\": false,\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            6,\n            4,\n            10,\n            12\n          ],\n          \"texture\": \"#torch\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"south\": {\n          \"uv\": [\n            6,\n            4,\n            10,\n            12\n          ],\n          \"texture\": \"#torch\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        }\n      }\n    },\n    {\n      \"name\": \"Base\",\n      \"from\": [\n        0,\n        0,\n        0\n      ],\n      \"to\": [\n        16,\n        5,\n        16\n      ],\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            11,\n            16,\n            16\n          ],\n          \"texture\": \"#side\"\n        },\n        \"east\": {\n          \"uv\": [\n            0,\n            11,\n            16,\n            16\n          ],\n          \"texture\": \"#side\"\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            11,\n            16,\n            16\n          ],\n          \"texture\": \"#side\"\n        },\n        \"west\": {\n          \"uv\": [\n            0,\n            11,\n            16,\n            16\n          ],\n          \"texture\": \"#side\"\n        },\n        \"up\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#top\"\n        },\n        \"down\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#bottom\"\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/detector_nonemissive.json",
    "content": "{\n  \"render_type\": \"cutout\",\n  \"parent\": \"block/cube\",\n  \"textures\": {\n    \"side\": \"refinedstorage:block/detector/side\",\n    \"bottom\": \"refinedstorage:block/detector/bottom\",\n    \"top\": \"refinedstorage:block/detector/top\",\n    \"particle\": \"refinedstorage:block/detector/side\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"Handle\",\n      \"from\": [\n        7,\n        5,\n        7\n      ],\n      \"to\": [\n        9,\n        8,\n        9\n      ],\n      \"shade\": false,\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            7,\n            7,\n            9,\n            11\n          ],\n          \"texture\": \"#side\"\n        },\n        \"east\": {\n          \"uv\": [\n            7,\n            7,\n            9,\n            11\n          ],\n          \"texture\": \"#side\"\n        },\n        \"south\": {\n          \"uv\": [\n            7,\n            7,\n            9,\n            11\n          ],\n          \"texture\": \"#side\"\n        },\n        \"west\": {\n          \"uv\": [\n            7,\n            7,\n            9,\n            11\n          ],\n          \"texture\": \"#side\"\n        },\n        \"up\": {\n          \"uv\": [\n            7,\n            7,\n            9,\n            9\n          ],\n          \"texture\": \"#side\"\n        }\n      }\n    },\n    {\n      \"name\": \"Torch\",\n      \"from\": [\n        7,\n        5,\n        6\n      ],\n      \"to\": [\n        9,\n        11,\n        10\n      ],\n      \"shade\": false,\n      \"faces\": {\n        \"east\": {\n          \"uv\": [\n            6,\n            4,\n            10,\n            12\n          ],\n          \"texture\": \"#torch\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            4,\n            10,\n            12\n          ],\n          \"texture\": \"#torch\"\n        }\n      }\n    },\n    {\n      \"name\": \"Torch\",\n      \"from\": [\n        6,\n        5,\n        7\n      ],\n      \"to\": [\n        10,\n        11,\n        9\n      ],\n      \"shade\": false,\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            6,\n            4,\n            10,\n            12\n          ],\n          \"texture\": \"#torch\"\n        },\n        \"south\": {\n          \"uv\": [\n            6,\n            4,\n            10,\n            12\n          ],\n          \"texture\": \"#torch\"\n        }\n      }\n    },\n    {\n      \"name\": \"Base\",\n      \"from\": [\n        0,\n        0,\n        0\n      ],\n      \"to\": [\n        16,\n        5,\n        16\n      ],\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            11,\n            16,\n            16\n          ],\n          \"texture\": \"#side\"\n        },\n        \"east\": {\n          \"uv\": [\n            0,\n            11,\n            16,\n            16\n          ],\n          \"texture\": \"#side\"\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            11,\n            16,\n            16\n          ],\n          \"texture\": \"#side\"\n        },\n        \"west\": {\n          \"uv\": [\n            0,\n            11,\n            16,\n            16\n          ],\n          \"texture\": \"#side\"\n        },\n        \"up\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#top\"\n        },\n        \"down\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#bottom\"\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/disk_drive.json",
    "content": "{\n  \"loader\": \"refinedstorage:disk_drive\"\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/disk_drive_base.json",
    "content": "{\n  \"parent\": \"block/block\",\n  \"textures\": {\n    \"particle\": \"refinedstorage:block/disk_drive\",\n    \"front\": \"refinedstorage:block/disk_drive\",\n    \"bottom\": \"refinedstorage:block/disk_drive_bottom\",\n    \"top\": \"refinedstorage:block/disk_drive_top\",\n    \"side\": \"refinedstorage:block/disk_drive_side\"\n  },\n  \"elements\": [\n    {\n      \"from\": [\n        0,\n        0,\n        0\n      ],\n      \"to\": [\n        16,\n        16,\n        16\n      ],\n      \"faces\": {\n        \"down\": {\n          \"texture\": \"#bottom\",\n          \"cullface\": \"down\"\n        },\n        \"up\": {\n          \"texture\": \"#top\",\n          \"cullface\": \"up\"\n        },\n        \"north\": {\n          \"texture\": \"#front\",\n          \"cullface\": \"north\"\n        },\n        \"south\": {\n          \"texture\": \"#side\",\n          \"cullface\": \"south\"\n        },\n        \"west\": {\n          \"texture\": \"#side\",\n          \"cullface\": \"west\"\n        },\n        \"east\": {\n          \"texture\": \"#side\",\n          \"cullface\": \"east\"\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/disks/disk.json",
    "content": "{\n  \"textures\": {\n    \"base\": \"refinedstorage:block/disks/disk\",\n    \"led\": \"refinedstorage:block/disks/leds\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"disk\",\n      \"from\": [\n        11.0,\n        14.0,\n        -1.0\n      ],\n      \"to\": [\n        16.0,\n        16.0,\n        0.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            3.0,\n            0.0,\n            8.0,\n            2.0\n          ]\n        },\n        \"east\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            2.0,\n            0.0,\n            3.0,\n            2.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            9.0,\n            0.0,\n            14.0,\n            2.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            8.0,\n            0.0,\n            9.0,\n            2.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            3.0,\n            2.0,\n            8.0,\n            3.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            3.0,\n            3.0,\n            8.0,\n            4.0\n          ]\n        }\n      }\n    },\n    {\n      \"name\": \"led\",\n      \"from\": [\n        12.0,\n        13.95,\n        -1.05\n      ],\n      \"to\": [\n        13.0,\n        15.0,\n        -0.10000000000000009\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            2.0,\n            0.0,\n            3.0,\n            1.0\n          ],\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"east\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            2.0,\n            0.0,\n            3.0,\n            1.0\n          ],\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"south\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            2.0,\n            0.0,\n            3.0,\n            1.0\n          ],\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"west\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            2.0,\n            0.0,\n            3.0,\n            1.0\n          ],\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"up\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            2.0,\n            0.0,\n            3.0,\n            1.0\n          ],\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"down\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            2.0,\n            0.0,\n            3.0,\n            1.0\n          ],\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/disks/disk_disconnected.json",
    "content": "{\n  \"__comment\": \"Model generated using MrCrayfish's Model Creator (http://mrcrayfish.com/modelcreator/)\",\n  \"textures\": {\n    \"base\": \"refinedstorage:block/disks/disk\",\n    \"led\": \"refinedstorage:block/disks/leds\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"disk\",\n      \"from\": [\n        11.0,\n        14.0,\n        -1.0\n      ],\n      \"to\": [\n        16.0,\n        16.0,\n        0.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            3.0,\n            0.0,\n            8.0,\n            2.0\n          ]\n        },\n        \"east\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            2.0,\n            0.0,\n            3.0,\n            2.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            9.0,\n            0.0,\n            14.0,\n            2.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            8.0,\n            0.0,\n            9.0,\n            2.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            3.0,\n            2.0,\n            8.0,\n            3.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            3.0,\n            3.0,\n            8.0,\n            4.0\n          ]\n        }\n      }\n    },\n    {\n      \"name\": \"led\",\n      \"from\": [\n        12.0,\n        13.95,\n        -1.05\n      ],\n      \"to\": [\n        13.0,\n        15.0,\n        -0.10000000000000009\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            3.0,\n            0.0,\n            4.0,\n            1.0\n          ]\n        },\n        \"east\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            3.0,\n            0.0,\n            4.0,\n            1.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            3.0,\n            0.0,\n            4.0,\n            1.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            3.0,\n            0.0,\n            4.0,\n            1.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            3.0,\n            0.0,\n            4.0,\n            1.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            3.0,\n            0.0,\n            4.0,\n            1.0\n          ]\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/disks/disk_full.json",
    "content": "{\n  \"__comment\": \"Model generated using MrCrayfish's Model Creator (http://mrcrayfish.com/modelcreator/)\",\n  \"textures\": {\n    \"base\": \"refinedstorage:block/disks/disk\",\n    \"led\": \"refinedstorage:block/disks/leds\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"disk\",\n      \"from\": [\n        11.0,\n        14.0,\n        -1.0\n      ],\n      \"to\": [\n        16.0,\n        16.0,\n        0.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            3.0,\n            0.0,\n            8.0,\n            2.0\n          ]\n        },\n        \"east\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            2.0,\n            0.0,\n            3.0,\n            2.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            9.0,\n            0.0,\n            14.0,\n            2.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            8.0,\n            0.0,\n            9.0,\n            2.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            3.0,\n            2.0,\n            8.0,\n            3.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            3.0,\n            3.0,\n            8.0,\n            4.0\n          ]\n        }\n      }\n    },\n    {\n      \"name\": \"led\",\n      \"from\": [\n        12.0,\n        13.95,\n        -1.05\n      ],\n      \"to\": [\n        13.0,\n        15.0,\n        -0.10000000000000009\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            1.0,\n            0.0,\n            2.0,\n            1.0\n          ],\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"east\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            1.0,\n            0.0,\n            2.0,\n            1.0\n          ],\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"south\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            1.0,\n            0.0,\n            2.0,\n            1.0\n          ],\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"west\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            1.0,\n            0.0,\n            2.0,\n            1.0\n          ],\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"up\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            1.0,\n            0.0,\n            2.0,\n            1.0\n          ],\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"down\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            1.0,\n            0.0,\n            2.0,\n            1.0\n          ],\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/disks/disk_near_capacity.json",
    "content": "{\n  \"__comment\": \"Model generated using MrCrayfish's Model Creator (http://mrcrayfish.com/modelcreator/)\",\n  \"textures\": {\n    \"base\": \"refinedstorage:block/disks/disk\",\n    \"led\": \"refinedstorage:block/disks/leds\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"disk\",\n      \"from\": [\n        11.0,\n        14.0,\n        -1.0\n      ],\n      \"to\": [\n        16.0,\n        16.0,\n        0.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            3.0,\n            0.0,\n            8.0,\n            2.0\n          ]\n        },\n        \"east\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            2.0,\n            0.0,\n            3.0,\n            2.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            9.0,\n            0.0,\n            14.0,\n            2.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            8.0,\n            0.0,\n            9.0,\n            2.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            3.0,\n            2.0,\n            8.0,\n            3.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#base\",\n          \"uv\": [\n            3.0,\n            3.0,\n            8.0,\n            4.0\n          ]\n        }\n      }\n    },\n    {\n      \"name\": \"led\",\n      \"from\": [\n        12.0,\n        13.95,\n        -1.05\n      ],\n      \"to\": [\n        13.0,\n        15.0,\n        -0.10000000000000009\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            0.0,\n            0.0,\n            1.0,\n            1.0\n          ],\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"east\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            0.0,\n            0.0,\n            1.0,\n            1.0\n          ],\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"south\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            0.0,\n            0.0,\n            1.0,\n            1.0\n          ],\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"west\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            0.0,\n            0.0,\n            1.0,\n            1.0\n          ],\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"up\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            0.0,\n            0.0,\n            1.0,\n            1.0\n          ],\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"down\": {\n          \"texture\": \"#led\",\n          \"uv\": [\n            0.0,\n            0.0,\n            1.0,\n            1.0\n          ],\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/disks/portable_grid_disk.json",
    "content": "{\n  \"textures\": {\n    \"disk\": \"refinedstorage:block/disks/portable_grid_disk\",\n    \"led\": \"refinedstorage:block/disks/leds\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"disk\",\n      \"from\": [\n        -1,\n        2,\n        9\n      ],\n      \"to\": [\n        0,\n        4,\n        14\n      ],\n      \"shade\": true,\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            5,\n            5,\n            6,\n            7\n          ],\n          \"texture\": \"#disk\"\n        },\n        \"east\": {\n          \"uv\": [\n            0,\n            5,\n            5,\n            7\n          ],\n          \"texture\": \"#disk\"\n        },\n        \"south\": {\n          \"uv\": [\n            11,\n            5,\n            12,\n            7\n          ],\n          \"texture\": \"#disk\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            5,\n            11,\n            7\n          ],\n          \"texture\": \"#disk\"\n        },\n        \"up\": {\n          \"uv\": [\n            5,\n            0,\n            6,\n            5\n          ],\n          \"texture\": \"#disk\",\n          \"rotation\": 180\n        },\n        \"down\": {\n          \"uv\": [\n            6,\n            0,\n            7,\n            5\n          ],\n          \"texture\": \"#disk\",\n          \"rotation\": 180\n        }\n      }\n    },\n    {\n      \"name\": \"disk_led\",\n      \"from\": [\n        -1.05,\n        2,\n        12\n      ],\n      \"to\": [\n        -0.050000000000000044,\n        3,\n        13\n      ],\n      \"shade\": true,\n      \"faces\": {\n        \"east\": {\n          \"uv\": [\n            2,\n            0,\n            3,\n            1\n          ],\n          \"texture\": \"#led\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"west\": {\n          \"uv\": [\n            2,\n            0,\n            3,\n            1\n          ],\n          \"texture\": \"#led\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"north\": {\n          \"uv\": [\n            2,\n            0,\n            3,\n            1\n          ],\n          \"texture\": \"#led\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"south\": {\n          \"uv\": [\n            2,\n            0,\n            3,\n            1\n          ],\n          \"texture\": \"#led\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"up\": {\n          \"uv\": [\n            2,\n            0,\n            3,\n            1\n          ],\n          \"texture\": \"#led\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"down\": {\n          \"uv\": [\n            2,\n            0,\n            3,\n            1\n          ],\n          \"texture\": \"#led\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/disks/portable_grid_disk_disconnected.json",
    "content": "{\n  \"textures\": {\n    \"disk\": \"refinedstorage:block/disks/portable_grid_disk\",\n    \"led\": \"refinedstorage:block/disks/portable_grid_leds\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"disk\",\n      \"from\": [\n        -1,\n        2,\n        9\n      ],\n      \"to\": [\n        0,\n        4,\n        14\n      ],\n      \"shade\": true,\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            5,\n            5,\n            6,\n            7\n          ],\n          \"texture\": \"#disk\"\n        },\n        \"east\": {\n          \"uv\": [\n            0,\n            5,\n            5,\n            7\n          ],\n          \"texture\": \"#disk\"\n        },\n        \"south\": {\n          \"uv\": [\n            11,\n            5,\n            12,\n            7\n          ],\n          \"texture\": \"#disk\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            5,\n            11,\n            7\n          ],\n          \"texture\": \"#disk\"\n        },\n        \"up\": {\n          \"uv\": [\n            5,\n            0,\n            6,\n            5\n          ],\n          \"texture\": \"#disk\",\n          \"rotation\": 180\n        },\n        \"down\": {\n          \"uv\": [\n            6,\n            0,\n            7,\n            5\n          ],\n          \"texture\": \"#disk\",\n          \"rotation\": 180\n        }\n      }\n    },\n    {\n      \"name\": \"disk_led\",\n      \"from\": [\n        -1.05,\n        2,\n        12\n      ],\n      \"to\": [\n        -0.050000000000000044,\n        3,\n        13\n      ],\n      \"shade\": true,\n      \"faces\": {\n        \"east\": {\n          \"uv\": [\n            3,\n            0,\n            4,\n            1\n          ],\n          \"texture\": \"#led\"\n        },\n        \"west\": {\n          \"uv\": [\n            3,\n            0,\n            4,\n            1\n          ],\n          \"texture\": \"#led\"\n        },\n        \"north\": {\n          \"uv\": [\n            3,\n            0,\n            4,\n            1\n          ],\n          \"texture\": \"#led\"\n        },\n        \"south\": {\n          \"uv\": [\n            3,\n            0,\n            4,\n            1\n          ],\n          \"texture\": \"#led\"\n        },\n        \"up\": {\n          \"uv\": [\n            3,\n            0,\n            4,\n            1\n          ],\n          \"texture\": \"#led\"\n        },\n        \"down\": {\n          \"uv\": [\n            3,\n            0,\n            4,\n            1\n          ],\n          \"texture\": \"#led\"\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/disks/portable_grid_disk_full.json",
    "content": "{\n  \"textures\": {\n    \"disk\": \"refinedstorage:block/disks/portable_grid_disk\",\n    \"led\": \"refinedstorage:block/disks/leds\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"disk\",\n      \"from\": [\n        -1,\n        2,\n        9\n      ],\n      \"to\": [\n        0,\n        4,\n        14\n      ],\n      \"shade\": true,\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            5,\n            5,\n            6,\n            7\n          ],\n          \"texture\": \"#disk\"\n        },\n        \"east\": {\n          \"uv\": [\n            0,\n            5,\n            5,\n            7\n          ],\n          \"texture\": \"#disk\"\n        },\n        \"south\": {\n          \"uv\": [\n            11,\n            5,\n            12,\n            7\n          ],\n          \"texture\": \"#disk\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            5,\n            11,\n            7\n          ],\n          \"texture\": \"#disk\"\n        },\n        \"up\": {\n          \"uv\": [\n            5,\n            0,\n            6,\n            5\n          ],\n          \"texture\": \"#disk\",\n          \"rotation\": 180\n        },\n        \"down\": {\n          \"uv\": [\n            6,\n            0,\n            7,\n            5\n          ],\n          \"texture\": \"#disk\",\n          \"rotation\": 180\n        }\n      }\n    },\n    {\n      \"name\": \"disk_led\",\n      \"from\": [\n        -1.05,\n        2,\n        12\n      ],\n      \"to\": [\n        -0.050000000000000044,\n        3,\n        13\n      ],\n      \"shade\": true,\n      \"faces\": {\n        \"east\": {\n          \"uv\": [\n            1,\n            0,\n            2,\n            1\n          ],\n          \"texture\": \"#led\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"west\": {\n          \"uv\": [\n            1,\n            0,\n            2,\n            1\n          ],\n          \"texture\": \"#led\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"north\": {\n          \"uv\": [\n            1,\n            0,\n            2,\n            1\n          ],\n          \"texture\": \"#led\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"south\": {\n          \"uv\": [\n            1,\n            0,\n            2,\n            1\n          ],\n          \"texture\": \"#led\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"up\": {\n          \"uv\": [\n            1,\n            0,\n            2,\n            1\n          ],\n          \"texture\": \"#led\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"down\": {\n          \"uv\": [\n            1,\n            0,\n            2,\n            1\n          ],\n          \"texture\": \"#led\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/disks/portable_grid_disk_near_capacity.json",
    "content": "{\n  \"textures\": {\n    \"disk\": \"refinedstorage:block/disks/portable_grid_disk\",\n    \"led\": \"refinedstorage:block/disks/leds\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"disk\",\n      \"from\": [\n        -1,\n        2,\n        9\n      ],\n      \"to\": [\n        0,\n        4,\n        14\n      ],\n      \"shade\": true,\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            5,\n            5,\n            6,\n            7\n          ],\n          \"texture\": \"#disk\"\n        },\n        \"east\": {\n          \"uv\": [\n            0,\n            5,\n            5,\n            7\n          ],\n          \"texture\": \"#disk\"\n        },\n        \"south\": {\n          \"uv\": [\n            11,\n            5,\n            12,\n            7\n          ],\n          \"texture\": \"#disk\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            5,\n            11,\n            7\n          ],\n          \"texture\": \"#disk\"\n        },\n        \"up\": {\n          \"uv\": [\n            5,\n            0,\n            6,\n            5\n          ],\n          \"texture\": \"#disk\",\n          \"rotation\": 180\n        },\n        \"down\": {\n          \"uv\": [\n            6,\n            0,\n            7,\n            5\n          ],\n          \"texture\": \"#disk\",\n          \"rotation\": 180\n        }\n      }\n    },\n    {\n      \"name\": \"disk_led\",\n      \"from\": [\n        -1.05,\n        2,\n        12\n      ],\n      \"to\": [\n        -0.050000000000000044,\n        3,\n        13\n      ],\n      \"shade\": true,\n      \"faces\": {\n        \"east\": {\n          \"uv\": [\n            0,\n            0,\n            1,\n            1\n          ],\n          \"texture\": \"#led\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"west\": {\n          \"uv\": [\n            0,\n            0,\n            1,\n            1\n          ],\n          \"texture\": \"#led\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"north\": {\n          \"uv\": [\n            0,\n            0,\n            1,\n            1\n          ],\n          \"texture\": \"#led\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            0,\n            1,\n            1\n          ],\n          \"texture\": \"#led\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"up\": {\n          \"uv\": [\n            0,\n            0,\n            1,\n            1\n          ],\n          \"texture\": \"#led\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"down\": {\n          \"uv\": [\n            0,\n            0,\n            1,\n            1\n          ],\n          \"texture\": \"#led\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/exporter.json",
    "content": "{\n  \"render_type\": \"cutout\",\n  \"textures\": {\n    \"border\": \"refinedstorage:block/cable_part_border\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"Line1\",\n      \"from\": [\n        6,\n        6,\n        0\n      ],\n      \"to\": [\n        10,\n        10,\n        2\n      ],\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            0,\n            4,\n            4\n          ],\n          \"texture\": \"#border\"\n        },\n        \"east\": {\n          \"uv\": [\n            0,\n            0,\n            2,\n            4\n          ],\n          \"texture\": \"#border\"\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            0,\n            4,\n            4\n          ],\n          \"texture\": \"#border\"\n        },\n        \"west\": {\n          \"uv\": [\n            0,\n            0,\n            2,\n            4\n          ],\n          \"texture\": \"#border\"\n        },\n        \"up\": {\n          \"uv\": [\n            0,\n            0,\n            4,\n            2\n          ],\n          \"texture\": \"#border\"\n        },\n        \"down\": {\n          \"uv\": [\n            0,\n            0,\n            4,\n            2\n          ],\n          \"texture\": \"#border\"\n        }\n      }\n    },\n    {\n      \"name\": \"Line2\",\n      \"from\": [\n        5,\n        5,\n        2\n      ],\n      \"to\": [\n        11,\n        11,\n        4\n      ],\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            0,\n            6,\n            6\n          ],\n          \"texture\": \"#border\"\n        },\n        \"east\": {\n          \"uv\": [\n            0,\n            0,\n            2,\n            6\n          ],\n          \"texture\": \"#border\"\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            0,\n            6,\n            6\n          ],\n          \"texture\": \"#border\"\n        },\n        \"west\": {\n          \"uv\": [\n            0,\n            0,\n            2,\n            6\n          ],\n          \"texture\": \"#border\"\n        },\n        \"up\": {\n          \"uv\": [\n            0,\n            0,\n            6,\n            2\n          ],\n          \"texture\": \"#border\"\n        },\n        \"down\": {\n          \"uv\": [\n            0,\n            0,\n            6,\n            2\n          ],\n          \"texture\": \"#border\"\n        }\n      }\n    },\n    {\n      \"name\": \"Line3\",\n      \"from\": [\n        3,\n        3,\n        4\n      ],\n      \"to\": [\n        13,\n        13,\n        6\n      ],\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            0,\n            10,\n            10\n          ],\n          \"texture\": \"#border\"\n        },\n        \"east\": {\n          \"uv\": [\n            0,\n            0,\n            2,\n            10\n          ],\n          \"texture\": \"#border\"\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            0,\n            10,\n            10\n          ],\n          \"texture\": \"#border\"\n        },\n        \"west\": {\n          \"uv\": [\n            0,\n            0,\n            2,\n            10\n          ],\n          \"texture\": \"#border\"\n        },\n        \"up\": {\n          \"uv\": [\n            0,\n            0,\n            10,\n            2\n          ],\n          \"texture\": \"#border\"\n        },\n        \"down\": {\n          \"uv\": [\n            0,\n            0,\n            10,\n            2\n          ],\n          \"texture\": \"#border\"\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/external_storage.json",
    "content": "{\n  \"render_type\": \"cutout\",\n  \"__comment\": \"Model generated using MrCrayfish's Model Creator (http://mrcrayfish.com/modelcreator/)\",\n  \"textures\": {\n    \"border\": \"refinedstorage:block/cable_part_border\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"Line1\",\n      \"from\": [\n        7.0,\n        7.0,\n        2.0\n      ],\n      \"to\": [\n        9.0,\n        9.0,\n        6.0\n      ],\n      \"faces\": {\n        \"east\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            2.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            4.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            2.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            4.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            4.0\n          ]\n        }\n      }\n    },\n    {\n      \"name\": \"Line2\",\n      \"from\": [\n        3.0,\n        3.0,\n        0.0\n      ],\n      \"to\": [\n        13.0,\n        13.0,\n        2.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            10.0,\n            10.0\n          ]\n        },\n        \"east\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            10.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            10.0,\n            10.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            10.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            10.0,\n            2.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            10.0,\n            2.0\n          ]\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/fluid_interface_connected.json",
    "content": "{\n  \"parent\": \"block/cube_all\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/fluid_interface_connected\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/fluid_interface_disconnected.json",
    "content": "{\n  \"parent\": \"block/cube_all\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/fluid_interface_disconnected\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/importer.json",
    "content": "{\n  \"render_type\": \"cutout\",\n  \"__comment\": \"Model generated using MrCrayfish's Model Creator (http://mrcrayfish.com/modelcreator/)\",\n  \"textures\": {\n    \"border\": \"refinedstorage:block/cable_part_border\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"Line1\",\n      \"from\": [\n        6.0,\n        6.0,\n        4.0\n      ],\n      \"to\": [\n        10.0,\n        10.0,\n        6.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            4.0\n          ]\n        },\n        \"east\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            4.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            4.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            4.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            2.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            2.0\n          ]\n        }\n      }\n    },\n    {\n      \"name\": \"Line2\",\n      \"from\": [\n        5.0,\n        5.0,\n        2.0\n      ],\n      \"to\": [\n        11.0,\n        11.0,\n        4.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            6.0,\n            6.0\n          ]\n        },\n        \"east\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            6.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            6.0,\n            6.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            6.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            6.0,\n            2.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            6.0,\n            2.0\n          ]\n        }\n      }\n    },\n    {\n      \"name\": \"Line3\",\n      \"from\": [\n        3.0,\n        3.0,\n        0.0\n      ],\n      \"to\": [\n        13.0,\n        13.0,\n        2.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            10.0,\n            10.0\n          ]\n        },\n        \"east\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            10.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            10.0,\n            10.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            10.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            10.0,\n            2.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            10.0,\n            2.0\n          ]\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/interface_connected.json",
    "content": "{\n  \"parent\": \"block/cube_all\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/interface_connected\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/interface_disconnected.json",
    "content": "{\n  \"parent\": \"block/cube_all\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/interface_disconnected\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/machine_casing.json",
    "content": "{\n  \"parent\": \"block/cube_all\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/machine_casing\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/portable_grid.json",
    "content": "{\n  \"render_type\": \"cutout\",\n  \"loader\": \"refinedstorage:portable_grid\"\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/portable_grid_base.json",
    "content": "{\n  \"render_type\": \"cutout\",\n  \"parent\": \"block/cube\",\n  \"textures\": {\n    \"particle\": \"refinedstorage:block/portable_grid_1\",\n    \"texture0\": \"refinedstorage:block/portable_grid_1\",\n    \"texture2\": \"refinedstorage:block/portable_grid_3\",\n    \"texture3\": \"refinedstorage:block/portable_grid_4\",\n    \"texture4\": \"refinedstorage:block/portable_grid_5\",\n    \"texture5\": \"refinedstorage:block/portable_grid_6\",\n    \"texture6\": \"refinedstorage:block/portable_grid_7\",\n    \"texture7\": \"refinedstorage:block/portable_grid_8\"\n  },\n  \"display\": {\n    \"firstperson_lefthand\": {\n      \"rotation\": [10, 130, 0],\n      \"scale\": [0.4, 0.4, 0.4],\n      \"translation\": [2, 3.5, 0]\n    },\n    \"firstperson_righthand\": {\n      \"rotation\": [10, 130, 0],\n      \"scale\": [0.4, 0.4, 0.4],\n      \"translation\": [2, 3.5, 0]\n    },\n    \"thirdperson_lefthand\": {\n      \"rotation\": [10, 180, 0],\n      \"scale\": [0.4, 0.4, 0.4],\n      \"translation\": [0, 3, 1]\n    },\n    \"thirdperson_righthand\": {\n      \"rotation\": [10, 180, 0],\n      \"scale\": [0.4, 0.4, 0.4],\n      \"translation\": [0, 3, 1]\n    },\n    \"gui\": {\n      \"rotation\": [30, 225, 0],\n      \"scale\": [0.625, 0.625, 0.625]\n    },\n    \"ground\": {\n      \"translation\": [0, 3, 0],\n      \"scale\": [0.25, 0.25, 0.25]\n    },\n    \"fixed\": {\n      \"scale\": [0.75, 0.75, 0.75]\n    }\n  },\n  \"elements\": [\n    {\n      \"name\": \"cube\",\n      \"from\": [\n        0,\n        6,\n        5\n      ],\n      \"to\": [\n        16,\n        13,\n        7\n      ],\n      \"shade\": true,\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            7,\n            16,\n            14\n          ],\n          \"texture\": \"#texture0\"\n        },\n        \"east\": {\n          \"uv\": [\n            0,\n            7,\n            2,\n            14\n          ],\n          \"texture\": \"#texture1\"\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            7\n          ],\n          \"texture\": \"#texture0\"\n        },\n        \"west\": {\n          \"uv\": [\n            0,\n            0,\n            2,\n            7\n          ],\n          \"texture\": \"#texture1\"\n        },\n        \"up\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            2\n          ],\n          \"texture\": \"#texture0\",\n          \"rotation\": 180\n        },\n        \"down\": {\n          \"uv\": [\n            0,\n            13,\n            16,\n            15\n          ],\n          \"texture\": \"#texture1\",\n          \"rotation\": 180\n        }\n      },\n      \"rotation\": {\n        \"origin\": [\n          8,\n          6,\n          7\n        ],\n        \"axis\": \"x\",\n        \"angle\": 22.5\n      }\n    },\n    {\n      \"name\": \"cube\",\n      \"from\": [\n        0,\n        4,\n        7\n      ],\n      \"to\": [\n        16,\n        6,\n        16\n      ],\n      \"shade\": true,\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            14,\n            16,\n            16\n          ],\n          \"texture\": \"#texture0\"\n        },\n        \"east\": {\n          \"uv\": [\n            3,\n            2,\n            12,\n            4\n          ],\n          \"texture\": \"#texture1\"\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            2\n          ],\n          \"texture\": \"#texture2\"\n        },\n        \"west\": {\n          \"uv\": [\n            3,\n            0,\n            12,\n            2\n          ],\n          \"texture\": \"#texture1\"\n        },\n        \"up\": {\n          \"uv\": [\n            0,\n            2,\n            16,\n            11\n          ],\n          \"texture\": \"#texture2\",\n          \"rotation\": 180\n        },\n        \"down\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            9\n          ],\n          \"texture\": \"#texture3\",\n          \"rotation\": 180\n        }\n      }\n    },\n    {\n      \"name\": \"cube\",\n      \"from\": [\n        0,\n        0,\n        0\n      ],\n      \"to\": [\n        16,\n        4,\n        16\n      ],\n      \"shade\": true,\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            9,\n            16,\n            13\n          ],\n          \"texture\": \"#texture3\"\n        },\n        \"east\": {\n          \"uv\": [\n            0,\n            4,\n            16,\n            8\n          ],\n          \"texture\": \"#texture4\"\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            11,\n            16,\n            15\n          ],\n          \"texture\": \"#texture2\"\n        },\n        \"west\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            4\n          ],\n          \"texture\": \"#texture4\"\n        },\n        \"up\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#texture5\",\n          \"rotation\": 180\n        },\n        \"down\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#texture6\",\n          \"rotation\": 180\n        }\n      }\n    },\n    {\n      \"name\": \"cube\",\n      \"from\": [\n        1,\n        4,\n        1\n      ],\n      \"to\": [\n        15,\n        5,\n        7\n      ],\n      \"shade\": true,\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            15,\n            14,\n            16\n          ],\n          \"texture\": \"#texture2\"\n        },\n        \"east\": {\n          \"uv\": [\n            4,\n            9,\n            10,\n            10\n          ],\n          \"texture\": \"#texture1\"\n        },\n        \"south\": {\n          \"uv\": [\n            2,\n            13,\n            16,\n            14\n          ],\n          \"texture\": \"#texture1\"\n        },\n        \"west\": {\n          \"uv\": [\n            4,\n            8,\n            10,\n            9\n          ],\n          \"texture\": \"#texture1\"\n        },\n        \"up\": {\n          \"uv\": [\n            0,\n            8,\n            14,\n            14\n          ],\n          \"texture\": \"#texture4\",\n          \"rotation\": 180\n        },\n        \"down\": {\n          \"uv\": [\n            0,\n            0,\n            14,\n            6\n          ],\n          \"texture\": \"#texture7\",\n          \"rotation\": 180\n        }\n      }\n    },\n    {\n      \"name\": \"cube\",\n      \"from\": [\n        3,\n        4.5,\n        6\n      ],\n      \"to\": [\n        4,\n        6.5,\n        8\n      ],\n      \"shade\": true,\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            5,\n            10,\n            6,\n            12\n          ],\n          \"texture\": \"#texture1\"\n        },\n        \"east\": {\n          \"uv\": [\n            7,\n            4,\n            9,\n            6\n          ],\n          \"texture\": \"#texture1\"\n        },\n        \"south\": {\n          \"uv\": [\n            4,\n            10,\n            5,\n            12\n          ],\n          \"texture\": \"#texture1\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            10,\n            8,\n            12\n          ],\n          \"texture\": \"#texture1\"\n        },\n        \"up\": {\n          \"uv\": [\n            7,\n            6,\n            8,\n            8\n          ],\n          \"texture\": \"#texture1\",\n          \"rotation\": 180\n        },\n        \"down\": {\n          \"uv\": [\n            8,\n            6,\n            9,\n            8\n          ],\n          \"texture\": \"#texture1\",\n          \"rotation\": 180\n        }\n      }\n    },\n    {\n      \"name\": \"cube\",\n      \"from\": [\n        12,\n        4.5,\n        6\n      ],\n      \"to\": [\n        13,\n        6.5,\n        8\n      ],\n      \"shade\": true,\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            9,\n            4,\n            10,\n            6\n          ],\n          \"texture\": \"#texture1\"\n        },\n        \"east\": {\n          \"uv\": [\n            9,\n            10,\n            11,\n            12\n          ],\n          \"texture\": \"#texture1\"\n        },\n        \"south\": {\n          \"uv\": [\n            8,\n            10,\n            9,\n            12\n          ],\n          \"texture\": \"#texture1\"\n        },\n        \"west\": {\n          \"uv\": [\n            9,\n            6,\n            11,\n            8\n          ],\n          \"texture\": \"#texture1\"\n        },\n        \"up\": {\n          \"uv\": [\n            7,\n            6,\n            8,\n            8\n          ],\n          \"texture\": \"#texture1\",\n          \"rotation\": 180\n        },\n        \"down\": {\n          \"uv\": [\n            8,\n            6,\n            9,\n            8\n          ],\n          \"texture\": \"#texture1\",\n          \"rotation\": 180\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/portable_grid_connected.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/portable_grid_base\",\n  \"textures\": {\n    \"texture1\": \"refinedstorage:block/portable_grid_2\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/portable_grid_disconnected.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/portable_grid_base\",\n  \"textures\": {\n    \"texture1\": \"refinedstorage:block/portable_grid_2_disconnected\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/quartz_enriched_iron_block.json",
    "content": "{\n  \"parent\": \"block/cube_all\",\n  \"textures\": {\n    \"all\": \"refinedstorage:block/quartz_enriched_iron_block\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/storage_monitor.json",
    "content": "{\n  \"parent\": \"block/cube\",\n  \"textures\": {\n    \"particle\": \"refinedstorage:block/side\",\n    \"north\": \"refinedstorage:block/storage_monitor_front\",\n    \"east\": \"refinedstorage:block/storage_monitor_left\",\n    \"south\": \"refinedstorage:block/storage_monitor_back\",\n    \"west\": \"refinedstorage:block/storage_monitor_right\",\n    \"up\": \"refinedstorage:block/storage_monitor_top\",\n    \"down\": \"refinedstorage:block/bottom\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/wireless_transmitter.json",
    "content": "{\n  \"render_type\": \"cutout\",\n  \"parent\": \"block/cube\",\n  \"ambientocclusion\": false,\n  \"textures\": {\n    \"particle\": \"refinedstorage:block/wireless_transmitter/wireless_transmitter\",\n    \"torch\": \"refinedstorage:block/wireless_transmitter/wireless_transmitter\"\n  },\n  \"elements\": [\n    {\n      \"from\": [\n        7,\n        0,\n        7\n      ],\n      \"to\": [\n        9,\n        10,\n        9\n      ],\n      \"shade\": false,\n      \"faces\": {\n        \"down\": {\n          \"uv\": [\n            7,\n            13,\n            9,\n            15\n          ],\n          \"texture\": \"#torch\"\n        },\n        \"up\": {\n          \"uv\": [\n            7,\n            6,\n            9,\n            8\n          ],\n          \"texture\": \"#torch\"\n        }\n      }\n    },\n    {\n      \"from\": [\n        7,\n        0,\n        0\n      ],\n      \"to\": [\n        9,\n        16,\n        16\n      ],\n      \"shade\": false,\n      \"faces\": {\n        \"west\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#torch\"\n        },\n        \"east\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#torch\"\n        }\n      }\n    },\n    {\n      \"from\": [\n        0,\n        0,\n        7\n      ],\n      \"to\": [\n        16,\n        16,\n        9\n      ],\n      \"shade\": false,\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#torch\"\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#torch\"\n        }\n      }\n    },\n    {\n      \"from\": [\n        7,\n        0,\n        7\n      ],\n      \"to\": [\n        9,\n        10,\n        9\n      ],\n      \"shade\": false,\n      \"faces\": {\n        \"down\": {\n          \"uv\": [\n            7,\n            13,\n            9,\n            15\n          ],\n          \"texture\": \"#cutout\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"up\": {\n          \"uv\": [\n            7,\n            6,\n            9,\n            8\n          ],\n          \"texture\": \"#cutout\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        }\n      }\n    },\n    {\n      \"from\": [\n        7,\n        0,\n        0\n      ],\n      \"to\": [\n        9,\n        16,\n        16\n      ],\n      \"shade\": false,\n      \"faces\": {\n        \"west\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#cutout\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"east\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#cutout\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        }\n      }\n    },\n    {\n      \"from\": [\n        0,\n        0,\n        7\n      ],\n      \"to\": [\n        16,\n        16,\n        9\n      ],\n      \"shade\": false,\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#cutout\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#cutout\",\n          \"neoforge_data\": {\n            \"block_light\": 15,\n            \"sky_light\": 15\n          }\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/block/wireless_transmitter_nonemissive.json",
    "content": "{\n  \"render_type\": \"cutout\",\n  \"parent\": \"block/cube\",\n  \"ambientocclusion\": false,\n  \"textures\": {\n    \"particle\": \"refinedstorage:block/wireless_transmitter/wireless_transmitter\",\n    \"torch\": \"refinedstorage:block/wireless_transmitter/wireless_transmitter\"\n  },\n  \"elements\": [\n    {\n      \"from\": [\n        7,\n        0,\n        7\n      ],\n      \"to\": [\n        9,\n        10,\n        9\n      ],\n      \"shade\": false,\n      \"faces\": {\n        \"down\": {\n          \"uv\": [\n            7,\n            13,\n            9,\n            15\n          ],\n          \"texture\": \"#torch\"\n        },\n        \"up\": {\n          \"uv\": [\n            7,\n            6,\n            9,\n            8\n          ],\n          \"texture\": \"#torch\"\n        }\n      }\n    },\n    {\n      \"from\": [\n        7,\n        0,\n        0\n      ],\n      \"to\": [\n        9,\n        16,\n        16\n      ],\n      \"shade\": false,\n      \"faces\": {\n        \"west\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#torch\"\n        },\n        \"east\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#torch\"\n        }\n      }\n    },\n    {\n      \"from\": [\n        0,\n        0,\n        7\n      ],\n      \"to\": [\n        16,\n        16,\n        9\n      ],\n      \"shade\": false,\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#torch\"\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#torch\"\n        }\n      }\n    },\n    {\n      \"from\": [\n        7,\n        0,\n        7\n      ],\n      \"to\": [\n        9,\n        10,\n        9\n      ],\n      \"shade\": false,\n      \"faces\": {\n        \"down\": {\n          \"uv\": [\n            7,\n            13,\n            9,\n            15\n          ],\n          \"texture\": \"#cutout\"\n        },\n        \"up\": {\n          \"uv\": [\n            7,\n            6,\n            9,\n            8\n          ],\n          \"texture\": \"#cutout\"\n        }\n      }\n    },\n    {\n      \"from\": [\n        7,\n        0,\n        0\n      ],\n      \"to\": [\n        9,\n        16,\n        16\n      ],\n      \"shade\": false,\n      \"faces\": {\n        \"west\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#cutout\"\n        },\n        \"east\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#cutout\"\n        }\n      }\n    },\n    {\n      \"from\": [\n        0,\n        0,\n        7\n      ],\n      \"to\": [\n        16,\n        16,\n        9\n      ],\n      \"shade\": false,\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#cutout\"\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            0,\n            16,\n            16\n          ],\n          \"texture\": \"#cutout\"\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/1024k_fluid_storage_block.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/1024k_fluid_storage_block\"\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/1024k_fluid_storage_disk.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/1024k_fluid_storage_disk\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/1024k_fluid_storage_part.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/1024k_fluid_storage_part\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/16k_storage_block.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/16k_storage_block\"\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/16k_storage_disk.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/16k_storage_disk\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/16k_storage_part.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/16k_storage_part\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/1k_storage_block.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/1k_storage_block\"\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/1k_storage_disk.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/1k_storage_disk\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/1k_storage_part.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/1k_storage_part\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/256k_fluid_storage_block.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/256k_fluid_storage_block\"\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/256k_fluid_storage_disk.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/256k_fluid_storage_disk\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/256k_fluid_storage_part.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/256k_fluid_storage_part\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/4096k_fluid_storage_block.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/4096k_fluid_storage_block\"\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/4096k_fluid_storage_disk.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/4096k_fluid_storage_disk\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/4096k_fluid_storage_part.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/4096k_fluid_storage_part\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/4k_storage_block.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/4k_storage_block\"\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/4k_storage_disk.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/4k_storage_disk\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/4k_storage_part.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/4k_storage_part\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/64k_fluid_storage_block.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/64k_fluid_storage_block\"\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/64k_fluid_storage_disk.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/64k_fluid_storage_disk\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/64k_fluid_storage_part.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/64k_fluid_storage_part\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/64k_storage_block.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/64k_storage_block\"\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/64k_storage_disk.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/64k_storage_disk\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/64k_storage_part.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/64k_storage_part\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/advanced_processor.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/advanced_processor\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/basic_processor.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/basic_processor\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/cable.json",
    "content": "{\n  \"parent\": \"block/block\",\n  \"textures\": {\n    \"cable\": \"refinedstorage:block/cable\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"Core\",\n      \"from\": [\n        6,\n        6,\n        6\n      ],\n      \"to\": [\n        10,\n        10,\n        10\n      ],\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"east\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"south\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"up\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"down\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        }\n      }\n    },\n    {\n      \"name\": \"Part1\",\n      \"from\": [\n        10,\n        6,\n        6\n      ],\n      \"to\": [\n        16,\n        10,\n        10\n      ],\n      \"rotation\": {\n        \"angle\": 0,\n        \"axis\": \"y\",\n        \"origin\": [\n          16,\n          8,\n          9\n        ]\n      },\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"east\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"south\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"up\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"down\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        }\n      }\n    },\n    {\n      \"name\": \"Part2\",\n      \"from\": [\n        0,\n        6,\n        6\n      ],\n      \"to\": [\n        6,\n        10,\n        10\n      ],\n      \"rotation\": {\n        \"angle\": 0,\n        \"axis\": \"y\",\n        \"origin\": [\n          6,\n          8,\n          9\n        ]\n      },\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"east\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"up\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"down\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/construction_core.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/construction_core\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/constructor.json",
    "content": "{\n  \"parent\": \"block/block\",\n  \"textures\": {\n    \"cable\": \"refinedstorage:block/cable\",\n    \"front\": \"refinedstorage:block/constructor/constructor\",\n    \"cutout\": \"refinedstorage:block/constructor/cutouts/disconnected\",\n    \"border\": \"refinedstorage:block/cable_part_border\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"Core\",\n      \"from\": [\n        6,\n        6,\n        6\n      ],\n      \"to\": [\n        10,\n        10,\n        10\n      ],\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"east\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"south\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"up\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"down\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        }\n      }\n    },\n    {\n      \"name\": \"Part1\",\n      \"from\": [\n        10,\n        6,\n        6\n      ],\n      \"to\": [\n        16,\n        10,\n        10\n      ],\n      \"rotation\": {\n        \"angle\": 0,\n        \"axis\": \"y\",\n        \"origin\": [\n          16,\n          8,\n          9\n        ]\n      },\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"east\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"south\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"up\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"down\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        }\n      }\n    },\n    {\n      \"name\": \"Part2\",\n      \"from\": [\n        0,\n        6,\n        6\n      ],\n      \"to\": [\n        6,\n        10,\n        10\n      ],\n      \"rotation\": {\n        \"angle\": 0,\n        \"axis\": \"y\",\n        \"origin\": [\n          6,\n          8,\n          9\n        ]\n      },\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"east\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"up\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"down\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        }\n      }\n    },\n    {\n      \"name\": \"Line1\",\n      \"from\": [\n        7.0,\n        7.0,\n        2.0\n      ],\n      \"to\": [\n        9.0,\n        9.0,\n        6.0\n      ],\n      \"faces\": {\n        \"east\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            2.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            4.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            2.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            4.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            4.0\n          ]\n        }\n      }\n    },\n    {\n      \"name\": \"Line2\",\n      \"from\": [\n        2.0,\n        2.0,\n        0.0\n      ],\n      \"to\": [\n        14.0,\n        14.0,\n        2.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#front\",\n          \"uv\": [\n            0.0,\n            0.0,\n            16.0,\n            16.0\n          ]\n        },\n        \"east\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            14.0,\n            0.0,\n            16.0,\n            16.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            16.0,\n            16.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            16.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            2.0,\n            0.0,\n            14.0,\n            2.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            2.0,\n            14.0,\n            14.0,\n            16.0\n          ]\n        }\n      }\n    },\n    {\n      \"name\": \"Line3\",\n      \"from\": [\n        2.0,\n        2.0,\n        0.0\n      ],\n      \"to\": [\n        14.0,\n        14.0,\n        2.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#cutout\",\n          \"uv\": [\n            0.0,\n            0.0,\n            16.0,\n            16.0\n          ]\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/crafting_upgrade.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/crafting_upgrade\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/creative_fluid_storage_block.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/creative_fluid_storage_block\"\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/creative_fluid_storage_disk.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/creative_fluid_storage_disk\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/creative_portable_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/portable_grid\"\n}\n\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/creative_storage_block.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/creative_storage_block\"\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/creative_storage_disk.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/creative_storage_disk\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/creative_wireless_crafting_monitor.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/wireless_crafting_monitor_disconnected\"\n  },\n  \"overrides\": [\n    {\n      \"predicate\": {\n        \"refinedstorage:connected\": 0\n      },\n      \"model\": \"refinedstorage:item/wireless_crafting_monitor_disconnected\"\n    },\n    {\n      \"predicate\": {\n        \"refinedstorage:connected\": 1\n      },\n      \"model\": \"refinedstorage:item/wireless_crafting_monitor_connected\"\n    }\n  ]\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/creative_wireless_fluid_grid.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/wireless_fluid_grid_disconnected\"\n  },\n  \"overrides\": [\n    {\n      \"predicate\": {\n        \"refinedstorage:connected\": 0\n      },\n      \"model\": \"refinedstorage:item/wireless_fluid_grid_disconnected\"\n    },\n    {\n      \"predicate\": {\n        \"refinedstorage:connected\": 1\n      },\n      \"model\": \"refinedstorage:item/wireless_fluid_grid_connected\"\n    }\n  ]\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/creative_wireless_grid.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/wireless_grid_disconnected\"\n  },\n  \"overrides\": [\n    {\n      \"predicate\": {\n        \"refinedstorage:connected\": 0\n      },\n      \"model\": \"refinedstorage:item/wireless_grid_disconnected\"\n    },\n    {\n      \"predicate\": {\n        \"refinedstorage:connected\": 1\n      },\n      \"model\": \"refinedstorage:item/wireless_grid_connected\"\n    }\n  ]\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/destruction_core.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/destruction_core\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/destructor.json",
    "content": "{\n  \"parent\": \"block/block\",\n  \"textures\": {\n    \"cable\": \"refinedstorage:block/cable\",\n    \"front\": \"refinedstorage:block/destructor/destructor\",\n    \"cutout\": \"refinedstorage:block/destructor/cutouts/disconnected\",\n    \"border\": \"refinedstorage:block/cable_part_border\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"Core\",\n      \"from\": [\n        6,\n        6,\n        6\n      ],\n      \"to\": [\n        10,\n        10,\n        10\n      ],\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"east\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"south\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"up\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"down\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        }\n      }\n    },\n    {\n      \"name\": \"Part1\",\n      \"from\": [\n        10,\n        6,\n        6\n      ],\n      \"to\": [\n        16,\n        10,\n        10\n      ],\n      \"rotation\": {\n        \"angle\": 0,\n        \"axis\": \"y\",\n        \"origin\": [\n          16,\n          8,\n          9\n        ]\n      },\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"east\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"south\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"up\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"down\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        }\n      }\n    },\n    {\n      \"name\": \"Part2\",\n      \"from\": [\n        0,\n        6,\n        6\n      ],\n      \"to\": [\n        6,\n        10,\n        10\n      ],\n      \"rotation\": {\n        \"angle\": 0,\n        \"axis\": \"y\",\n        \"origin\": [\n          6,\n          8,\n          9\n        ]\n      },\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"east\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"up\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"down\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        }\n      }\n    },\n    {\n      \"name\": \"Line1\",\n      \"from\": [\n        7.0,\n        7.0,\n        2.0\n      ],\n      \"to\": [\n        9.0,\n        9.0,\n        6.0\n      ],\n      \"faces\": {\n        \"east\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            2.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            4.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            2.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            4.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            4.0\n          ]\n        }\n      }\n    },\n    {\n      \"name\": \"Line2\",\n      \"from\": [\n        2.0,\n        2.0,\n        0.0\n      ],\n      \"to\": [\n        14.0,\n        14.0,\n        2.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#front\",\n          \"uv\": [\n            0.0,\n            0.0,\n            16.0,\n            16.0\n          ]\n        },\n        \"east\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            14.0,\n            0.0,\n            16.0,\n            16.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            16.0,\n            16.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            16.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            2.0,\n            0.0,\n            14.0,\n            2.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            2.0,\n            14.0,\n            14.0,\n            16.0\n          ]\n        }\n      }\n    },\n    {\n      \"name\": \"Line3\",\n      \"from\": [\n        2.0,\n        2.0,\n        0.0\n      ],\n      \"to\": [\n        14.0,\n        14.0,\n        2.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#cutout\",\n          \"uv\": [\n            0.0,\n            0.0,\n            16.0,\n            16.0\n          ]\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/disk_drive.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/disk_drive\"\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/exporter.json",
    "content": "{\n  \"parent\": \"block/block\",\n  \"textures\": {\n    \"cable\": \"refinedstorage:block/cable\",\n    \"border\": \"refinedstorage:block/cable_part_border\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"Core\",\n      \"from\": [\n        6,\n        6,\n        6\n      ],\n      \"to\": [\n        10,\n        10,\n        10\n      ],\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"east\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"south\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"up\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"down\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        }\n      }\n    },\n    {\n      \"name\": \"Part1\",\n      \"from\": [\n        10,\n        6,\n        6\n      ],\n      \"to\": [\n        16,\n        10,\n        10\n      ],\n      \"rotation\": {\n        \"angle\": 0,\n        \"axis\": \"y\",\n        \"origin\": [\n          16,\n          8,\n          9\n        ]\n      },\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"east\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"south\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"up\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"down\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        }\n      }\n    },\n    {\n      \"name\": \"Part2\",\n      \"from\": [\n        0,\n        6,\n        6\n      ],\n      \"to\": [\n        6,\n        10,\n        10\n      ],\n      \"rotation\": {\n        \"angle\": 0,\n        \"axis\": \"y\",\n        \"origin\": [\n          6,\n          8,\n          9\n        ]\n      },\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"east\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"up\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"down\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        }\n      }\n    },\n    {\n      \"name\": \"Line1\",\n      \"from\": [\n        6,\n        6,\n        0\n      ],\n      \"to\": [\n        10,\n        10,\n        2\n      ],\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            0,\n            4,\n            4\n          ],\n          \"texture\": \"#border\"\n        },\n        \"east\": {\n          \"uv\": [\n            0,\n            0,\n            2,\n            4\n          ],\n          \"texture\": \"#border\"\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            0,\n            4,\n            4\n          ],\n          \"texture\": \"#border\"\n        },\n        \"west\": {\n          \"uv\": [\n            0,\n            0,\n            2,\n            4\n          ],\n          \"texture\": \"#border\"\n        },\n        \"up\": {\n          \"uv\": [\n            0,\n            0,\n            4,\n            2\n          ],\n          \"texture\": \"#border\"\n        },\n        \"down\": {\n          \"uv\": [\n            0,\n            0,\n            4,\n            2\n          ],\n          \"texture\": \"#border\"\n        }\n      }\n    },\n    {\n      \"name\": \"Line2\",\n      \"from\": [\n        5,\n        5,\n        2\n      ],\n      \"to\": [\n        11,\n        11,\n        4\n      ],\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            0,\n            6,\n            6\n          ],\n          \"texture\": \"#border\"\n        },\n        \"east\": {\n          \"uv\": [\n            0,\n            0,\n            2,\n            6\n          ],\n          \"texture\": \"#border\"\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            0,\n            6,\n            6\n          ],\n          \"texture\": \"#border\"\n        },\n        \"west\": {\n          \"uv\": [\n            0,\n            0,\n            2,\n            6\n          ],\n          \"texture\": \"#border\"\n        },\n        \"up\": {\n          \"uv\": [\n            0,\n            0,\n            6,\n            2\n          ],\n          \"texture\": \"#border\"\n        },\n        \"down\": {\n          \"uv\": [\n            0,\n            0,\n            6,\n            2\n          ],\n          \"texture\": \"#border\"\n        }\n      }\n    },\n    {\n      \"name\": \"Line3\",\n      \"from\": [\n        3,\n        3,\n        4\n      ],\n      \"to\": [\n        13,\n        13,\n        6\n      ],\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            0,\n            10,\n            10\n          ],\n          \"texture\": \"#border\"\n        },\n        \"east\": {\n          \"uv\": [\n            0,\n            0,\n            2,\n            10\n          ],\n          \"texture\": \"#border\"\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            0,\n            10,\n            10\n          ],\n          \"texture\": \"#border\"\n        },\n        \"west\": {\n          \"uv\": [\n            0,\n            0,\n            2,\n            10\n          ],\n          \"texture\": \"#border\"\n        },\n        \"up\": {\n          \"uv\": [\n            0,\n            0,\n            10,\n            2\n          ],\n          \"texture\": \"#border\"\n        },\n        \"down\": {\n          \"uv\": [\n            0,\n            0,\n            10,\n            2\n          ],\n          \"texture\": \"#border\"\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/external_storage.json",
    "content": "{\n  \"parent\": \"block/block\",\n  \"textures\": {\n    \"cable\": \"refinedstorage:block/cable\",\n    \"border\": \"refinedstorage:block/cable_part_border\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"Core\",\n      \"from\": [\n        6,\n        6,\n        6\n      ],\n      \"to\": [\n        10,\n        10,\n        10\n      ],\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"east\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"south\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"up\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"down\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        }\n      }\n    },\n    {\n      \"name\": \"Part1\",\n      \"from\": [\n        10,\n        6,\n        6\n      ],\n      \"to\": [\n        16,\n        10,\n        10\n      ],\n      \"rotation\": {\n        \"angle\": 0,\n        \"axis\": \"y\",\n        \"origin\": [\n          16,\n          8,\n          9\n        ]\n      },\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"east\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"south\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"up\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"down\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        }\n      }\n    },\n    {\n      \"name\": \"Part2\",\n      \"from\": [\n        0,\n        6,\n        6\n      ],\n      \"to\": [\n        6,\n        10,\n        10\n      ],\n      \"rotation\": {\n        \"angle\": 0,\n        \"axis\": \"y\",\n        \"origin\": [\n          6,\n          8,\n          9\n        ]\n      },\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"east\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"up\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"down\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        }\n      }\n    },\n    {\n      \"name\": \"Line1\",\n      \"from\": [\n        7.0,\n        7.0,\n        2.0\n      ],\n      \"to\": [\n        9.0,\n        9.0,\n        6.0\n      ],\n      \"faces\": {\n        \"east\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            2.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            4.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            2.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            4.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            4.0\n          ]\n        }\n      }\n    },\n    {\n      \"name\": \"Line2\",\n      \"from\": [\n        3.0,\n        3.0,\n        0.0\n      ],\n      \"to\": [\n        13.0,\n        13.0,\n        2.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            10.0,\n            10.0\n          ]\n        },\n        \"east\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            10.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            10.0,\n            10.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            10.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            10.0,\n            2.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            10.0,\n            2.0\n          ]\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/filter.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/filter\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/fluid_interface.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/fluid_interface_disconnected\"\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/fortune_1_upgrade.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/fortune_upgrade\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/fortune_2_upgrade.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/fortune_upgrade\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/fortune_3_upgrade.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/fortune_upgrade\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/importer.json",
    "content": "{\n  \"parent\": \"block/block\",\n  \"textures\": {\n    \"cable\": \"refinedstorage:block/cable\",\n    \"border\": \"refinedstorage:block/cable_part_border\"\n  },\n  \"elements\": [\n    {\n      \"name\": \"Core\",\n      \"from\": [\n        6,\n        6,\n        6\n      ],\n      \"to\": [\n        10,\n        10,\n        10\n      ],\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"east\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"south\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"up\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"down\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        }\n      }\n    },\n    {\n      \"name\": \"Part1\",\n      \"from\": [\n        10,\n        6,\n        6\n      ],\n      \"to\": [\n        16,\n        10,\n        10\n      ],\n      \"rotation\": {\n        \"angle\": 0,\n        \"axis\": \"y\",\n        \"origin\": [\n          16,\n          8,\n          9\n        ]\n      },\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"east\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"south\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"up\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"down\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        }\n      }\n    },\n    {\n      \"name\": \"Part2\",\n      \"from\": [\n        0,\n        6,\n        6\n      ],\n      \"to\": [\n        6,\n        10,\n        10\n      ],\n      \"rotation\": {\n        \"angle\": 0,\n        \"axis\": \"y\",\n        \"origin\": [\n          6,\n          8,\n          9\n        ]\n      },\n      \"faces\": {\n        \"north\": {\n          \"uv\": [\n            10,\n            6,\n            16,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"east\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"south\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"west\": {\n          \"uv\": [\n            6,\n            6,\n            10,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"up\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        },\n        \"down\": {\n          \"uv\": [\n            0,\n            6,\n            6,\n            10\n          ],\n          \"texture\": \"#cable\"\n        }\n      }\n    },\n    {\n      \"name\": \"Line1\",\n      \"from\": [\n        6.0,\n        6.0,\n        4.0\n      ],\n      \"to\": [\n        10.0,\n        10.0,\n        6.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            4.0\n          ]\n        },\n        \"east\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            4.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            4.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            4.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            2.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            4.0,\n            2.0\n          ]\n        }\n      }\n    },\n    {\n      \"name\": \"Line2\",\n      \"from\": [\n        5.0,\n        5.0,\n        2.0\n      ],\n      \"to\": [\n        11.0,\n        11.0,\n        4.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            6.0,\n            6.0\n          ]\n        },\n        \"east\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            6.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            6.0,\n            6.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            6.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            6.0,\n            2.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            6.0,\n            2.0\n          ]\n        }\n      }\n    },\n    {\n      \"name\": \"Line3\",\n      \"from\": [\n        3.0,\n        3.0,\n        0.0\n      ],\n      \"to\": [\n        13.0,\n        13.0,\n        2.0\n      ],\n      \"faces\": {\n        \"north\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            10.0,\n            10.0\n          ]\n        },\n        \"east\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            10.0\n          ]\n        },\n        \"south\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            10.0,\n            10.0\n          ]\n        },\n        \"west\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            2.0,\n            10.0\n          ]\n        },\n        \"up\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            10.0,\n            2.0\n          ]\n        },\n        \"down\": {\n          \"texture\": \"#border\",\n          \"uv\": [\n            0.0,\n            0.0,\n            10.0,\n            2.0\n          ]\n        }\n      }\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/improved_processor.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/improved_processor\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/interface.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/interface_disconnected\"\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/machine_casing.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/machine_casing\"\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/network_card.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/network_card\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/pattern.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/pattern\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/portable_grid.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/portable_grid\"\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/processor_binding.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/processor_binding\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/quartz_enriched_iron.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/quartz_enriched_iron\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/quartz_enriched_iron_block.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/quartz_enriched_iron_block\"\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/range_upgrade.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/range_upgrade\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/raw_advanced_processor.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/raw_advanced_processor\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/raw_basic_processor.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/raw_basic_processor\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/raw_improved_processor.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/raw_improved_processor\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/regulator_upgrade.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/regulator_upgrade\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/security_card.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/security_card_inactive\"\n  },\n  \"overrides\": [\n    {\n      \"predicate\": {\n        \"refinedstorage:active\": 0\n      },\n      \"model\": \"refinedstorage:item/security_card_inactive\"\n    },\n    {\n      \"predicate\": {\n        \"refinedstorage:active\": 1\n      },\n      \"model\": \"refinedstorage:item/security_card_active\"\n    }\n  ]\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/security_card_active.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/security_card_active\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/security_card_inactive.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/security_card_inactive\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/silicon.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/silicon\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/silk_touch_upgrade.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/silk_touch_upgrade\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/speed_upgrade.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/speed_upgrade\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/stack_upgrade.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/stack_upgrade\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/storage_housing.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/storage_housing\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/storage_monitor.json",
    "content": "{\n  \"parent\": \"refinedstorage:block/storage_monitor\"\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/upgrade.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/upgrade\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/wireless_crafting_monitor.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/wireless_crafting_monitor_disconnected\"\n  },\n  \"overrides\": [\n    {\n      \"predicate\": {\n        \"refinedstorage:connected\": 0\n      },\n      \"model\": \"refinedstorage:item/wireless_crafting_monitor_disconnected\"\n    },\n    {\n      \"predicate\": {\n        \"refinedstorage:connected\": 1\n      },\n      \"model\": \"refinedstorage:item/wireless_crafting_monitor_connected\"\n    }\n  ]\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/wireless_crafting_monitor_connected.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/wireless_crafting_monitor_connected\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/wireless_crafting_monitor_disconnected.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/wireless_crafting_monitor_disconnected\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/wireless_fluid_grid.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/wireless_fluid_grid_disconnected\"\n  },\n  \"overrides\": [\n    {\n      \"predicate\": {\n        \"refinedstorage:connected\": 0\n      },\n      \"model\": \"refinedstorage:item/wireless_fluid_grid_disconnected\"\n    },\n    {\n      \"predicate\": {\n        \"refinedstorage:connected\": 1\n      },\n      \"model\": \"refinedstorage:item/wireless_fluid_grid_connected\"\n    }\n  ]\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/wireless_fluid_grid_connected.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/wireless_fluid_grid_connected\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/wireless_fluid_grid_disconnected.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/wireless_fluid_grid_disconnected\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/wireless_grid.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/wireless_grid_disconnected\"\n  },\n  \"overrides\": [\n    {\n      \"predicate\": {\n        \"refinedstorage:connected\": 0\n      },\n      \"model\": \"refinedstorage:item/wireless_grid_disconnected\"\n    },\n    {\n      \"predicate\": {\n        \"refinedstorage:connected\": 1\n      },\n      \"model\": \"refinedstorage:item/wireless_grid_connected\"\n    }\n  ]\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/wireless_grid_connected.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/wireless_grid_connected\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/wireless_grid_disconnected.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/wireless_grid_disconnected\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/models/item/wrench.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"refinedstorage:item/wrench\"\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/constructor/cutouts/connected.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 2,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/black.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 2,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/blue.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 2,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/brown.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 1,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/cyan.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 2,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/gray.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 2,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/green.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 2,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/light_blue.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 2,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/light_gray.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 2,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/lime.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 2,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/magenta.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 2,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/nearly_off.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 1,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/nearly_off_gray.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 1,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/nearly_on.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 2,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/nearly_on_gray.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 2,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/on.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 2,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/orange.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 2,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/pink.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 2,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/purple.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 2,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/red.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 2,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/white.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 2,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/yellow.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 2,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11\n    ]\n  }\n}\n"
  },
  {
    "path": "src/main/resources/assets/refinedstorage/textures/block/destructor/cutouts/connected.png.mcmeta",
    "content": "{\n  \"animation\": {\n    \"frametime\": 1,\n    \"frames\": [\n      0,\n      1,\n      2,\n      3,\n      4,\n      5,\n      6,\n      7,\n      8,\n      9,\n      10,\n      11,\n      12,\n      13,\n      14,\n      15,\n      16,\n      17,\n      18,\n      19\n    ]\n  }\n}"
  },
  {
    "path": "src/main/resources/data/curios/tags/items/curio.json",
    "content": "{\n  \"replace\": false,\n  \"values\": [\n    \"refinedstorage:wireless_grid\",\n    \"refinedstorage:creative_wireless_grid\",\n    \"refinedstorage:wireless_fluid_grid\",\n    \"refinedstorage:creative_wireless_fluid_grid\",\n    \"refinedstorage:wireless_crafting_monitor\",\n    \"refinedstorage:creative_wireless_crafting_monitor\"\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/forge/tags/items/silicon.json",
    "content": "{\n  \"replace\": false,\n  \"values\": [\n    \"refinedstorage:silicon\"\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/autocrafting.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:crafter\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.autocrafting\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.autocrafting.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:root\",\n  \"criteria\": {\n    \"crafter_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:crafter\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/better_than_a_barrel.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:storage_monitor\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.better_than_a_barrel\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.better_than_a_barrel.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:root\",\n  \"criteria\": {\n    \"storage_monitor_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:storage_monitor\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/conditional_connecting.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:relay\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.conditional_connecting\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.conditional_connecting.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:connecting\",\n  \"criteria\": {\n    \"relay_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:relay\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/connecting.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:cable\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.connecting\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.connecting.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:root\",\n  \"criteria\": {\n    \"cable_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:cable\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/construction.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:constructor\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.construction\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.construction.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:exporting\",\n  \"criteria\": {\n    \"constructor_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:constructor\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/crafting_on_demand.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:crafting_upgrade\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.crafting_on_demand\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.crafting_on_demand.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:pattern_creation\",\n  \"criteria\": {\n    \"upgrade_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:crafting_upgrade\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/destruction.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:destructor\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.destruction\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.destruction.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:importing\",\n  \"criteria\": {\n    \"destructor_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:destructor\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/detecting.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:detector\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.detecting\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.detecting.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:root\",\n  \"criteria\": {\n    \"detector_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:detector\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/drives.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:disk_drive\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.drives\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.drives.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:root\",\n  \"criteria\": {\n    \"disk_drive_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:disk_drive\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/exporting.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:exporter\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.exporting\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.exporting.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:root\",\n  \"criteria\": {\n    \"exporter_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:exporter\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/importing.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:importer\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.importing\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.importing.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:root\",\n  \"criteria\": {\n    \"importer_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:importer\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/interface_to_the_world.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:interface\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.interface_to_the_world\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.interface_to_the_world.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:root\",\n  \"criteria\": {\n    \"interface_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:interface\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/managing_patterns.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:crafter_manager\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.managing_patterns\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.managing_patterns.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:autocrafting\",\n  \"criteria\": {\n    \"crafter_manager_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:crafter_manager\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/manipulating_disks.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:disk_manipulator\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.manipulating_disks\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.manipulating_disks.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:drives\",\n  \"criteria\": {\n    \"disk_manipulator_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:disk_manipulator\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/monitoring.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:crafting_monitor\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.monitoring\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.monitoring.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:autocrafting\",\n  \"criteria\": {\n    \"crafting_monitor_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:crafting_monitor\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/no_cables_required.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:network_transmitter\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.no_cables_required\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.no_cables_required.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:wireless\",\n  \"criteria\": {\n    \"network_transmitter_receiver_card_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:network_transmitter\"\n            ]\n          },\n          {\n            \"items\": [\n              \"refinedstorage:network_receiver\"\n            ]\n          },\n          {\n            \"items\": [\n              \"refinedstorage:network_card\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/pattern_creation.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:pattern\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.pattern_creation\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.pattern_creation.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:autocrafting\",\n  \"criteria\": {\n    \"pattern_and_pattern_grid_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:pattern\"\n            ]\n          },\n          {\n            \"items\": [\n              \"refinedstorage:pattern_grid\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/portable_storage.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:portable_grid\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.portable_storage\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.portable_storage.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:viewing_items\",\n  \"criteria\": {\n    \"portable_grid_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:portable_grid\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/root.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:creative_controller\"\n    },\n    \"title\": {\n      \"translate\": \"itemGroup.refinedstorage\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.controlling.description\"\n    },\n    \"background\": \"refinedstorage:textures/gui/advancements.png\"\n  },\n  \"criteria\": {\n    \"controller_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:controller\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/security.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:security_manager\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.security\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.security.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:root\",\n  \"criteria\": {\n    \"security_manager_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:security_manager\"\n            ]\n          },\n          {\n            \"items\": [\n              \"refinedstorage:security_card\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/storing_externally.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:external_storage\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.storing_externally\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.storing_externally.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:root\",\n  \"criteria\": {\n    \"external_storage_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:external_storage\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/storing_fluids.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:64k_fluid_storage_disk\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.storing_fluids\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.storing_fluids.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:drives\",\n  \"criteria\": {\n    \"fluid_storage_disk_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:64k_fluid_storage_disk\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/storing_items.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:1k_storage_disk\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.storing_items\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.storing_items.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:drives\",\n  \"criteria\": {\n    \"storage_disk_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:1k_storage_disk\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/upgrading.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:upgrade\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.upgrading\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.upgrading.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:root\",\n  \"criteria\": {\n    \"upgrade_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:upgrade\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/upgrading_your_grid.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:crafting_grid\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.upgrading_your_grid\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.upgrading_your_grid.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:viewing_items\",\n  \"criteria\": {\n    \"crafting_grid_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:crafting_grid\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/viewing_fluids.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:fluid_grid\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.viewing_fluids\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.viewing_fluids.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:storing_fluids\",\n  \"criteria\": {\n    \"fluid_grid_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:fluid_grid\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/viewing_items.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:grid\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.viewing_items\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.viewing_items.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:storing_items\",\n  \"criteria\": {\n    \"grid_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:grid\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/wireless.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:wireless_transmitter\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.wireless\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.wireless.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:root\",\n  \"criteria\": {\n    \"wireless_transmitter_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:wireless_transmitter\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/wireless_fluids.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:wireless_fluid_grid\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.wireless_fluids\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.wireless_fluids.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:wireless\",\n  \"criteria\": {\n    \"wireless_fluid_grid_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:wireless_fluid_grid\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/wireless_items.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:wireless_grid\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.wireless_items\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.wireless_items.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:wireless\",\n  \"criteria\": {\n    \"wireless_grid_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:wireless_grid\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/advancements/wireless_monitoring.json",
    "content": "{\n  \"display\": {\n    \"icon\": {\n      \"item\": \"refinedstorage:wireless_crafting_monitor\"\n    },\n    \"title\": {\n      \"translate\": \"advancements.refinedstorage.wireless_monitoring\"\n    },\n    \"description\": {\n      \"translate\": \"advancements.refinedstorage.wireless_monitoring.description\"\n    }\n  },\n  \"parent\": \"refinedstorage:wireless\",\n  \"criteria\": {\n    \"wireless_crafting_monitor_in_inventory\": {\n      \"trigger\": \"minecraft:inventory_changed\",\n      \"conditions\": {\n        \"items\": [\n          {\n            \"items\": [\n              \"refinedstorage:wireless_crafting_monitor\"\n            ]\n          }\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/1024k_fluid_storage_block.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:1024k_fluid_storage_block\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:storage_block\"\n            }\n          ]\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/16k_storage_block.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:16k_storage_block\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:storage_block\"\n            }\n          ]\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/1k_storage_block.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:1k_storage_block\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:storage_block\"\n            }\n          ]\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/256k_fluid_storage_block.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:256k_fluid_storage_block\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:storage_block\"\n            }\n          ]\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/4096k_fluid_storage_block.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:4096k_fluid_storage_block\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:storage_block\"\n            }\n          ]\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/4k_storage_block.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:4k_storage_block\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:storage_block\"\n            }\n          ]\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/64k_fluid_storage_block.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:64k_fluid_storage_block\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:storage_block\"\n            }\n          ]\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/64k_storage_block.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:64k_storage_block\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:storage_block\"\n            }\n          ]\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/cable.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:cable\"\n        }\n      ],\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/constructor.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:constructor\"\n        }\n      ],\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/creative_fluid_storage_block.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:creative_fluid_storage_block\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:storage_block\"\n            }\n          ]\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/creative_portable_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:creative_portable_grid\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:portable_grid\"\n            }\n          ]\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/creative_storage_block.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:creative_storage_block\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:storage_block\"\n            }\n          ]\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/destructor.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:destructor\"\n        }\n      ],\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/disk_drive.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:disk_drive\"\n        }\n      ],\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/exporter.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:exporter\"\n        }\n      ],\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/external_storage.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:external_storage\"\n        }\n      ],\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/fluid_interface.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:fluid_interface\"\n        }\n      ],\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/importer.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:importer\"\n        }\n      ],\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/interface.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:interface\"\n        }\n      ],\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/machine_casing.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:machine_casing\"\n        }\n      ],\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/portable_grid.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:portable_grid\",\n          \"functions\": [\n            {\n              \"function\": \"refinedstorage:portable_grid\"\n            }\n          ]\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/quartz_enriched_iron_block.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:quartz_enriched_iron_block\"\n        }\n      ],\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/loot_tables/blocks/storage_monitor.json",
    "content": "{\n  \"type\": \"minecraft:block\",\n  \"pools\": [\n    {\n      \"rolls\": 1,\n      \"entries\": [\n        {\n          \"type\": \"minecraft:item\",\n          \"name\": \"refinedstorage:storage_monitor\"\n        }\n      ],\n      \"conditions\": [\n        {\n          \"condition\": \"minecraft:survives_explosion\"\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/1024k_fluid_storage_block.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EPE\",\n    \"EME\",\n    \"ERE\"\n  ],\n  \"key\": {\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:1024k_fluid_storage_part\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:1024k_fluid_storage_block\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/1024k_fluid_storage_disk.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"GRG\",\n    \"RPR\",\n    \"EEE\"\n  ],\n  \"key\": {\n    \"G\": {\n      \"tag\": \"forge:glass\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:1024k_fluid_storage_part\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:1024k_fluid_storage_disk\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/1024k_fluid_storage_disk_from_storage_housing.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:storage_housing\"\n    },\n    {\n      \"item\": \"refinedstorage:1024k_fluid_storage_part\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:1024k_fluid_storage_disk\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/1024k_fluid_storage_part.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"PEP\",\n    \"SRS\",\n    \"PSP\"\n  ],\n  \"key\": {\n    \"P\": {\n      \"item\": \"refinedstorage:improved_processor\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"S\": {\n      \"item\": \"refinedstorage:256k_fluid_storage_part\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:bucket\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:1024k_fluid_storage_part\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/16k_storage_block.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EPE\",\n    \"EME\",\n    \"ERE\"\n  ],\n  \"key\": {\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:16k_storage_part\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:16k_storage_block\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/16k_storage_disk.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"GRG\",\n    \"RPR\",\n    \"EEE\"\n  ],\n  \"key\": {\n    \"G\": {\n      \"tag\": \"forge:glass\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:16k_storage_part\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:16k_storage_disk\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/16k_storage_disk_from_storage_housing.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:storage_housing\"\n    },\n    {\n      \"item\": \"refinedstorage:16k_storage_part\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:16k_storage_disk\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/16k_storage_part.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"PEP\",\n    \"SRS\",\n    \"PSP\"\n  ],\n  \"key\": {\n    \"P\": {\n      \"item\": \"refinedstorage:improved_processor\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"S\": {\n      \"item\": \"refinedstorage:4k_storage_part\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:16k_storage_part\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/1k_storage_block.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EPE\",\n    \"EME\",\n    \"ERE\"\n  ],\n  \"key\": {\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:1k_storage_part\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:1k_storage_block\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/1k_storage_disk.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"GRG\",\n    \"RPR\",\n    \"EEE\"\n  ],\n  \"key\": {\n    \"G\": {\n      \"tag\": \"forge:glass\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:1k_storage_part\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:1k_storage_disk\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/1k_storage_disk_from_storage_housing.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:storage_housing\"\n    },\n    {\n      \"item\": \"refinedstorage:1k_storage_part\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:1k_storage_disk\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/1k_storage_part.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"SES\",\n    \"GRG\",\n    \"SGS\"\n  ],\n  \"key\": {\n    \"S\": {\n      \"tag\": \"forge:silicon\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"G\": {\n      \"tag\": \"forge:glass\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:1k_storage_part\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/256k_fluid_storage_block.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EPE\",\n    \"EME\",\n    \"ERE\"\n  ],\n  \"key\": {\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:256k_fluid_storage_part\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:256k_fluid_storage_block\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/256k_fluid_storage_disk.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"GRG\",\n    \"RPR\",\n    \"EEE\"\n  ],\n  \"key\": {\n    \"G\": {\n      \"tag\": \"forge:glass\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:256k_fluid_storage_part\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:256k_fluid_storage_disk\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/256k_fluid_storage_disk_from_storage_housing.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:storage_housing\"\n    },\n    {\n      \"item\": \"refinedstorage:256k_fluid_storage_part\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:256k_fluid_storage_disk\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/256k_fluid_storage_part.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"PEP\",\n    \"SRS\",\n    \"PSP\"\n  ],\n  \"key\": {\n    \"P\": {\n      \"item\": \"refinedstorage:basic_processor\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"S\": {\n      \"item\": \"refinedstorage:64k_fluid_storage_part\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:bucket\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:256k_fluid_storage_part\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/4096k_fluid_storage_block.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EPE\",\n    \"EME\",\n    \"ERE\"\n  ],\n  \"key\": {\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:4096k_fluid_storage_part\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:4096k_fluid_storage_block\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/4096k_fluid_storage_disk.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"GRG\",\n    \"RPR\",\n    \"EEE\"\n  ],\n  \"key\": {\n    \"G\": {\n      \"tag\": \"forge:glass\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:4096k_fluid_storage_part\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:4096k_fluid_storage_disk\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/4096k_fluid_storage_disk_from_storage_housing.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:storage_housing\"\n    },\n    {\n      \"item\": \"refinedstorage:4096k_fluid_storage_part\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:4096k_fluid_storage_disk\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/4096k_fluid_storage_part.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"PEP\",\n    \"SRS\",\n    \"PSP\"\n  ],\n  \"key\": {\n    \"P\": {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"S\": {\n      \"item\": \"refinedstorage:1024k_fluid_storage_part\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:bucket\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:4096k_fluid_storage_part\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/4k_storage_block.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EPE\",\n    \"EME\",\n    \"ERE\"\n  ],\n  \"key\": {\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:4k_storage_part\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:4k_storage_block\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/4k_storage_disk.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"GRG\",\n    \"RPR\",\n    \"EEE\"\n  ],\n  \"key\": {\n    \"G\": {\n      \"tag\": \"forge:glass\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:4k_storage_part\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:4k_storage_disk\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/4k_storage_disk_from_storage_housing.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:storage_housing\"\n    },\n    {\n      \"item\": \"refinedstorage:4k_storage_part\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:4k_storage_disk\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/4k_storage_part.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"PEP\",\n    \"SRS\",\n    \"PSP\"\n  ],\n  \"key\": {\n    \"P\": {\n      \"item\": \"refinedstorage:basic_processor\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"S\": {\n      \"item\": \"refinedstorage:1k_storage_part\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:4k_storage_part\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/64k_fluid_storage_block.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EPE\",\n    \"EME\",\n    \"ERE\"\n  ],\n  \"key\": {\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:64k_fluid_storage_part\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:64k_fluid_storage_block\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/64k_fluid_storage_disk.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"GRG\",\n    \"RPR\",\n    \"EEE\"\n  ],\n  \"key\": {\n    \"G\": {\n      \"tag\": \"forge:glass\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:64k_fluid_storage_part\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:64k_fluid_storage_disk\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/64k_fluid_storage_disk_from_storage_housing.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:storage_housing\"\n    },\n    {\n      \"item\": \"refinedstorage:64k_fluid_storage_part\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:64k_fluid_storage_disk\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/64k_fluid_storage_part.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"SES\",\n    \"GRG\",\n    \"SGS\"\n  ],\n  \"key\": {\n    \"S\": {\n      \"tag\": \"forge:silicon\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"G\": {\n      \"tag\": \"forge:glass\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:bucket\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:64k_fluid_storage_part\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/64k_storage_block.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EPE\",\n    \"EME\",\n    \"ERE\"\n  ],\n  \"key\": {\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:64k_storage_part\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:64k_storage_block\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/64k_storage_disk.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"GRG\",\n    \"RPR\",\n    \"EEE\"\n  ],\n  \"key\": {\n    \"G\": {\n      \"tag\": \"forge:glass\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:64k_storage_part\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:64k_storage_disk\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/64k_storage_disk_from_storage_housing.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:storage_housing\"\n    },\n    {\n      \"item\": \"refinedstorage:64k_storage_part\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:64k_storage_disk\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/64k_storage_part.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"PEP\",\n    \"SRS\",\n    \"PSP\"\n  ],\n  \"key\": {\n    \"P\": {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"S\": {\n      \"item\": \"refinedstorage:16k_storage_part\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:64k_storage_part\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/advanced_processor.json",
    "content": "{\n  \"type\": \"minecraft:smelting\",\n  \"ingredient\": {\n    \"item\": \"refinedstorage:raw_advanced_processor\"\n  },\n  \"result\": \"refinedstorage:advanced_processor\",\n  \"experience\": 0.5\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/basic_processor.json",
    "content": "{\n  \"type\": \"minecraft:smelting\",\n  \"ingredient\": {\n    \"item\": \"refinedstorage:raw_basic_processor\"\n  },\n  \"result\": \"refinedstorage:basic_processor\",\n  \"experience\": 0.5\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/block_of_quartz_enriched_iron.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EEE\",\n    \"EEE\",\n    \"EEE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:quartz_enriched_iron_block\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/cable.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EEE\",\n    \"GRG\",\n    \"EEE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"G\": {\n      \"tag\": \"forge:glass\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:cable\",\n    \"count\": 12\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/construction_core.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:basic_processor\"\n    },\n    {\n      \"item\": \"minecraft:glowstone_dust\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:construction_core\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/constructor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"ECE\",\n    \"RMR\",\n    \"EIE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"C\": {\n      \"item\": \"refinedstorage:construction_core\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"M\": {\n      \"item\": \"refinedstorage:cable\"\n    },\n    \"I\": {\n      \"item\": \"refinedstorage:improved_processor\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:constructor\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/controller.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EPE\",\n    \"SMS\",\n    \"ESE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    \"S\": {\n      \"tag\": \"forge:silicon\"\n    },\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:controller\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/cover.json",
    "content": "{\n  \"type\": \"refinedstorage:cover_recipe\"\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/crafter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"ECE\",\n    \"AMA\",\n    \"EDE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"C\": {\n      \"item\": \"refinedstorage:construction_core\"\n    },\n    \"A\": {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    },\n    \"D\": {\n      \"item\": \"refinedstorage:destruction_core\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:crafter\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/crafter_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"PCG\",\n    \"EMG\",\n    \"PCG\"\n  ],\n  \"key\": {\n    \"P\": {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    \"C\": {\n      \"tag\": \"refinedstorage:crafter\"\n    },\n    \"G\": {\n      \"tag\": \"forge:glass\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:crafter_manager\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"PAG\",\n    \"EMG\",\n    \"PAG\"\n  ],\n  \"key\": {\n    \"P\": {\n      \"item\": \"refinedstorage:improved_processor\"\n    },\n    \"A\": {\n      \"item\": \"refinedstorage:pattern\"\n    },\n    \"G\": {\n      \"tag\": \"forge:glass\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:crafting_monitor\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/crafting_upgrade.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EOE\",\n    \"CUC\",\n    \"EEE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"C\": {\n      \"tag\": \"refinedstorage:crafting_tables\"\n    },\n    \"O\": {\n      \"item\": \"refinedstorage:construction_core\"\n    },\n    \"U\": {\n      \"item\": \"refinedstorage:upgrade\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:crafting_upgrade\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/destruction_core.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:basic_processor\"\n    },\n    {\n      \"item\": \"minecraft:quartz\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:destruction_core\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/destructor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EDE\",\n    \"RMR\",\n    \"EIE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"D\": {\n      \"item\": \"refinedstorage:destruction_core\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"M\": {\n      \"item\": \"refinedstorage:cable\"\n    },\n    \"I\": {\n      \"item\": \"refinedstorage:improved_processor\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:destructor\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/detector.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"ERE\",\n    \"CMC\",\n    \"EPE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"C\": {\n      \"item\": \"minecraft:comparator\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone_torch\"\n    },\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:improved_processor\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:detector\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/disk_drive.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"ECE\",\n    \"EME\",\n    \"EPE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"C\": {\n      \"tag\": \"forge:chests\"\n    },\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:advanced_processor\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:disk_drive\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/disk_manipulator.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"ESE\",\n    \"CMD\",\n    \"ESE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"S\": {\n      \"item\": \"refinedstorage:storage_housing\"\n    },\n    \"C\": {\n      \"item\": \"refinedstorage:construction_core\"\n    },\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    },\n    \"D\": {\n      \"item\": \"refinedstorage:destruction_core\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:disk_manipulator\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/exporter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:cable\"\n    },\n    {\n      \"item\": \"refinedstorage:construction_core\"\n    },\n    {\n      \"item\": \"refinedstorage:improved_processor\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:exporter\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/external_storage.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"CED\",\n    \"HMH\",\n    \"EPE\"\n  ],\n  \"key\": {\n    \"C\": {\n      \"item\": \"refinedstorage:construction_core\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"D\": {\n      \"item\": \"refinedstorage:destruction_core\"\n    },\n    \"H\": {\n      \"tag\": \"forge:chests\"\n    },\n    \"M\": {\n      \"item\": \"refinedstorage:cable\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:improved_processor\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:external_storage\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/filter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EPE\",\n    \"PHP\",\n    \"EPE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"P\": {\n      \"item\": \"minecraft:paper\"\n    },\n    \"H\": {\n      \"item\": \"minecraft:hopper\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:filter\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/fluid_interface.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:interface\"\n    },\n    {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    {\n      \"item\": \"minecraft:bucket\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:fluid_interface\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/fortune_1_upgrade.json",
    "content": "{\n  \"type\": \"refinedstorage:upgrade_with_enchanted_book\",\n  \"enchantment\": \"minecraft:fortune\",\n  \"level\": 1,\n  \"result\": \"refinedstorage:fortune_1_upgrade\"\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/fortune_2_upgrade.json",
    "content": "{\n  \"type\": \"refinedstorage:upgrade_with_enchanted_book\",\n  \"enchantment\": \"minecraft:fortune\",\n  \"level\": 2,\n  \"result\": \"refinedstorage:fortune_2_upgrade\"\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/fortune_3_upgrade.json",
    "content": "{\n  \"type\": \"refinedstorage:upgrade_with_enchanted_book\",\n  \"enchantment\": \"minecraft:fortune\",\n  \"level\": 3,\n  \"result\": \"refinedstorage:fortune_3_upgrade\"\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"PCG\",\n    \"EMG\",\n    \"PDG\"\n  ],\n  \"key\": {\n    \"P\": {\n      \"item\": \"refinedstorage:improved_processor\"\n    },\n    \"C\": {\n      \"item\": \"refinedstorage:construction_core\"\n    },\n    \"G\": {\n      \"tag\": \"forge:glass\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    },\n    \"D\": {\n      \"item\": \"refinedstorage:destruction_core\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:grid\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/hollow_cover.json",
    "content": "{\n  \"type\": \"refinedstorage:hollow_cover_recipe\"\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/importer.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:cable\"\n    },\n    {\n      \"item\": \"refinedstorage:destruction_core\"\n    },\n    {\n      \"item\": \"refinedstorage:improved_processor\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:importer\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/improved_processor.json",
    "content": "{\n  \"type\": \"minecraft:smelting\",\n  \"ingredient\": {\n    \"item\": \"refinedstorage:raw_improved_processor\"\n  },\n  \"result\": \"refinedstorage:improved_processor\",\n  \"experience\": 0.5\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/interface.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"UIU\",\n    \"RMR\",\n    \"UEU\"\n  ],\n  \"key\": {\n    \"I\": {\n      \"item\": \"refinedstorage:importer\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:exporter\"\n    },\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"U\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:interface\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/machine_casing.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EEE\",\n    \"ESE\",\n    \"EEE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"S\": {\n      \"tag\": \"forge:stone\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:machine_casing\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/network_card.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EEE\",\n    \"PAP\",\n    \"EEE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"P\": {\n      \"item\": \"minecraft:paper\"\n    },\n    \"A\": {\n      \"item\": \"refinedstorage:advanced_processor\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:network_card\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/network_receiver.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"ANA\",\n    \"CMD\",\n    \"EEE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"tag\": \"forge:ender_pearls\"\n    },\n    \"C\": {\n      \"item\": \"refinedstorage:construction_core\"\n    },\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    },\n    \"D\": {\n      \"item\": \"refinedstorage:destruction_core\"\n    },\n    \"A\": {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    \"N\": {\n      \"item\": \"minecraft:netherite_ingot\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:network_receiver\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/network_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EEE\",\n    \"CMD\",\n    \"ANA\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"tag\": \"forge:ender_pearls\"\n    },\n    \"C\": {\n      \"item\": \"refinedstorage:construction_core\"\n    },\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    },\n    \"D\": {\n      \"item\": \"refinedstorage:destruction_core\"\n    },\n    \"A\": {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    \"N\": {\n      \"item\": \"minecraft:netherite_ingot\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:network_transmitter\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/pattern.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"GRG\",\n    \"RGR\",\n    \"EEE\"\n  ],\n  \"key\": {\n    \"G\": {\n      \"tag\": \"forge:glass\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:pattern\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/portable_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EGE\",\n    \"ECE\",\n    \"EFE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"G\": {\n      \"tag\": \"refinedstorage:grid\"\n    },\n    \"F\": {\n      \"item\": \"refinedstorage:fluid_grid\"\n    },\n    \"C\": {\n      \"tag\": \"refinedstorage:controller\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:portable_grid\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/processor_binding.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"   \",\n    \"SLS\",\n    \"   \"\n  ],\n  \"key\": {\n    \"S\": {\n      \"tag\": \"forge:string\"\n    },\n    \"L\": {\n      \"tag\": \"forge:slimeballs\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:processor_binding\",\n    \"count\": 8\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/quartz_enriched_iron.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"II\",\n    \"IQ\"\n  ],\n  \"key\": {\n    \"I\": {\n      \"item\": \"minecraft:iron_ingot\"\n    },\n    \"Q\": {\n      \"item\": \"minecraft:quartz\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:quartz_enriched_iron\",\n    \"count\": 4\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/quartz_enriched_iron_from_block.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:quartz_enriched_iron_block\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:quartz_enriched_iron\",\n    \"count\": 9\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/range_upgrade.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EPE\",\n    \"PUP\",\n    \"EEE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"P\": {\n      \"tag\": \"forge:ender_pearls\"\n    },\n    \"U\": {\n      \"item\": \"refinedstorage:upgrade\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:range_upgrade\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/raw_advanced_processor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:processor_binding\"\n    },\n    {\n      \"item\": \"minecraft:diamond\"\n    },\n    {\n      \"tag\": \"forge:silicon\"\n    },\n    {\n      \"item\": \"minecraft:redstone\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:raw_advanced_processor\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/raw_basic_processor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:processor_binding\"\n    },\n    {\n      \"item\": \"minecraft:iron_ingot\"\n    },\n    {\n      \"tag\": \"forge:silicon\"\n    },\n    {\n      \"item\": \"minecraft:redstone\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:raw_basic_processor\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/raw_improved_processor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:processor_binding\"\n    },\n    {\n      \"item\": \"minecraft:gold_ingot\"\n    },\n    {\n      \"tag\": \"forge:silicon\"\n    },\n    {\n      \"item\": \"minecraft:redstone\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:raw_improved_processor\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/regulator_upgrade.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"ECE\",\n    \"RUR\",\n    \"EEE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"C\": {\n      \"item\": \"minecraft:comparator\"\n    },\n    \"U\": {\n      \"item\": \"refinedstorage:upgrade\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:regulator_upgrade\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/relay.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"ingredients\": [\n    {\n      \"item\": \"refinedstorage:machine_casing\"\n    },\n    {\n      \"item\": \"refinedstorage:cable\"\n    },\n    {\n      \"item\": \"minecraft:redstone_torch\"\n    }\n  ],\n  \"result\": {\n    \"item\": \"refinedstorage:relay\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/security_card.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EEE\",\n    \"CAC\",\n    \"EEE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"C\": {\n      \"item\": \"refinedstorage:network_card\"\n    },\n    \"A\": {\n      \"item\": \"refinedstorage:advanced_processor\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:security_card\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/security_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"ECE\",\n    \"SMS\",\n    \"ESE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"C\": {\n      \"tag\": \"forge:chests\"\n    },\n    \"S\": {\n      \"item\": \"refinedstorage:security_card\"\n    },\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:security_manager\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/silicon.json",
    "content": "{\n  \"type\": \"minecraft:smelting\",\n  \"ingredient\": {\n    \"item\": \"minecraft:quartz\"\n  },\n  \"result\": \"refinedstorage:silicon\",\n  \"experience\": 0.5\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/silk_touch_upgrade.json",
    "content": "{\n  \"type\": \"refinedstorage:upgrade_with_enchanted_book\",\n  \"enchantment\": \"minecraft:silk_touch\",\n  \"result\": \"refinedstorage:silk_touch_upgrade\"\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/speed_upgrade.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"ESE\",\n    \"SUS\",\n    \"EEE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"S\": {\n      \"item\": \"minecraft:sugar\"\n    },\n    \"U\": {\n      \"item\": \"refinedstorage:upgrade\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:speed_upgrade\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/stack_upgrade.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"USU\",\n    \"SUS\",\n    \"USU\"\n  ],\n  \"key\": {\n    \"U\": {\n      \"item\": \"minecraft:sugar\"\n    },\n    \"S\": {\n      \"item\": \"refinedstorage:speed_upgrade\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:stack_upgrade\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/storage_housing.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"GRG\",\n    \"R R\",\n    \"EEE\"\n  ],\n  \"key\": {\n    \"G\": {\n      \"tag\": \"forge:glass\"\n    },\n    \"R\": {\n      \"item\": \"minecraft:redstone\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:storage_housing\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/storage_monitor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"PCG\",\n    \"EMG\",\n    \"PDG\"\n  ],\n  \"key\": {\n    \"P\": {\n      \"item\": \"refinedstorage:basic_processor\"\n    },\n    \"C\": {\n      \"item\": \"refinedstorage:construction_core\"\n    },\n    \"G\": {\n      \"tag\": \"forge:glass\"\n    },\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    },\n    \"D\": {\n      \"item\": \"refinedstorage:destruction_core\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:storage_monitor\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/upgrade.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EGE\",\n    \"EPE\",\n    \"EGE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"G\": {\n      \"tag\": \"forge:glass\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:improved_processor\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:upgrade\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/wireless_crafting_monitor.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EPE\",\n    \"EME\",\n    \"EAE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"P\": {\n      \"tag\": \"forge:ender_pearls\"\n    },\n    \"M\": {\n      \"tag\": \"refinedstorage:crafting_monitor\"\n    },\n    \"A\": {\n      \"item\": \"refinedstorage:advanced_processor\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:wireless_crafting_monitor\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/wireless_fluid_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EPE\",\n    \"EGE\",\n    \"EAE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"P\": {\n      \"tag\": \"forge:ender_pearls\"\n    },\n    \"G\": {\n      \"tag\": \"refinedstorage:fluid_grid\"\n    },\n    \"A\": {\n      \"item\": \"refinedstorage:advanced_processor\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:wireless_fluid_grid\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/wireless_grid.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EPE\",\n    \"EGE\",\n    \"EAE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"P\": {\n      \"tag\": \"forge:ender_pearls\"\n    },\n    \"G\": {\n      \"tag\": \"refinedstorage:grid\"\n    },\n    \"A\": {\n      \"item\": \"refinedstorage:advanced_processor\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:wireless_grid\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/wireless_transmitter.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EPE\",\n    \"EME\",\n    \"EAE\"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"A\": {\n      \"item\": \"refinedstorage:advanced_processor\"\n    },\n    \"M\": {\n      \"item\": \"refinedstorage:machine_casing\"\n    },\n    \"P\": {\n      \"tag\": \"forge:ender_pearls\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:wireless_transmitter\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/recipes/wrench.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"EPE\",\n    \"EEE\",\n    \" E \"\n  ],\n  \"key\": {\n    \"E\": {\n      \"item\": \"refinedstorage:quartz_enriched_iron\"\n    },\n    \"P\": {\n      \"item\": \"refinedstorage:basic_processor\"\n    }\n  },\n  \"result\": {\n    \"item\": \"refinedstorage:wrench\"\n  }\n}"
  },
  {
    "path": "src/main/resources/data/refinedstorage/tags/items/crafting_tables.json",
    "content": "{\n  \"replace\": false,\n  \"values\": [\n    \"minecraft:crafting_table\"\n  ]\n}"
  },
  {
    "path": "src/main/resources/pack.mcmeta",
    "content": "{\n  \"pack\": {\n    \"description\": {\n      \"text\": \"Refined Storage resources\"\n    },\n    \"pack_format\": 18\n  }\n}\n"
  },
  {
    "path": "tools/missing-translation-keys.sh",
    "content": "# usage: missing-translation-keys.sh nl_nl\n\nif [ $# -ne 1 ]; then\n    echo \"missing language to compare with\"\n    exit\nfi\n\nfilename=src/main/resources/assets/refinedstorage/lang/$1.lang\n\nif [ ! -f $filename ]; then\n    echo \"$filename not found\"\n    exit\nfi\n\nBASE_LANG=\"en_us\"\n\ncat src/main/resources/assets/refinedstorage/lang/$BASE_LANG.lang | cut -d \"=\" -f 1 > a.lang\ncat $filename | cut -d \"=\" -f 1 > b.lang\n\ndiff -s -y a.lang b.lang\n\nrm a.lang b.lang\n"
  }
]